I have integrated DataLoaders into my graphQL requests, but for some reason the cache is memoized across requests. I can read that passing a function to context in the ApolloServer config should create a new context on each request, but for some reason the DataLoaders are memoized even then.
This is my code
Apollo Config:
export default new ApolloServer({
resolvers,
typeDefs,
context: ({ req, res }) => generateContext(req, res)
});
generateContext:
const generateContext = (req: Express.Request, res: Express.Response) => ({
...generateLoaders(),
res,
req
});
generateLoaders:
import * as questionLoaders from './questionLoaders';
const generateLoaders = () => ({
questionLoaders
});
questionLoader:
const batchQuestions = async (ids: number[]) => {
const questions = await Question.query().findByIds(ids);
return ids.map((id) => questions.find((q) => q.id === id));
};
export const questionLoader = new dataloader((ids: number[]) => batchQuestions(ids));
You only call the DataLoader
constructor once and then export the resulting DataLoader instance as a constant. Even though your context function is called on each request, it uses the imported value, which is always the same DataLoader instance. Change your export so that it is a function:
export const createQuestionLoader = () => new dataloader((ids: number[]) => batchQuestions(ids));
You can then import it and call the function inside context
:
import { createQuestionLoader } from '...'
const generateContext = (req: Express.Request, res: Express.Response) => ({
QuestionLoader: createQuestionLoader(),
res,
req
});