Repository navigation
fix(graphql-server): resolve hosts in the resolver schema routing_planes() names - #1932
Conversation
… routing_planes() names
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
Review complete. 🟡 1 medium 💬 Inline comments (1)
The change replaces the previous hardcoded own-plane-first lookup in
Reviewed commit: 65ada1f |
There was a problem hiding this comment.
This PR reworks multi-tenant route resolution in the GraphQL server middleware so host lookup runs across routing planes sourced from the function_resolution.routing_planes() table, with matching test coverage added.
Key findings
- 🟡 Own
routing_publicplane now resolved only ifrouting_planes()lists it — routing.ts:212
| const planes = await loadRoutingPlanes(pool); | ||
| const own = planes.find((plane) => plane.schema === ROUTING_SCHEMA); | ||
| if (own) { | ||
| const route = await resolveRoute(pool, own.resolverSchema, host); | ||
| if (route) return { route, planeDatabaseId: null }; | ||
| } |
There was a problem hiding this comment.
🟡 bug · medium
Own routing_public plane now resolved only if routing_planes() lists it
resolveRouteAcrossPlanes now resolves the server's own plane only when function_resolution.routing_planes() returns a row with schema === ROUTING_SCHEMA, and runs loadRoutingPlanes before any own-plane attempt (graphql/server/src/middleware/routing.ts:212-217). Previously resolveRoute(pool, ROUTING_SCHEMA, host) ran unconditionally first, so tenant-plane listing errors or incomplete registrations could not affect hosts owned by the server's own plane. Now a missing own-plane row silently skips own resolution (hosts fall through to tenant planes or 404), an incomplete tenant row throws ROUTING_PLANE_INCOMPLETE before own hosts are tried, and a failure of the routing_planes() query itself turns previously successful routing_public matches into errors.
📋 Prompt for AI Agents
In graphql/server/src/middleware/routing.ts in resolveRouteAcrossPlanes (around lines 208-229), restore the pre-change ordering: call resolveRoute(pool, ROUTING_SCHEMA, host) unconditionally first and return its match with planeDatabaseId: null before calling loadRoutingPlanes. In the tenant loop, skip planes whose schema === ROUTING_SCHEMA by value instead of relying on the own reference. This keeps the server's own plane resolving its hosts even when routing_planes() omits the platform registration, contains an incomplete tenant row, or errors.
This comment has been minimized.
This comment has been minimized.
…_name) and register the server's own routing_public plane
Summary
The server used to call
"routing_public".resolve_route(...)directly, and called each tenant plane's resolver in that plane's API schema. Now it reads the resolver's schema from the database (function_resolution.routing_planes()→resolver_schema_name), so the resolver can live in a different schema from the plane's API schema without any server change.loadDatabaseRoutingPlanes→loadRoutingPlanesreturns every plane as{ databaseId, schema, resolverSchema, resolver }.resolveRouteAcrossPlanestakes the server's own plane from that list (schema === ROUTING_SCHEMA), resolves on it first, then on the tenant planes, always viaquoteQualifiedIdentifier(plane.resolverSchema, plane.resolver). Nothing falls back torouting_public.ROUTING_PLANE_INCOMPLETE.pgpm.jsonpins@pgpm/*to0.47.7, the first release whoserouting_planes()returnsresolver_schema_name. The sharedscopedseed and thetenant-routing-planesseed now register the server's ownrouting_publicplane with aroute_modulerow, the same way real deployments do. Without that row the server has no own plane to resolve on.Tests:
routing.test.tscovers a tenant-plane call through its resolver schema and the missing-resolver-schema throw.graphql/serverpasses 260/260 andgraphql/server-test232/232 locally.Rollout coupling
resolver_schema_nameto a schema other than the API schema. The current published modules return the same schema for both, so this PR works against them as-is.resolver_schema_nameand keeps callingrouting_public.resolve_route.Link to Devin session: https://app.devin.ai/sessions/ea7371d8dbc441c49cb46e16d1d97517
Open in Devin Desktop: https://app.devin.ai/desktop/session/ea7371d8dbc441c49cb46e16d1d97517?variant=devin
Requested by: @pyramation