graphql-schema-registry icon indicating copy to clipboard operation
graphql-schema-registry copied to clipboard

Add supergraph endpoint

Open agologan opened this issue 1 year ago • 4 comments

Problem

In order to use Apollo Router #162 one needs a composed supergraph to provide to it. While this can be done using Rover CLI or via @apollo/composition it's not very easy to do it and may require an extra infrastructure component.

Changes

New /schema/supegraph that can be passed directly to the router. Endpoint is cached in memory (without other deps), and is invalidated on subgraph changes.

Example Helm values for Apollo Router:

router:
  args:
    - --hot-reload
    - -s
    - /tmp/supergraph.graphql
extraContainers:
  - name: update-graph
    image: quay.io/curl/curl:8.4.0
    command: ["watch"]
    args: ["-n", "60", "curl", "-v", "http://graphql-schema-registry/schema/supergraph", "-o", "/tmp/supergraph.graphql"]
    volumeMounts:
    - name: schema
      mountPath: /tmp/
extraVolumes:
  - name: schema
    emptyDir: {}
extraVolumeMounts:
  - name: schema
    mountPath: /tmp/
    readOnly: true

agologan avatar Oct 31 '23 14:10 agologan

hey @agologan . Thanks for the effort. How is supergraph different from GET /schema/latest ? Is it because of text/plain.. or different format? Also, some tests would be nice

tot-ra avatar Dec 04 '23 13:12 tot-ra

router.get('/schema/latest', asyncWrap(schema.composeLatest));
export async function composeLatest(req, res) {
	const schema = await getAndValidateSchema(connection, false, false);

	return res.json({
		success: true,
		data: schema,
	});
}

At a quick glance it just returns the schema wrapper in JSON object, but looking further..

export async function getAndValidateSchema(
	trx,
	services = false,
	validate = true
) {
	const schemas = services
		? await schemaModel.getSchemaByServiceVersions({ trx, services })
		: await schemaModel.getLastUpdatedForActiveServices({ trx });

	logger.info(
		'Validating schema. Got services schemas from DB transaction..',
		{
			schemas,
		}
	);

	if (validate && schemas && schemas.length) {
		federationHelper.composeAndValidateSchema(schemas);
	}

	return schemas;
}

So getAndValidateSchema composes the schema for validation but throws away the composition (supergraph) and in turns returns a list of schemas.

Put together GET /schema/latest returns a json object indicating composition success and the list of schemas that would make up the supergraph. One can also see this in the examples where the gateway needs to compose the graph i.e. https://github.com/tot-ra/graphql-schema-registry/blob/master/examples/gateway_service_hard_coded_urls/supergraph.js#L88

By comparison, the new endpoint composes, caches and returns the supergraph to be used directly in a gateway or router.

In case of Apollo Router it does not do it's own composition as seen here https://www.apollographql.com/docs/router/migrating-from-gateway#servicelist--introspectandcompose So if one wanted to use it they'd either have to add another infrastructure component to do the composition or have the registry do it since it already runs that code but it throws away the result.

agologan avatar Dec 14 '23 12:12 agologan

please add tests and examples of how its used

tot-ra avatar Dec 30 '23 23:12 tot-ra

Added a sanity test to schema.itest.ts to ensure composition works. Added new tests to router/index.itest.ts using supertest which call via express router testing the caching layer as well.

LE: Provided a working compose example and updated the examples docs. See: 34ab51a69daaea940cf5df421eaabb803319a766

agologan avatar Mar 13 '24 23:03 agologan