Full Schema Stitching with Apollo Server

转自: https://tomasalabes.me/blog/nodejs/graphql/apollo/2018/09/18/schema-stitiching-apollo.html

Full Schema Stitching with Apollo Server

In this post we will see how we can stitch the queries/mutations and subscriptions from an Apollo Server and its Links packages. Plus a few tips to make it more interesting ;)

Our Goal

Our goal is creating a single apollo-link that will let Apollo stitch all requests going to the server and send them to the right downstream server.

 

apollo-stitchingapollo-stitching

 

Once we have the function that creates the link, the overall code should look something like this:

import { introspectSchema, makeRemoteExecutableSchema, mergeSchemas } from 'graphql-tools';

export const createSchema = async () => {
    const { link } = createLink(); // -> this is the method that we will create

    const introspectedSchema = await introspectSchema(link);
    const schema = makeRemoteExecutableSchema({
        link,
        schema: introspectedSchema
    });

    return mergeSchemas({
        schemas: [
            schema
            // more schemas
        ]
    });
};

Ok, let’s stitch!

This one is pretty straight forward, apollo-link-http redirects http/s queries to the provided URL. I use node-fetchwhich is the recommended fetch package for Node.

import { HttpLink } from 'apollo-link-http';
import fetch from 'node-fetch';

const createHttpLink = (gqlServerUrl) => {
    const uri = `http://${gqlServerUrl}/graphql`;
    return new HttpLink({
        fetch,
        uri
    });
};

Now subscriptions. We need to use apollo-link-ws It’s similar to the http-link except we need to first create a SubscriptionClient where we pass the urloptions and the websockets node implementation. In the previous link we passed the fetch implementation, now is the websocket’s one.

import WebSocket from 'ws';
import { WebSocketLink } from 'apollo-link-ws';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import { WebSocketLink } from 'apollo-link-ws';

const createWsLink = (gqlServerUrl) => {
    const wsUri = `ws://${gqlServerUrl}/subscriptions`;
    const wsClient = new SubscriptionClient(
        wsUri,
        {
            reconnect: true // if connection is lost, retry
        },
        WebSocket
    );

    return new WebSocketLink(wsClient);
};

All options for the SubscriptionClient are here.

This is where we add the “magic”. We will use the above 2 links, with a split and retry strategies.

We will:

  1. Create the HTTP and WS links
  2. Using split, depending on the requested operation we will evaluate what link is needed
  3. Using RetryLink, we will check if there was an error connecting to the server, and retry the connection if necessary
import { RetryLink } from 'apollo-link-retry';
import { getMainDefinition } from 'apollo-utilities';

const createLink = () => {
    const projectGqlServer = `your-gql-server:3000`;
    const httpLink = createHttpLink(projectGqlServer);
    const wsLink = createWsLink(projectGqlServer);

    const link = new RetryLink({
        // these are the defaults, change them as you will
        delay: {
            initial: 300, // The number of milliseconds to wait before attempting the first retry.
            max: Infinity, // The maximum number of milliseconds that the link should wait for any retry
            jitter: true // Whether delays between attempts should be randomized.
        },
        attempts: {
            max: 5, // The max number of times to try a single operation before giving up.
            retryIf: (error, _operation) => !!error // A predicate function that can determine whether a particular response should be retried.
        }
    }).split( // using "Directional Composition" of links
        ({ query }) => {
            const { kind, operation } = getMainDefinition(query);
            return kind === 'OperationDefinition' && operation === 'subscription';
        },
        wsLink,
        httpLink
    );
    return { link };
};

Conclusion

With this you should be able to route all types of operations received by this server to the remote server.

There’re other strategies using other link packages but I haven’t tried them, as some I think don’t apply to the server but to the client. But I think this gives you the base for the stitching, from here you can take it to where you need it.

As always, hope it helps! And share if it does!

Cheers!

posted on   荣锋亮  阅读(387)  评论(0编辑  收藏  举报

编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2018-01-19 sailsjs 不用写代码就能生成rest api 代码

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示