UNPKG

@tomei/customer-base

Version:

Tomei Customer Base Package

225 lines (207 loc) 6.08 kB
import { Transaction } from 'sequelize'; import cuid from '../../helpers/cuid'; import { TrigerredByEnum } from '../../enum/triggered-by.enum'; import { EventTypeEnum } from '../../enum/event-type.enum'; import { SyncLoggerRepository } from './sync-logger.repository'; import { CustomerSyncLogModel } from '../../models/customer-sync-log.entity'; import { SyncStatusEnum } from '../../enum/sync-status.enum'; import { SystemSyncPolicy } from '../system-sync-policy'; import { IsPolicyAllowInsertEnum, IsPolicyAllowUpdateEnum, } from '../../enum/system-sync-policy.enum'; import { syncQueue } from '../sync-queue/sync-queue'; interface LogSyncTargetsParams { CustomerId: string; SourceSystemCode: string; TargetSystemCodes: string[]; TriggeredBy: TrigerredByEnum; EventType: EventTypeEnum; dbTransaction: Transaction; } export class SyncLogger { private static readonly _Repository = new SyncLoggerRepository(); async logSyncTargets(params: LogSyncTargetsParams): Promise<void> { const { CustomerId, SourceSystemCode, TargetSystemCodes, TriggeredBy, EventType, dbTransaction, } = params; for (const targetSystemCode of TargetSystemCodes) { try { if (targetSystemCode === SourceSystemCode) continue; const policy = await SystemSyncPolicy.get( SourceSystemCode, targetSystemCode, EventType, ); const isAllowed = !!policy && !( (EventType === EventTypeEnum.Insert && policy.AllowInsertYN !== IsPolicyAllowInsertEnum.Y) || (EventType === EventTypeEnum.Update && policy.AllowUpdateYN !== IsPolicyAllowUpdateEnum.Y) ); if (!isAllowed) { console.info('[SyncLogger.logSyncTargets] skipped by policy', { CustomerId, SourceSystemCode, TargetSystemCode: targetSystemCode, EventType, }); continue; } const logEntry = { SyncLogId: cuid(), CustomerId, SourceSystemCode, TargetSystemCode: targetSystemCode, EventType, TrigerredBy: TriggeredBy, Status: SyncStatusEnum.Pending, CreatedAt: new Date(), UpdatedAt: new Date(), }; await SyncLogger._Repository.create(logEntry, dbTransaction); await this.enqueueForLog( logEntry.SyncLogId, CustomerId, targetSystemCode, dbTransaction, ); } catch (err) { console.error('[SyncLogger.logSyncTargets] outer failure', { CustomerId, SourceSystemCode, EventType, error: (err as Error)?.message, }); throw err; } } } private async enqueueForLog( syncLogId: string, customerId: string, targetSystemCode: string, dbTransaction?: Transaction, ): Promise<void> { const doEnqueue = async () => { try { const job = await syncQueue.add('syncCustomer', { syncLogId, customerId, targetSystemCode, }); // update created CustomerSyncLog record to write back BullMQ job id await SyncLogger._Repository.update( { QueueJobId: String(job.id), LastStatus: SyncStatusEnum.Pending, LastAttemptAt: new Date(), }, { where: { SyncLogId: syncLogId }, }, ); } catch (err) { await SyncLogger._Repository.update( { LastErrorMessage: String(err), LastAttemptAt: new Date() }, { where: { SyncLogId: syncLogId } }, ); console.error('[SyncLogger.logSyncTargets] enqueue failed', { SyncLogId: syncLogId, error: (err as Error)?.message, }); } }; if (dbTransaction) { dbTransaction.afterCommit(() => { void doEnqueue(); }); } else { await doEnqueue(); } } async markSuccess( syncLogId: string, transaction?: Transaction, ): Promise<void> { try { await SyncLogger._Repository.update( { Status: SyncStatusEnum.Success, LastStatus: SyncStatusEnum.Success, SyncedAt: new Date(), LastAttemptAt: new Date(), LastErrorMessage: null, }, { where: { SyncLogId: syncLogId }, transaction }, ); } catch (err) { console.error('[SyncLogger.markSuccess] failed', { syncLogId, error: (err as Error)?.message, }); throw err; } } async markFailure( syncLogId: string, error: string, transaction?: Transaction, ): Promise<void> { try { const record = await SyncLogger._Repository.findByPk( syncLogId, transaction, ); const currentRetryCount = record?.RetryCount ?? 0; await SyncLogger._Repository.update( { Status: SyncStatusEnum.Failed, LastStatus: SyncStatusEnum.Failed, LastAttemptAt: new Date(), LastErrorMessage: error, RetryCount: currentRetryCount + 1, }, { where: { SyncLogId: syncLogId }, transaction }, ); } catch (err) { console.error('[SyncLogger.markFailure] failed', { syncLogId, incomingError: error, error: (err as Error)?.message, }); throw err; } } async markSkipped( syncLogId: string, reason: string, transaction?: Transaction, ): Promise<void> { try { await SyncLogger._Repository.update( { Status: SyncStatusEnum.Skipped, LastStatus: SyncStatusEnum.Skipped, LastAttemptAt: new Date(), LastErrorMessage: reason, }, { where: { SyncLogId: syncLogId }, transaction }, ); } catch (err) { console.error('[SyncLogger.markSkipped] failed', { syncLogId, reason, error: (err as Error)?.message, }); throw err; } } }