fix: resolved race loading issues with dataloader (#2117)

This commit is contained in:
Wyatt Johnson
2018-12-12 20:54:43 +00:00
committed by Kiwi
parent 4584c3d4fb
commit 8a64e6f62d
4 changed files with 51 additions and 9 deletions
@@ -20,6 +20,9 @@ import {
retrieveManyComments,
} from "talk-server/models/comment";
import { Connection } from "talk-server/models/connection";
import { retrieveSharedModerationQueueQueuesCounts } from "talk-server/models/story/counts/shared";
import { SingletonResolver } from "./util";
/**
* primeCommentsFromConnection will prime a given context with the comments
@@ -114,4 +117,11 @@ export default (ctx: Context) => ({
// The cursor passed here is always going to be a number.
before: before as number,
}).then(primeCommentsFromConnection(ctx)),
sharedModerationQueueQueuesCounts: new SingletonResolver(() =>
retrieveSharedModerationQueueQueuesCounts(
ctx.mongo,
ctx.redis,
ctx.tenant.id
)
),
});
@@ -11,8 +11,18 @@ import { findOrCreate } from "talk-server/services/stories";
import { scraper } from "talk-server/services/stories/scraper";
export default (ctx: TenantContext) => ({
findOrCreate: (input: FindOrCreateStoryInput) =>
findOrCreate(ctx.mongo, ctx.tenant, input, ctx.queue.scraper),
findOrCreate: new DataLoader(
(inputs: FindOrCreateStoryInput[]) =>
Promise.all(
inputs.map(input =>
findOrCreate(ctx.mongo, ctx.tenant, input, ctx.queue.scraper)
)
),
{
// TODO: (wyattjoh) see if there's something we can do to improve the cache key
cacheKeyFn: (input: FindOrCreateStoryInput) => `${input.id}:${input.url}`,
}
),
story: new DataLoader<string, Story | null>(ids =>
retrieveManyStories(ctx.mongo, ctx.tenant.id, ids)
),
@@ -0,0 +1,26 @@
/**
* SingletonResolver is a cached loader for a single result.
*/
export class SingletonResolver<T> {
private cache: Promise<T> | null = null;
private resolver: () => Promise<T>;
constructor(resolver: () => Promise<T>) {
this.resolver = resolver;
}
public load() {
if (this.cache) {
return this.cache;
}
const promise = this.resolver().then(result => {
return result;
});
// Set the promise on the cache.
this.cache = promise;
return promise;
}
}
@@ -1,9 +1,9 @@
import { GQLQueryTypeResolver } from "talk-server/graph/tenant/schema/__generated__/types";
import { retrieveSharedModerationQueueQueuesCounts } from "talk-server/models/story";
import { ModerationQueuesInput } from "./ModerationQueues";
export const Query: GQLQueryTypeResolver<void> = {
story: (source, args, ctx) => ctx.loaders.Stories.findOrCreate(args),
story: (source, args, ctx) => ctx.loaders.Stories.findOrCreate.load(args),
comment: (source, { id }, ctx) =>
id ? ctx.loaders.Comments.comment.load(id) : null,
comments: (source, args, ctx) => ctx.loaders.Comments.forFilter(args),
@@ -21,10 +21,6 @@ export const Query: GQLQueryTypeResolver<void> = {
// We don't need to filter the connection, as this is tenant wide (tenant
// filtering is completed at the model layer).
connection: {},
counts: await retrieveSharedModerationQueueQueuesCounts(
ctx.mongo,
ctx.redis,
ctx.tenant.id
),
counts: await ctx.loaders.Comments.sharedModerationQueueQueuesCounts.load(),
}),
};