diff --git a/src/graphql/operations/votes.ts b/src/graphql/operations/votes.ts index fcf058d2..1036abfc 100644 --- a/src/graphql/operations/votes.ts +++ b/src/graphql/operations/votes.ts @@ -1,7 +1,7 @@ import graphqlFields from 'graphql-fields'; import db from '../../helpers/mysql'; import { buildWhereQuery, checkLimits, formatProposal, formatSpace, formatVote } from '../helpers'; -import serve from '../../helpers/ee'; +import serve from '../../helpers/requestDeduplicator'; import log from '../../helpers/log'; import { capture } from '@snapshot-labs/snapshot-sentry'; diff --git a/src/helpers/ee.ts b/src/helpers/ee.ts deleted file mode 100644 index fc227a0f..00000000 --- a/src/helpers/ee.ts +++ /dev/null @@ -1,20 +0,0 @@ -import events from 'events'; -import { sha256 } from './utils'; - -const eventEmitter = new events.EventEmitter(); -eventEmitter.setMaxListeners(1000); // https://stackoverflow.com/a/26176922 - -export default async function serve(id, action, args) { - const key = sha256(id); - // eslint-disable-next-line no-async-promise-executor - return new Promise(async (resolve, reject) => { - eventEmitter.once(key, data => (data.error ? reject(data.e) : resolve(data))); - if (eventEmitter.listenerCount(key) === 1) { - try { - eventEmitter.emit(key, await action(...args)); - } catch (e) { - eventEmitter.emit(key, { error: true, e }); - } - } - }); -} diff --git a/src/helpers/requestDeduplicator.ts b/src/helpers/requestDeduplicator.ts new file mode 100644 index 00000000..55e21964 --- /dev/null +++ b/src/helpers/requestDeduplicator.ts @@ -0,0 +1,21 @@ +import { sha256 } from './utils'; + +const ongoingRequests = new Map(); + +export default async function serve(id, action, args) { + const key = sha256(id); + if (!ongoingRequests.has(key)) { + const requestPromise = action(...args) + .then(result => { + ongoingRequests.delete(key); + return result; + }) + .catch(e => { + ongoingRequests.delete(key); + throw e; + }); + ongoingRequests.set(key, requestPromise); + } + + return ongoingRequests.get(key); +}