UNPKG

@arturwojnar/hermes-postgresql

Version:

Production-Ready TypeScript Outbox Pattern for PostgreSQL

67 lines 2.3 kB
import { Duration } from '@arturwojnar/hermes'; import { EventEmitter } from 'events'; class TransactionManager extends EventEmitter { publish; currentTransaction; lastAcknowledgedLsn; isProcessing = false; processingTimeout; constructor(publish, initialLsn, processingTimeout = Duration.ofSeconds(30)) { super(); this.publish = publish; this.lastAcknowledgedLsn = initialLsn; this.processingTimeout = processingTimeout; } beginTransaction(transaction) { if (this.currentTransaction) { throw new Error('Previous transaction not completed'); } this.currentTransaction = { ...transaction, results: [] }; } addInsert(result) { if (!this.currentTransaction) { throw new Error('No active transaction'); } this.currentTransaction.results.push(result); } async commitTransaction() { if (!this.currentTransaction) { throw new Error('No active transaction to commit'); } const transaction = this.currentTransaction; const finalLsn = this.currentTransaction.lsn; this.currentTransaction = undefined; try { for (const result of transaction.results) { try { await this.publish({ position: result.position, eventType: result.eventType, lsn: transaction.lsn, event: JSON.parse(result.payload), }); } catch (error) { this.emit('error', { transaction, error }); this.currentTransaction = transaction; throw error; } } this.lastAcknowledgedLsn = finalLsn; this.emit('transactionProcessed', transaction); } catch (error) { throw error; } } getLastAcknowledgedLsn() { return this.lastAcknowledgedLsn || '0/00000000'; } async retry() { if (this.currentTransaction && !this.isProcessing) { await this.commitTransaction(); } } } export { TransactionManager }; //# sourceMappingURL=TransactionManager.js.map