-
Notifications
You must be signed in to change notification settings - Fork 458
Open
Labels
Milestone
Description
Summary
The OPA (Open Policy Agent) plugin uses synchronous requests.post() which blocks the async event loop during policy evaluation.
Problem
File: plugins/external/opa/opapluginfilter/plugin.py (line 152)
import requests
# Current pattern - blocks async event loop
response = requests.post(opa_url, json=input_data)When the OPA plugin is enabled and evaluates policies, each policy check blocks the entire async worker until the HTTP request completes. This can cause:
- Increased latency for all concurrent requests
- Reduced throughput under load
- Event loop starvation with slow OPA servers
Proposed Solution
Replace synchronous requests with the shared async httpx client:
from mcpgateway.services.http_client_service import get_http_client
# Async pattern - non-blocking
client = await get_http_client()
response = await client.post(opa_url, json=input_data)Or if the plugin hook is synchronous, use httpx.Client with connection pooling:
import httpx
# If sync context is required, at minimum use pooled client
# Initialize once in plugin __init__
self._http_client = httpx.Client(
limits=httpx.Limits(max_connections=100, max_keepalive_connections=20)
)
# Reuse in policy checks
response = self._http_client.post(opa_url, json=input_data)Impact
- Performance: Eliminates event loop blocking during OPA policy evaluation
- Throughput: Allows concurrent request processing while waiting for OPA
- Consistency: Aligns with async patterns used throughout the gateway
Acceptance Criteria
- Replace
requests.post()with async httpx or pooled sync client - Ensure proper client lifecycle management (shutdown cleanup)
- Add timeout configuration for OPA requests
- Update plugin tests
References
mcpgateway/services/http_client_service.py- Shared async client patterntodo/pooling-optimizations.md- Full optimization analysis