UNPKG

6.57 kBSource Map (JSON)View Raw
1{"version":3,"file":"deduplicate.js","sourceRoot":"","sources":["deduplicate.ts"],"names":[],"mappings":"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","sourcesContent":["import { create as createLogger } from '../common/log'\nimport { createHash } from 'crypto'\nimport * as IlpPacket from 'ilp-packet'\nimport { Middleware, MiddlewareCallback, MiddlewareServices, Pipelines } from '../types/middleware'\nimport { AccountInfo } from '../types/accounts'\nimport BigNumber from 'bignumber.js'\n\n// Where in the ILP packet does the static data begin (i.e. the data that is not modified hop-to-hop)\nconst STATIC_DATA_OFFSET = 25 // 8 byte amount + 17 byte expiry date\n\nconst DEFAULT_CLEANUP_INTERVAL = 30000\nconst DEFAULT_PACKET_LIFETIME = 30000\n\ninterface CachedPacket {\n amount: string,\n expiresAt: Date,\n promise: Promise<Buffer>\n}\n\nexport default class DeduplicateMiddleware implements Middleware {\n private packetCache: Map<string, CachedPacket> = new Map()\n private getInfo: (accountId: string) => AccountInfo\n\n constructor (opts: {}, { getInfo }: MiddlewareServices) {\n this.getInfo = getInfo\n }\n\n async applyToPipelines (pipelines: Pipelines, accountId: string) {\n const log = createLogger(`deduplicate-middleware[${accountId}]`)\n const accountInfo = this.getInfo(accountId)\n if (!accountInfo) {\n throw new Error('account info unavailable. accountId=' + accountId)\n }\n\n const {\n cleanupInterval,\n packetLifetime\n } = accountInfo.deduplicate || {\n cleanupInterval: DEFAULT_CLEANUP_INTERVAL,\n packetLifetime: DEFAULT_PACKET_LIFETIME\n }\n\n let interval: NodeJS.Timer\n pipelines.startup.insertLast({\n name: 'deduplicate',\n method: async (dummy: void, next: MiddlewareCallback<void, void>) => {\n interval = setInterval(() => this.cleanupCache(packetLifetime), cleanupInterval)\n return next(dummy)\n }\n })\n\n pipelines.teardown.insertLast({\n name: 'deduplicate',\n method: async (dummy: void, next: MiddlewareCallback<void, void>) => {\n clearInterval(interval)\n return next(dummy)\n }\n })\n\n pipelines.outgoingData.insertLast({\n name: 'deduplicate',\n method: async (data: Buffer, next: MiddlewareCallback<Buffer, Buffer>) => {\n if (data[0] === IlpPacket.Type.TYPE_ILP_PREPARE) {\n const { contents } = IlpPacket.deserializeEnvelope(data)\n\n const index = createHash('sha256')\n .update(contents.slice(STATIC_DATA_OFFSET))\n .digest()\n .slice(0, 16) // 128 bits is enough and saves some memory\n .toString('base64')\n\n const { amount, expiresAt } = IlpPacket.deserializeIlpPrepare(data)\n\n const cachedPacket = this.packetCache.get(index)\n if (cachedPacket) {\n // We have seen this packet before, let's check if previous amount and expiresAt were larger\n if (new BigNumber(cachedPacket.amount).gte(amount) && cachedPacket.expiresAt >= expiresAt) {\n log.warn('deduplicate packet cache hit. accountId=%s elapsed=%s amount=%s', accountId, cachedPacket.expiresAt.getTime() - Date.now(), amount)\n return cachedPacket.promise\n }\n }\n\n const promise = next(data)\n\n this.packetCache.set(index, {\n amount,\n expiresAt,\n promise\n })\n\n return promise\n }\n\n return next(data)\n }\n })\n }\n\n private cleanupCache (packetLifetime: number) {\n const now = Date.now()\n for (const index of this.packetCache.keys()) {\n const cachedPacket = this.packetCache.get(index)\n if (!cachedPacket) continue\n const packetExpiry = cachedPacket.expiresAt.getTime() + packetLifetime\n if (packetExpiry < now) {\n this.packetCache.delete(index)\n }\n }\n }\n}\n"]}
\No newline at end of file