Enhanced Gateway Connection Manager#83
Enhanced Gateway Connection Manager#83JeremyWurbs wants to merge 6 commits intoservices/feature/gatewayfrom
Conversation
…anager attributes dynamically
There was a problem hiding this comment.
Pull Request Overview
This PR extends the Gateway to propagate registered app endpoints (with schema-based proxies) across all connection manager instances—both existing and newly created—by introducing a detailed schema endpoint, synthetic CMs, and a reconnect mechanism.
- Adds a
/detailed_endpointsroute andget_detailed_endpointsinServicefor full schema introspection - Refactors
ProxyConnectionManagerto generate schema-aware sync/async proxy methods and property routing - Enhances
Gateway.connect/reconnectto auto‐sync existing registrations via synthetic CMs and track manual registrations
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| mindtrace/services/mindtrace/services/core/service.py | Adds detailed_endpoints route and schema for full endpoint schemas |
| mindtrace/services/mindtrace/services/core/types.py | Introduces DetailedEndpointsSchema for the new route |
| mindtrace/services/mindtrace/services/core/utils.py | Ensures service endpoints are stored on generated CM classes |
| mindtrace/services/mindtrace/services/gateway/gateway.py | Implements list_apps[_with_schemas], enhanced register_app, connect, and reconnect |
| mindtrace/services/mindtrace/services/gateway/proxy_connection_manager.py | Refactors proxy logic to use TaskSchema, sync/async methods, and property forwarding |
| tests/unit/mindtrace/services/gateway/test_proxy_connection_manager.py | Updates and expands tests for proxy initialization, property/method routing |
| tests/unit/mindtrace/services/gateway/test_gateway.py | Adds tests for enhanced registered_apps behavior |
| tests/integration/mindtrace/services/test_gateway_integration.py | Adds end‐to‐end scenarios for multi‐CM sync, URL object support, and discovery |
Comments suppressed due to low confidence (4)
mindtrace/services/mindtrace/services/gateway/gateway.py:276
- [nitpick] Using raw
app_name(which may contain hyphens or other invalid identifier characters) as an attribute risks invalid attribute access. Consider sanitizing or normalizing names (e.g., replace '-' with '_').
setattr(base_cm, app_name, proxy_cm)
mindtrace/services/mindtrace/services/gateway/gateway.py:366
- The new
reconnectmethod is critical for syncing late registrations but lacks dedicated unit tests. Please add tests that verify attribute refresh and synthetic proxy creation on attribute access failure.
def reconnect():
mindtrace/services/mindtrace/services/gateway/gateway.py:69
- [nitpick] The
list_appsendpoint is using POST; a read-only resource may be better served by GET for consistency with RESTful conventions.
self.add_endpoint("/list_apps", func=self.list_apps, schema=ListAppsTaskSchema(), methods=["POST"])
mindtrace/services/mindtrace/services/core/utils.py:129
- This line reassigns
_service_endpointstwice in a row. You can remove the redundant assignment to keep the code concise.
ServiceConnectionManager._service_endpoints = temp_service._endpoints
| from fastapi import HTTPException | ||
|
|
There was a problem hiding this comment.
Duplicate import of HTTPException. Please remove one of the two identical imports to reduce redundancy.
| from fastapi import HTTPException |
| return service_class._endpoints | ||
|
|
||
| # Last resort: infer from methods (less reliable) | ||
| return self._infer_endpoints_from_methods(original_cm) |
There was a problem hiding this comment.
The instance‐level _service_endpoints on original_cm is never checked. If endpoints are stored on the instance rather than the class, they will be lost—consider adding elif hasattr(original_cm, '_service_endpoints') before falling back.
This PR implements and closes #82.
It enables all connection managers generated from connecting to a Gateway-derived class the ability to use registered app endpoints as attributes on the returned connection manager.
Namely,
This PR is being raise as a draft PR for now, for a few reasons, which I will be unlikely to have time to fix before next week, but would like to make this code available before then:
Implementation Details
New
Service.detailed_endpoints()methodA new
detailed_endpointsendpoint/method has been added to theServicebase class, which will return all of the endpoints with their schema information.New
Gateway._create_synthetic_connection_managerThe
Gatewayclass has a new method, similar togenerate_connection_manager, but uses the provided endpoint information from the above to create aConnectionManager. The Gateway only collects and tracks this information for apps that provide it (inself.registered_app_info).TODO: Note that in the current implementation, it is the act of providing a connection manager that triggers the tracking of the service's schemas, but actually non-
Service-derived classes may also already have said schemas (especially if we are considering it to tie in with MCP-compliance). In the future it should be possible to enable the described behavior for any FastAPI / MCP service that provides associated schemas.As this behavior is required by MCP, we may decide to simply make this endpoint match the MCP version. Refer here for a working example.
Update
Gateway.connectThe above is used in the updated
Gateway.connectmethod. The current logic is quite long, and ties in to the even-longerProxyConnectionManagerclass, which still exists.New
Gateway.reconnectThere is a new
Gateway.reconnectmethod. It might make sense to do a simpler "reconnect" call, where the original connect kwargs are stored and used again, but instead in the current implementationreconnectdoesn't attempt to do that, but rather just refreshes the endpoint information.In theory it sounded like the simpler implementation, in practice it is just as complicated as the original
connect.Catching
AttributeErrorwith areconnect+ retryConsider the following:
At this point, if you check if
echoeris an attribute on each connection manager:It would appear that the second connection manager doesn't know about
echoer, but if you reach for it, you find it's there:The main logic that makes the above possible is simply:
AttributeErrorthrown by__getattribute__, which occurs when "echoer" is not found as an attribute ingateway_cm2;reconnectonce, refreshing the connection manager attributes, ideally to now contain the updated property;Buried in the updated
connectmethod:Documentation & Testing
Unit and integration tests have been added covering the new use case, but many more tests, including the myriad of corner cases, should be added before considered complete. Tests should still all pass with ~70% coverage on the
GatewayandProxyConnectionManagerfiles.