it’s not unusual that there are cases we have new graphql servers to be added, or existing graphql servers updated.
Apollo server at the moment, have a gateway component which could statically maintain and route the right traffic to the right server and aggregate results.
However, this community version of Apollo server and gateway is not able to cater for the case in the beginning, where we would like to hot update/reload the gateway with any updates however with shut down the servers.
After some trials and errors, this is the work around to sort this out:
instead of hardcode the service list (apollo graphql servers), maintain it separately and dynamically:
#### instead of this const gateway = new ApolloGateway({ serviceList: [ { name: "astronauts", url: "http://localhost:4002" }, { name: "missions", url: "http://localhost:4003" } ] }); ## maintain this list #### instead of this const dynamicServiceList = [ { name: "astronauts", url: "http://localhost:4002" }, { name: "missions", url: "http://localhost:4003" } ];
then from apollo gateway, instead of spoon feeding the list, switch it to dynamically load the definitions
const gateway = new ApolloGateway({ serviceList: [], ... experimental_updateServiceDefinitions: async (serviceList) => { return { isNewSchema: true, serviceDefinitions: await Promise.all(dynamicServiceList.map(async (service) => { //load the sql const data = await request(service.url, sdlGQL); ... return { ... //then feed the data here name: service.name, url: service.url, typeDefs: parse(data._service.sdl) }; })) }; } });
At the same time, create a new endpoint, if needed, to take in updated servers, or new servers, so that to update the dynamic list
app.get('/hot_reload_schema/', async (req, res) => { //get the new server info from req .... const status = await validateSDL(name, url); if (status){ //update the dynamic list dynamicServiceList.push({name, url}); res.send('The new schema has been successfully registered'); } else { res.send('Please check the log for the error details while registering this schema'); } } );
lastly, make sure the gateway is polling the service list at some intervals:
new ApolloGateway({ pollingTimer: 100_000, experimental_pollInterval: 100_000, .... });
alternatively, this could also be updated by an explicit load:
new ApolloGateway({ .... }).load();
have contributed the solution to the community here.
Published
Originally published at https://lwpro2.dev on July 27, 2020.