All files / events outbox.service.ts

75% Statements 6/8
0% Branches 0/6
0% Functions 0/2
66.66% Lines 4/6

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 574x   4x 4x                                                           4x                                              
import { Injectable } from '@nestjs/common';
import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
import { db } from '../db/client';
import { outboxEvents } from '../db/schema';
import * as schema from '../db/schema';
 
export interface OutboxEventInput {
  tenantId: string;
  /** Fara workspace, proiectiile nu stiu in ce partitie sa scrie si sar evenimentul. */
  workspaceId?: string;
  eventType: string;
  subjectId?: string;
  aggregateType?: string;
  actorId?: string;
  payload: Record<string, unknown>;
  correlationId?: string;
  /** Ce comanda/eveniment a produs acest eveniment. */
  causationId?: string;
  /** C0-C4; controleaza catre ce servicii poate fi distribuit. */
  classification?: string;
  provenance?: Record<string, unknown>;
  eventVersion?: number;
}
 
type Transaction = Parameters<Parameters<NodePgDatabase<typeof schema>['transaction']>[0]>[0];
 
/**
 * Blueprint 9.1 / principiul 2.1 "events before intelligence": orice scriere de
 * domeniu care trebuie sa produca un eveniment scrie in aceeasi tranzactie in
 * outbox_events. Publicarea efectiva (dispatch) se face separat, async, de catre
 * OutboxDispatcher -- niciodata inline in request path.
 */
@Injectable()
export class OutboxService {
  async withTransaction<T>(fn: (tx: Transaction) => Promise<T>): Promise<T> {
    return db.transaction(fn);
  }
 
  async record(tx: Transaction, event: OutboxEventInput): Promise<void> {
    await tx.insert(outboxEvents).values({
      tenantId: event.tenantId,
      workspaceId: event.workspaceId,
      eventType: event.eventType,
      eventVersion: event.eventVersion ?? 1,
      occurredAt: new Date(),
      actorId: event.actorId,
      aggregateType: event.aggregateType,
      subjectId: event.subjectId,
      payload: event.payload,
      correlationId: event.correlationId,
      causationId: event.causationId,
      classification: event.classification ?? 'c2',
      provenance: event.provenance ?? {},
    });
  }
}