UNPKG

@message-queue-toolkit/core

Version:

Useful utilities, interfaces and base classes for message queue handling. Supports AMQP and SQS with a common abstraction on top currently

110 lines 4.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HandlerSpy = void 0; exports.isHandlerSpy = isHandlerSpy; exports.resolveHandlerSpy = resolveHandlerSpy; const node_crypto_1 = require("node:crypto"); const node_core_1 = require("@lokalise/node-core"); const toad_cache_1 = require("toad-cache"); const matchUtils_1 = require("../utils/matchUtils"); function isHandlerSpy(value) { return ((0, node_core_1.isObject)(value) && (value instanceof HandlerSpy || value.name === 'HandlerSpy')); } class HandlerSpy { name = 'HandlerSpy'; // biome-ignore lint/suspicious/noExplicitAny: This is expected messageBuffer; messageIdField; messageTypeField; spyPromises; constructor(params = {}) { this.messageBuffer = new toad_cache_1.Fifo(params.bufferSize ?? 100); // @ts-ignore this.messageIdField = params.messageIdField ?? 'id'; // @ts-ignore this.messageTypeField = params.messageTypeField ?? 'type'; this.spyPromises = []; } messageMatchesFilter(spyResult, fields, status) { return ((0, matchUtils_1.objectMatches)(fields, spyResult.message) && (!status || spyResult.processingResult.status === status)); } waitForMessageWithId(id, status) { return this.waitForMessage( // @ts-expect-error { [this.messageIdField]: id }, status); } checkForMessage(expectedFields, status) { return Object.values(this.messageBuffer.items).find((spyResult) => { return this.messageMatchesFilter(spyResult.value, expectedFields, status); })?.value; } waitForMessage(expectedFields, status) { const processedMessageEntry = this.checkForMessage(expectedFields, status); if (processedMessageEntry) { return Promise.resolve(processedMessageEntry); } let resolve; const spyPromise = new Promise((_resolve) => { resolve = _resolve; }); this.spyPromises.push({ promise: spyPromise, status, fields: expectedFields, // @ts-ignore resolve, }); // @ts-ignore return spyPromise; } clear() { this.messageBuffer.clear(); } addProcessedMessage(processingResult, messageId) { const resolvedMessageId = processingResult.message?.[this.messageIdField] ?? messageId ?? (0, node_crypto_1.randomUUID)(); const resolvedMessageType = processingResult.message?.[this.messageTypeField] ?? 'FAILED_TO_RESOLVE'; // If we failed to parse message, let's store id and type at least const resolvedProcessingResult = processingResult.message ? processingResult : { ...processingResult, message: { [this.messageIdField]: messageId, [this.messageTypeField]: resolvedMessageType, }, }; // @ts-ignore const cacheId = `${resolvedMessageId}-${Date.now()}-${(Math.random() + 1) .toString(36) .substring(7)}`; this.messageBuffer.set(cacheId, resolvedProcessingResult); const foundPromise = this.spyPromises.find((spyPromise) => { return this.messageMatchesFilter(resolvedProcessingResult, spyPromise.fields, spyPromise.status); }); if (foundPromise) { // eslint-disable-next-line @typescript-eslint/no-unsafe-call foundPromise.resolve(processingResult); const index = this.spyPromises.indexOf(foundPromise); if (index > -1) { // only splice array when item is found this.spyPromises.splice(index, 1); // 2nd parameter means remove one item only } } } } exports.HandlerSpy = HandlerSpy; function resolveHandlerSpy(queueOptions) { if (isHandlerSpy(queueOptions.handlerSpy)) { return queueOptions.handlerSpy; } if (!queueOptions.handlerSpy) { return undefined; } if (queueOptions.handlerSpy === true) { return new HandlerSpy(); } return new HandlerSpy(queueOptions.handlerSpy); } //# sourceMappingURL=HandlerSpy.js.map