The wrapper inefficiently takes 2.5s for each query by repeatedly calling makePromise
After trying out your library we discovered that your call to makePromise is highly inefficient since it takes 2.5s for each query. It gets especially since it takes multiples of 2.5s for each sub-query.
https://github.com/poetic/apollo-datasource-graphql/blob/1fe3bbd6872dc9d239d88ba3d4ed141cee8e9d9c/src/GraphQLDataSource.ts#L66
You should create a single client that you persist through multiple calls to the very same endpoint. That's why we moved to a custom wrapper that create such a single client.
@ChristianIvicevic Could you opensource or gist your custom wrapper?
We just ended up with two things. First of all our small custom GraphQLDataSource class:
import ApolloClient, {QueryOptions} from 'apollo-boost';
import fetch from 'node-fetch';
export abstract class GraphQLDataSource {
protected client: ApolloClient<unknown>;
protected constructor(uri?: string) {
this.client = new ApolloClient({
uri,
fetch: (fetch as unknown) as GlobalFetch['fetch'],
headers: {
'Cache-Control': 'no-cache'
}
});
}
protected query<TResponse, TVariables>(options: QueryOptions<TVariables>) {
return this.client.query<TResponse, TVariables>(options);
}
}
The datasources look as follows:
export class MasterDataGraphQLApi extends GraphQLDataSource {
public constructor() {
super(process.env.MASTER_DATA_GQL_ENDPOINT);
}
public async getProjects(offset: number, first: number) {
try {
const response = await this.query<ProjectsQuery, ProjectsQueryVariables>({
query: GET_PROJECTS,
variables: {offset, first}
});
return response.data.projects.page;
} catch (error) {
console.error(error);
}
}
// ...
}
Furthermore when injecting the datasources keep in mind to use the same instances and not creating them with each call:
import {ApolloServer, IResolvers} from 'apollo-server-express';
const masterDataApi = new MasterDataGraphQLApi();
const dataQueryApi = new DataQueryGraphQLApi();
const dataSources = () => ({
masterDataApi,
dataQueryApi,
});
const server = new ApolloServer({
typeDefs: schema,
resolvers: (resolvers as unknown) as IResolvers,
dataSources: dataSources as <T extends object>() => Record<string, T>,
});