Skip to content

Commit

Permalink
Merge pull request #211 from pieh/parallel-queries-overwrites
Browse files Browse the repository at this point in the history
fix: scope locale context to current query and not reuse globally
  • Loading branch information
stefanoverna authored Jan 11, 2023
2 parents ff0b5f1 + 2462344 commit 2f73b0f
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 26 deletions.
18 changes: 6 additions & 12 deletions src/hooks/createResolvers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,16 @@ module.exports = (
fallbackLocales: { type: '[String!]' },
},
resolve: async (parent, args, context, info) => {
if (context.sourceDatocms.localeState) {
context.sourceDatocms.localeState.clear(info);
}
if (context.sourceDatocms.fallbackLocales) {
context.sourceDatocms.fallbackLocales.clear(info);
}

if (args.locale) {
context.sourceDatocms.localeState.set(info, args.locale);
sourceDatocms
.getQueryContext(context)
.localeState.set(info, args.locale);
}

if (args.fallbackLocales) {
context.sourceDatocms.fallbackLocalesState.set(
info,
args.fallbackLocales,
);
context.sourceDatocms
.getQueryContext(context)
.fallbackLocalesState.set(info, args.fallbackLocales);
}

const { locale, fallbackLocales, ...argsWithoutLocale } = args;
Expand Down
18 changes: 14 additions & 4 deletions src/hooks/createSchemaCustomization/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,20 @@ module.exports = async (
logApiCalls,
},
) => {
const localeState = new CascadedContext({ reporter });
const fallbackLocalesState = new CascadedContext({ reporter });

actions.createResolverContext({ localeState, fallbackLocalesState });
const statePerQuery = new WeakMap();
actions.createResolverContext({
getQueryContext: key => {
let queryState = statePerQuery.get(key);
if (!queryState) {
queryState = {
localeState: new CascadedContext({ reporter }),
fallbackLocalesState: new CascadedContext({ reporter }),
};
statePerQuery.set(key, queryState);
}
return queryState;
},
});

if (!apiToken) {
const errorText = `API token must be provided!`;
Expand Down
25 changes: 19 additions & 6 deletions src/hooks/sourceNodes/createTypes/item/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,39 @@ const { seoTagsBuilder, JsonApiEntity } = require('datocms-client');

function getI18n(args, context, info, mainLocale) {
if (args.locale) {
context.sourceDatocms.localeState.set(info, args.locale);
context.sourceDatocms
.getQueryContext(context)
.localeState.set(info, args.locale);
}

if (args.fallbackLocales) {
context.sourceDatocms.fallbackLocalesState.set(info, args.fallbackLocales);
context.sourceDatocms
.getQueryContext(context)
.fallbackLocalesState.set(info, args.fallbackLocales);
}

const locale = context.sourceDatocms.localeState.get(info) || mainLocale;
const locale =
context.sourceDatocms.getQueryContext(context).localeState.get(info) ||
mainLocale;

return {
locale,
fallbacks: {
[locale]: context.sourceDatocms.fallbackLocalesState.get(info) || [],
[locale]:
context.sourceDatocms
.getQueryContext(context)
.fallbackLocalesState.get(info) || [],
},
};
}

function getAllLocalesI18n(node, args, context, info) {
context.sourceDatocms.localeState.set(info, node.locale);
context.sourceDatocms.fallbackLocalesState.set(info, []);
context.sourceDatocms
.getQueryContext(context)
.localeState.set(info, node.locale);
context.sourceDatocms
.getQueryContext(context)
.fallbackLocalesState.set(info, []);

return {
locale: node.locale,
Expand Down
17 changes: 13 additions & 4 deletions src/hooks/sourceNodes/createTypes/site/DatoCmsSite.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,28 @@ const { localizedRead } = require('datocms-client');

function getI18n(args, context, info, mainLocale) {
if (args.locale) {
context.sourceDatocms.localeState.set(info, args.locale);
context.sourceDatocms
.getQueryContext(context)
.localeState.set(info, args.locale);
}

if (args.fallbackLocales) {
context.sourceDatocms.fallbackLocalesState.set(info, args.fallbackLocales);
context.sourceDatocms
.getQueryContext(context)
.fallbackLocalesState.set(info, args.fallbackLocales);
}

const locale = context.sourceDatocms.localeState.get(info) || mainLocale;
const locale =
context.sourceDatocms.getQueryContext(context).localeState.get(info) ||
mainLocale;

return {
locale,
fallbacks: {
[locale]: context.sourceDatocms.fallbackLocalesState.get(info) || [],
[locale]:
context.sourceDatocms
.getQueryContext(context)
.fallbackLocalesState.get(info) || [],
},
};
}
Expand Down
47 changes: 47 additions & 0 deletions test/graphql.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,53 @@ test('items', async () => {
expect(result).toMatchSnapshot();
});

test('items (parallel)', async () => {
const getQuery = locale => /* GraphQL */ `
{
article: datoCmsArticle(originalId: {eq: "7364344"}, locale: "${locale}") {
__typename
originalId
id
locales
singleLineString
singleLink {
id
singleLineString
}
multipleLinks {
id
singleLineString
}
advancedMultipleLinks {
__typename
... on DatoCmsArticle {
singleLineString
}
... on DatoCmsSecondaryModel {
title
}
}
}
allDatoCmsOptionalLocalesModel(locale: "it", fallbackLocales: ["en"]) {
nodes {
originalId
title
boolean
}
}
}
`;

const [result1, result2] = await Promise.all([
executeQuery(getQuery(`en`)),
executeQuery(getQuery(`it`)),
]);

// we compare results of queries running in parallel to results of queries running one by one
expect(await executeQuery(getQuery(`en`))).toEqual(result1);
expect(await executeQuery(getQuery(`it`))).toEqual(result2);
});

test('structured text', async () => {
const query = /* GraphQL */ `
{
Expand Down

0 comments on commit 2f73b0f

Please sign in to comment.