UNPKG

pg-transactional-outbox

Version:

A PostgreSQL based transactional outbox and inbox pattern implementation to support exactly once message processing (with at least once message delivery).

79 lines 3.87 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.initializeMessageStorage = void 0; const error_1 = require("../common/error"); /** * Initialize the message storage to store outbox or inbox messages in the corresponding table. * @param config The configuration object that defines the values on how to connect to the database and general settings. * @param logger A logger instance for logging trace up to error logs * @returns Initializes the function to store the outbox or inbox message data to the database and provides the shutdown action. */ const initializeMessageStorage = ({ settings, outboxOrInbox, }, logger) => { /** * The function to store the message data to the database. * @param message The received message that should be stored as a outbox or inbox message * @param client A database client with an active transaction(!) can be provided. Otherwise * @throws Error if the message could not be stored */ return (message, client) => __awaiter(void 0, void 0, void 0, function* () { try { yield insertMessage(message, client, settings, logger); } catch (err) { const messageError = new error_1.MessageError(`Could not store the ${outboxOrInbox} message with id ${message.id}`, 'MESSAGE_STORAGE_FAILED', message, err); logger.error(messageError, `Could not store the ${outboxOrInbox} message`); throw messageError; } }); }; exports.initializeMessageStorage = initializeMessageStorage; const insertMessage = (message_1, client_1, _a, logger_1) => __awaiter(void 0, [message_1, client_1, _a, logger_1], void 0, function* (message, client, { dbSchema, dbTable }, logger) { const { id, aggregateType, aggregateId, messageType, segment, payload, metadata, concurrency, createdAt, lockedUntil, } = message; const insertValues = [ id, aggregateType, aggregateId, messageType, segment, payload, metadata, ]; let optionalPlaceholders = ''; const addPlaceholder = () => (optionalPlaceholders += `, $${insertValues.length}`); let optionalFields = ''; const addOptionalFields = (name) => (optionalFields += `, ${name}`); if (concurrency) { insertValues.push(concurrency); addOptionalFields('concurrency'); addPlaceholder(); } if (createdAt) { insertValues.push(createdAt); addOptionalFields('created_at'); addPlaceholder(); } if (lockedUntil) { insertValues.push(lockedUntil); addOptionalFields('locked_until'); addPlaceholder(); } const messageResult = yield client.query( /* sql */ ` INSERT INTO ${dbSchema}.${dbTable} (id, aggregate_type, aggregate_id, message_type, segment, payload, metadata${optionalFields}) VALUES ($1, $2, $3, $4, $5, $6, $7${optionalPlaceholders}) ON CONFLICT (id) DO NOTHING`, insertValues); if (!messageResult.rowCount || messageResult.rowCount < 1) { logger.warn(message, `The message with id ${id} already existed`); } }); //# sourceMappingURL=initialize-message-storage.js.map