Apollo call API which provides all of a type, reducing duplicate calls when resolving individuals

19 Views Asked by At

I am trying to abstract a 3rd party API into a graph using Apollo Server. The API provides an object called Environment which I can query like:

https://api.name.com/v1/subscriptions/{subscriptionId}/environments/{environmentId}

each environment has a list of filtersets which it provides me, in that API, as primary keys.

I can query for each filterset individually like:

https://api.name.com/v1/subscriptions/{subscriptionId}/ipfiltersets?code={code}

but this is slower than just returning all of them and filtering out the response.

In Apollo server, how can I check ahead of time that I'm going to be returning the filter sets and make this single query per subscription rather than calling it for every single environment? I've been using DataLoaders but I'm not seeing any improvement and there is still a duplicate call per environment.

My DataLoader looks like this:

import axios from 'axios';
import DataLoader from 'dataloader';

const TemplateHeaders = {
    "Content-Type" : "application/json",
    "Accept" : "application/json"
}

export class IPFilterSetDataSource {

    apiKey;

    constructor(apiKey){
        this.apiKey = apiKey;
    }

    batchIPFilterSets = new DataLoader(async (incIDs) => {
        let subscriptionId = incIDs[0].split("_")[0];
        const ids = incIDs.map((id) => id.split("_")[1]);
        const ApiOptions = {
            "headers" : {
                ...TemplateHeaders,
                "Authorization" : `Bearer ${this.apiKey}`
            }
        }
        const ipFilterSets = (await axios.get(`https://example.api.com/v1/subscriptions/${subscriptionId}/ipfiltersets`, ApiOptions)).data;
        let foundSets = ipFilterSets.filter(({code}) => ids.includes(code));
        return Promise.resolve(foundSets);
    });

    async getIpFilterSetForId(subscriptionId, id) {
        return this.batchIPFilterSets.load(`${subscriptionId}_${id}`);
    }
}

And I call it from my resolver like this:

Environment: {
        ipFilteringSets: async (parent, __, {subscriptionCode, dataSources}) => {
            return parent.ipFilteringSets.map(s => dataSources.ipFilterSet.getIpFilterSetForId(subscriptionCode, s));
        }
    }

But it's still calling the main API multiple times

0

There are 0 best solutions below