@generazioneai/events 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +106 -1
- package/dist/connection.d.ts +23 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +113 -0
- package/dist/connection.js.map +1 -0
- package/dist/consumers.service.d.ts +54 -0
- package/dist/consumers.service.d.ts.map +1 -0
- package/dist/consumers.service.js +346 -0
- package/dist/consumers.service.js.map +1 -0
- package/dist/decorators.d.ts +12 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +14 -0
- package/dist/decorators.js.map +1 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +24 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.module.d.ts +20 -0
- package/dist/events.module.d.ts.map +1 -0
- package/dist/events.module.js +98 -0
- package/dist/events.module.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics.d.ts +18 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +64 -0
- package/dist/metrics.js.map +1 -0
- package/dist/outbox.service.d.ts +24 -0
- package/dist/outbox.service.d.ts.map +1 -0
- package/dist/outbox.service.js +88 -0
- package/dist/outbox.service.js.map +1 -0
- package/dist/prisma-resolver.d.ts +11 -0
- package/dist/prisma-resolver.d.ts.map +1 -0
- package/dist/prisma-resolver.js +46 -0
- package/dist/prisma-resolver.js.map +1 -0
- package/dist/relay.service.d.ts +32 -0
- package/dist/relay.service.d.ts.map +1 -0
- package/dist/relay.service.js +153 -0
- package/dist/relay.service.js.map +1 -0
- package/dist/tokens.d.ts +4 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +7 -0
- package/dist/tokens.js.map +1 -0
- package/dist/types.d.ts +116 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +34 -0
- package/dist/types.js.map +1 -0
- package/dist/uuid.d.ts +7 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +32 -0
- package/dist/uuid.js.map +1 -0
- package/package.json +65 -4
- package/prisma/events.prisma +30 -0
- package/sql/001-events-outbox-inbox-rientro.sql +3 -0
- package/sql/001-events-outbox-inbox.sql +28 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type Labels = Record<string, string>;
|
|
2
|
+
/**
|
|
3
|
+
* Registro minimo di metriche (nessuna dipendenza). `render()` produce il testo Prometheus: il servizio lo aggiunge al suo
|
|
4
|
+
* endpoint delle metriche (o `@generazioneai/telemetry` lo legge). Nomi del contratto: events_outbox_pending,
|
|
5
|
+
* events_outbox_oldest_seconds, events_published_total, events_delivered_total{consumer}, events_nak_total,
|
|
6
|
+
* events_term_total, events_consumer_lag{consumer}.
|
|
7
|
+
*/
|
|
8
|
+
export declare class EventsMetrics {
|
|
9
|
+
private counters;
|
|
10
|
+
private gauges;
|
|
11
|
+
private static key;
|
|
12
|
+
inc(name: string, labels?: Labels, by?: number): void;
|
|
13
|
+
set(name: string, value: number, labels?: Labels): void;
|
|
14
|
+
get(name: string, labels?: Labels): number;
|
|
15
|
+
render(): string;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAEA,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErC;;;;;GAKG;AACH,qBACa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,MAAM,CAA0C;IAExD,OAAO,CAAC,MAAM,CAAC,GAAG;IAQlB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,SAAI,GAAG,IAAI;IAOhD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAMvD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;IAK1C,MAAM,IAAI,MAAM;CAYjB"}
|
package/dist/metrics.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var EventsMetrics_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.EventsMetrics = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
/**
|
|
13
|
+
* Registro minimo di metriche (nessuna dipendenza). `render()` produce il testo Prometheus: il servizio lo aggiunge al suo
|
|
14
|
+
* endpoint delle metriche (o `@generazioneai/telemetry` lo legge). Nomi del contratto: events_outbox_pending,
|
|
15
|
+
* events_outbox_oldest_seconds, events_published_total, events_delivered_total{consumer}, events_nak_total,
|
|
16
|
+
* events_term_total, events_consumer_lag{consumer}.
|
|
17
|
+
*/
|
|
18
|
+
let EventsMetrics = EventsMetrics_1 = class EventsMetrics {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.counters = new Map();
|
|
21
|
+
this.gauges = new Map();
|
|
22
|
+
}
|
|
23
|
+
static key(l) {
|
|
24
|
+
if (!l)
|
|
25
|
+
return '';
|
|
26
|
+
return Object.keys(l)
|
|
27
|
+
.sort()
|
|
28
|
+
.map((k) => `${k}="${String(l[k]).replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`)
|
|
29
|
+
.join(',');
|
|
30
|
+
}
|
|
31
|
+
inc(name, labels, by = 1) {
|
|
32
|
+
const m = this.counters.get(name) ?? new Map();
|
|
33
|
+
const k = EventsMetrics_1.key(labels);
|
|
34
|
+
m.set(k, (m.get(k) ?? 0) + by);
|
|
35
|
+
this.counters.set(name, m);
|
|
36
|
+
}
|
|
37
|
+
set(name, value, labels) {
|
|
38
|
+
const m = this.gauges.get(name) ?? new Map();
|
|
39
|
+
m.set(EventsMetrics_1.key(labels), value);
|
|
40
|
+
this.gauges.set(name, m);
|
|
41
|
+
}
|
|
42
|
+
get(name, labels) {
|
|
43
|
+
const k = EventsMetrics_1.key(labels);
|
|
44
|
+
return this.counters.get(name)?.get(k) ?? this.gauges.get(name)?.get(k) ?? 0;
|
|
45
|
+
}
|
|
46
|
+
render() {
|
|
47
|
+
const out = [];
|
|
48
|
+
const dump = (type, src) => {
|
|
49
|
+
for (const [name, series] of src) {
|
|
50
|
+
out.push(`# TYPE ${name} ${type}`);
|
|
51
|
+
for (const [k, v] of series)
|
|
52
|
+
out.push(`${name}${k ? `{${k}}` : ''} ${v}`);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
dump('counter', this.counters);
|
|
56
|
+
dump('gauge', this.gauges);
|
|
57
|
+
return out.join('\n') + '\n';
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.EventsMetrics = EventsMetrics;
|
|
61
|
+
exports.EventsMetrics = EventsMetrics = EventsMetrics_1 = __decorate([
|
|
62
|
+
(0, common_1.Injectable)()
|
|
63
|
+
], EventsMetrics);
|
|
64
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { EnqueueParams, PrismaTx, ResolvedEventsOptions } from './types';
|
|
2
|
+
export declare const OUTBOX_INSERT = "INSERT INTO outbox_events\n (\"id\",\"subject\",\"aggregateType\",\"aggregateId\",\"aggregateVersion\",\"juridicalId\",\"payload\",\"headers\")\n VALUES ($1::uuid,$2,$3,$4,$5,$6,$7::jsonb,$8::jsonb)";
|
|
3
|
+
export declare class OutboxService {
|
|
4
|
+
private readonly opts;
|
|
5
|
+
/** Client di transazione già verificati (un `tx` vive quanto la sua transazione: la prova si fa una volta sola). */
|
|
6
|
+
private readonly verified;
|
|
7
|
+
constructor(opts: ResolvedEventsOptions);
|
|
8
|
+
/**
|
|
9
|
+
* Riconosce una transazione dal lato del database, non dalla forma del client (in Prisma 7 il `tx` ha anch'esso `$transaction`):
|
|
10
|
+
* `SAVEPOINT` esiste solo dentro un blocco di transazione, altrimenti Postgres risponde 25P01. Con il client radice (una query
|
|
11
|
+
* in autocommit) fallisce → `EVENTS_OUTSIDE_TX`. Un `tx` verificato non si riprova.
|
|
12
|
+
*/
|
|
13
|
+
private assertInTransaction;
|
|
14
|
+
/**
|
|
15
|
+
* Scrive l'evento nell'outbox, nella stessa transazione del dato. `tx` è il client del callback di
|
|
16
|
+
* `prisma.$transaction(async (tx) => …)`; fuori da una transazione (client radice, con `$transaction`) lancia
|
|
17
|
+
* `EVENTS_OUTSIDE_TX`: niente «pubblica e speriamo».
|
|
18
|
+
*
|
|
19
|
+
* Con `EVENTS_MODE=off` non scrive nulla e restituisce `null` (il controllo della transazione resta, per trovare i bug prima
|
|
20
|
+
* dell'accensione). Altrimenti restituisce l'id dell'evento (UUID v7).
|
|
21
|
+
*/
|
|
22
|
+
enqueue<T>(tx: PrismaTx, p: EnqueueParams<T>): Promise<string | null>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=outbox.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.service.d.ts","sourceRoot":"","sources":["../src/outbox.service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAG9E,eAAO,MAAM,aAAa,6MAE6B,CAAC;AAExD,qBACa,aAAa;IAIY,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHzD,oHAAoH;IACpH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;gBAEG,IAAI,EAAE,qBAAqB;IAEhF;;;;OAIG;YACW,mBAAmB;IAiBjC;;;;;;;OAOG;IACG,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CA+B5E"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.OutboxService = exports.OUTBOX_INSERT = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const errors_1 = require("./errors");
|
|
18
|
+
const tokens_1 = require("./tokens");
|
|
19
|
+
const uuid_1 = require("./uuid");
|
|
20
|
+
exports.OUTBOX_INSERT = `INSERT INTO outbox_events
|
|
21
|
+
("id","subject","aggregateType","aggregateId","aggregateVersion","juridicalId","payload","headers")
|
|
22
|
+
VALUES ($1::uuid,$2,$3,$4,$5,$6,$7::jsonb,$8::jsonb)`;
|
|
23
|
+
let OutboxService = class OutboxService {
|
|
24
|
+
constructor(opts) {
|
|
25
|
+
this.opts = opts;
|
|
26
|
+
/** Client di transazione già verificati (un `tx` vive quanto la sua transazione: la prova si fa una volta sola). */
|
|
27
|
+
this.verified = new WeakSet();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Riconosce una transazione dal lato del database, non dalla forma del client (in Prisma 7 il `tx` ha anch'esso `$transaction`):
|
|
31
|
+
* `SAVEPOINT` esiste solo dentro un blocco di transazione, altrimenti Postgres risponde 25P01. Con il client radice (una query
|
|
32
|
+
* in autocommit) fallisce → `EVENTS_OUTSIDE_TX`. Un `tx` verificato non si riprova.
|
|
33
|
+
*/
|
|
34
|
+
async assertInTransaction(tx, subject) {
|
|
35
|
+
const outside = (cause) => new errors_1.EventsError('EVENTS_OUTSIDE_TX', `enqueue(${subject}) va chiamato dentro prisma.$transaction(async (tx) => …) passando il tx, non il client${cause ? ` (${cause?.message ?? cause})` : ''}`);
|
|
36
|
+
if (!tx || typeof tx.$executeRawUnsafe !== 'function')
|
|
37
|
+
throw outside();
|
|
38
|
+
if (this.verified.has(tx))
|
|
39
|
+
return;
|
|
40
|
+
try {
|
|
41
|
+
await tx.$executeRawUnsafe('SAVEPOINT genai_events_probe');
|
|
42
|
+
await tx.$executeRawUnsafe('RELEASE SAVEPOINT genai_events_probe');
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
throw outside(e);
|
|
46
|
+
}
|
|
47
|
+
this.verified.add(tx);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Scrive l'evento nell'outbox, nella stessa transazione del dato. `tx` è il client del callback di
|
|
51
|
+
* `prisma.$transaction(async (tx) => …)`; fuori da una transazione (client radice, con `$transaction`) lancia
|
|
52
|
+
* `EVENTS_OUTSIDE_TX`: niente «pubblica e speriamo».
|
|
53
|
+
*
|
|
54
|
+
* Con `EVENTS_MODE=off` non scrive nulla e restituisce `null` (il controllo della transazione resta, per trovare i bug prima
|
|
55
|
+
* dell'accensione). Altrimenti restituisce l'id dell'evento (UUID v7).
|
|
56
|
+
*/
|
|
57
|
+
async enqueue(tx, p) {
|
|
58
|
+
if (this.opts.mode !== 'off')
|
|
59
|
+
await this.assertInTransaction(tx, p?.subject);
|
|
60
|
+
else if (!tx || typeof tx.$executeRawUnsafe !== 'function')
|
|
61
|
+
return null; // off non lancia mai
|
|
62
|
+
const svc = this.opts.service;
|
|
63
|
+
const ok = p.subject?.startsWith(`evt.${svc}.`) || p.subject === `audit.${svc}` || p.subject?.startsWith(`audit.${svc}.`);
|
|
64
|
+
if (!ok) {
|
|
65
|
+
// evt.<svc>.* va sullo stream EVT_<SVC>; audit.<svc>[.*] sullo stream AUDIT (lo sceglie NATS dal subject)
|
|
66
|
+
throw new errors_1.EventsError('EVENTS_INVALID', `il subject «${p.subject}» deve iniziare con evt.${svc}. oppure essere audit.${svc}[.…]`);
|
|
67
|
+
}
|
|
68
|
+
if (!p.aggregate?.type || !p.aggregate?.id || !Number.isInteger(p.aggregate.version)) {
|
|
69
|
+
throw new errors_1.EventsError('EVENTS_INVALID', 'aggregate { type, id, version } è obbligatorio');
|
|
70
|
+
}
|
|
71
|
+
if (this.opts.mode === 'off')
|
|
72
|
+
return null;
|
|
73
|
+
const id = (0, uuid_1.uuidv7)();
|
|
74
|
+
const headers = { occurredAt: new Date().toISOString() };
|
|
75
|
+
const tp = this.opts.traceparent?.();
|
|
76
|
+
if (tp)
|
|
77
|
+
headers.traceparent = tp;
|
|
78
|
+
await tx.$executeRawUnsafe(exports.OUTBOX_INSERT, id, p.subject, p.aggregate.type, p.aggregate.id, p.aggregate.version, p.juridicalId ?? null, JSON.stringify(p.data ?? null), JSON.stringify(headers));
|
|
79
|
+
return id;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
exports.OutboxService = OutboxService;
|
|
83
|
+
exports.OutboxService = OutboxService = __decorate([
|
|
84
|
+
(0, common_1.Injectable)(),
|
|
85
|
+
__param(0, (0, common_1.Inject)(tokens_1.EVENTS_OPTIONS)),
|
|
86
|
+
__metadata("design:paramtypes", [Object])
|
|
87
|
+
], OutboxService);
|
|
88
|
+
//# sourceMappingURL=outbox.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.service.js","sourceRoot":"","sources":["../src/outbox.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ModuleRef } from '@nestjs/core';
|
|
2
|
+
import type { EventsModuleOptions, PrismaLike } from './types';
|
|
3
|
+
/** Risolve `PrismaService` quando serve (non alla costruzione: il suo modulo può non essere ancora pronto). */
|
|
4
|
+
export declare class PrismaResolver {
|
|
5
|
+
private readonly ref;
|
|
6
|
+
private readonly raw;
|
|
7
|
+
private cached?;
|
|
8
|
+
constructor(ref: ModuleRef, raw: EventsModuleOptions);
|
|
9
|
+
get(): PrismaLike;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=prisma-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-resolver.d.ts","sourceRoot":"","sources":["../src/prisma-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/D,+GAA+G;AAC/G,qBACa,cAAc;IAGvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACQ,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHlD,OAAO,CAAC,MAAM,CAAC,CAAa;gBAET,GAAG,EAAE,SAAS,EACc,GAAG,EAAE,mBAAmB;IAGvE,GAAG,IAAI,UAAU;CAYlB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PrismaResolver = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const core_1 = require("@nestjs/core");
|
|
18
|
+
const errors_1 = require("./errors");
|
|
19
|
+
const tokens_1 = require("./tokens");
|
|
20
|
+
/** Risolve `PrismaService` quando serve (non alla costruzione: il suo modulo può non essere ancora pronto). */
|
|
21
|
+
let PrismaResolver = class PrismaResolver {
|
|
22
|
+
constructor(ref, raw) {
|
|
23
|
+
this.ref = ref;
|
|
24
|
+
this.raw = raw;
|
|
25
|
+
}
|
|
26
|
+
get() {
|
|
27
|
+
if (this.cached)
|
|
28
|
+
return this.cached;
|
|
29
|
+
const p = this.raw.prisma;
|
|
30
|
+
const inst = (typeof p === 'function' || typeof p === 'string' || typeof p === 'symbol'
|
|
31
|
+
? this.ref.get(p, { strict: false })
|
|
32
|
+
: p);
|
|
33
|
+
if (!inst || typeof inst.$transaction !== 'function') {
|
|
34
|
+
throw new errors_1.EventsError('EVENTS_CONFIG', 'EventsModule.forRoot({ prisma }) non risolve a un PrismaService con $transaction');
|
|
35
|
+
}
|
|
36
|
+
this.cached = inst;
|
|
37
|
+
return inst;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.PrismaResolver = PrismaResolver;
|
|
41
|
+
exports.PrismaResolver = PrismaResolver = __decorate([
|
|
42
|
+
(0, common_1.Injectable)(),
|
|
43
|
+
__param(1, (0, common_1.Inject)(tokens_1.EVENTS_RAW_OPTIONS)),
|
|
44
|
+
__metadata("design:paramtypes", [core_1.ModuleRef, Object])
|
|
45
|
+
], PrismaResolver);
|
|
46
|
+
//# sourceMappingURL=prisma-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-resolver.js","sourceRoot":"","sources":["../src/prisma-resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,uCAAyC;AACzC,qCAAuC;AACvC,qCAA8C;AAG9C,+GAA+G;AAExG,IAAM,cAAc,GAApB,MAAM,cAAc;IAEzB,YACmB,GAAc,EACc,GAAwB;QADpD,QAAG,GAAH,GAAG,CAAW;QACc,QAAG,GAAH,GAAG,CAAqB;IACpE,CAAC;IAEJ,GAAG;QACD,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,UAAU,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ;YACrF,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;YAC3C,CAAC,CAAC,CAAC,CAA2B,CAAC;QACjC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;YACrD,MAAM,IAAI,oBAAW,CAAC,eAAe,EAAE,kFAAkF,CAAC,CAAC;QAC7H,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAnBY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,eAAM,EAAC,2BAAkB,CAAC,CAAA;qCADL,gBAAS;GAHtB,cAAc,CAmB1B"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { EventsConnection } from './connection';
|
|
2
|
+
import { EventsMetrics } from './metrics';
|
|
3
|
+
import { PrismaResolver } from './prisma-resolver';
|
|
4
|
+
import type { ResolvedEventsOptions } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Relay dell'outbox: prende fino a `relayBatchSize` righe con `FOR UPDATE SKIP LOCKED` (più repliche non si pestano i piedi),
|
|
7
|
+
* pubblica con `Nats-Msg-Id` = id, aspetta il PubAck e segna `publishedAt`, tutto nella stessa transazione. Se la pubblicazione
|
|
8
|
+
* fallisce si ferma (l'ordine del giro si conserva), conta il tentativo e riprova al giro dopo. L'ordine fra transazioni che
|
|
9
|
+
* committano fuori ordine, e fra repliche, NON è garantito: chi consuma usa `aggregateVersion`.
|
|
10
|
+
*/
|
|
11
|
+
export declare class OutboxRelay {
|
|
12
|
+
private readonly opts;
|
|
13
|
+
private readonly conn;
|
|
14
|
+
private readonly prisma;
|
|
15
|
+
private readonly metrics;
|
|
16
|
+
private readonly log;
|
|
17
|
+
private timer?;
|
|
18
|
+
private stopped;
|
|
19
|
+
private running;
|
|
20
|
+
private lastGauges;
|
|
21
|
+
private lastPrune;
|
|
22
|
+
constructor(opts: ResolvedEventsOptions, conn: EventsConnection, prisma: PrismaResolver, metrics: EventsMetrics);
|
|
23
|
+
start(): void;
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
private schedule;
|
|
26
|
+
private tick;
|
|
27
|
+
/** Un giro. Restituisce quante righe ha pubblicato. Usato anche dai test. */
|
|
28
|
+
drainOnce(): Promise<number>;
|
|
29
|
+
private publish;
|
|
30
|
+
private housekeeping;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=relay.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay.service.d.ts","sourceRoot":"","sources":["../src/relay.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,KAAK,EAA2B,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAa9E;;;;;GAKG;AACH,qBACa,WAAW;IASI,OAAO,CAAC,QAAQ,CAAC,IAAI;IAC7C,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA6B;IACjD,OAAO,CAAC,KAAK,CAAC,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,SAAS,CAAK;gBAGqB,IAAI,EAAE,qBAAqB,EACnD,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,aAAa;IAGzC,KAAK,IAAI,IAAI;IAMP,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,OAAO,CAAC,QAAQ;YAKF,IAAI;IAYlB,6EAA6E;IACvE,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;YA0CpB,OAAO;YAuBP,YAAY;CAsB3B"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.OutboxRelay = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const transport_node_1 = require("@nats-io/transport-node");
|
|
18
|
+
const connection_1 = require("./connection");
|
|
19
|
+
const metrics_1 = require("./metrics");
|
|
20
|
+
const prisma_resolver_1 = require("./prisma-resolver");
|
|
21
|
+
const tokens_1 = require("./tokens");
|
|
22
|
+
/**
|
|
23
|
+
* Relay dell'outbox: prende fino a `relayBatchSize` righe con `FOR UPDATE SKIP LOCKED` (più repliche non si pestano i piedi),
|
|
24
|
+
* pubblica con `Nats-Msg-Id` = id, aspetta il PubAck e segna `publishedAt`, tutto nella stessa transazione. Se la pubblicazione
|
|
25
|
+
* fallisce si ferma (l'ordine del giro si conserva), conta il tentativo e riprova al giro dopo. L'ordine fra transazioni che
|
|
26
|
+
* committano fuori ordine, e fra repliche, NON è garantito: chi consuma usa `aggregateVersion`.
|
|
27
|
+
*/
|
|
28
|
+
let OutboxRelay = class OutboxRelay {
|
|
29
|
+
constructor(opts, conn, prisma, metrics) {
|
|
30
|
+
this.opts = opts;
|
|
31
|
+
this.conn = conn;
|
|
32
|
+
this.prisma = prisma;
|
|
33
|
+
this.metrics = metrics;
|
|
34
|
+
this.log = new common_1.Logger('EventsRelay');
|
|
35
|
+
this.stopped = true;
|
|
36
|
+
this.running = false;
|
|
37
|
+
this.lastGauges = 0;
|
|
38
|
+
this.lastPrune = 0;
|
|
39
|
+
}
|
|
40
|
+
start() {
|
|
41
|
+
if (!this.stopped)
|
|
42
|
+
return;
|
|
43
|
+
this.stopped = false;
|
|
44
|
+
this.schedule(0);
|
|
45
|
+
}
|
|
46
|
+
async stop() {
|
|
47
|
+
this.stopped = true;
|
|
48
|
+
if (this.timer)
|
|
49
|
+
clearTimeout(this.timer);
|
|
50
|
+
while (this.running)
|
|
51
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
52
|
+
}
|
|
53
|
+
schedule(ms) {
|
|
54
|
+
if (this.stopped)
|
|
55
|
+
return;
|
|
56
|
+
this.timer = setTimeout(() => void this.tick(), ms);
|
|
57
|
+
}
|
|
58
|
+
async tick() {
|
|
59
|
+
let again = false;
|
|
60
|
+
try {
|
|
61
|
+
const n = await this.drainOnce();
|
|
62
|
+
again = n >= this.opts.relayBatchSize;
|
|
63
|
+
await this.housekeeping();
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
this.log.warn(`giro del relay fallito: ${e?.message ?? e}`);
|
|
67
|
+
}
|
|
68
|
+
this.schedule(again ? 0 : this.opts.relayIntervalMs);
|
|
69
|
+
}
|
|
70
|
+
/** Un giro. Restituisce quante righe ha pubblicato. Usato anche dai test. */
|
|
71
|
+
async drainOnce() {
|
|
72
|
+
if (this.running)
|
|
73
|
+
return 0;
|
|
74
|
+
this.running = true;
|
|
75
|
+
try {
|
|
76
|
+
if (!this.conn.connected)
|
|
77
|
+
return 0;
|
|
78
|
+
const prisma = this.prisma.get();
|
|
79
|
+
return await prisma.$transaction(async (tx) => {
|
|
80
|
+
const rows = await tx.$queryRawUnsafe(`SELECT "id","subject","aggregateType","aggregateId","aggregateVersion","juridicalId","payload","headers"
|
|
81
|
+
FROM outbox_events WHERE "publishedAt" IS NULL ORDER BY "id" LIMIT ${Math.floor(this.opts.relayBatchSize)}
|
|
82
|
+
FOR UPDATE SKIP LOCKED`);
|
|
83
|
+
let done = 0;
|
|
84
|
+
for (const r of rows) {
|
|
85
|
+
try {
|
|
86
|
+
await this.publish(r);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
await tx.$executeRawUnsafe(`UPDATE outbox_events SET "attempts" = "attempts" + 1, "lastError" = $2 WHERE "id" = $1::uuid`, r.id, String(e?.message ?? e).slice(0, 500));
|
|
90
|
+
this.log.warn(`pubblicazione di ${r.subject} (${r.id}) fallita: ${e?.message ?? e}`);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
await tx.$executeRawUnsafe(`UPDATE outbox_events SET "publishedAt" = CURRENT_TIMESTAMP, "attempts" = "attempts" + 1, "lastError" = NULL WHERE "id" = $1::uuid`, r.id);
|
|
94
|
+
this.metrics.inc('events_published_total', { subject: r.subject });
|
|
95
|
+
done++;
|
|
96
|
+
}
|
|
97
|
+
return done;
|
|
98
|
+
}, { timeout: 60_000, maxWait: 10_000 });
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
this.running = false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async publish(r) {
|
|
105
|
+
const envelope = {
|
|
106
|
+
v: 1,
|
|
107
|
+
id: r.id,
|
|
108
|
+
subject: r.subject,
|
|
109
|
+
aggregateType: r.aggregateType,
|
|
110
|
+
aggregateId: r.aggregateId,
|
|
111
|
+
aggregateVersion: r.aggregateVersion,
|
|
112
|
+
occurredAt: r.headers?.occurredAt ?? new Date().toISOString(),
|
|
113
|
+
...(r.juridicalId ? { juridicalId: r.juridicalId } : {}),
|
|
114
|
+
data: r.payload,
|
|
115
|
+
};
|
|
116
|
+
const h = (0, transport_node_1.headers)();
|
|
117
|
+
h.set('Nats-Msg-Id', r.id);
|
|
118
|
+
h.set('Gen-Event-Version', '1');
|
|
119
|
+
if (r.juridicalId)
|
|
120
|
+
h.set('Gen-Tenant', r.juridicalId);
|
|
121
|
+
if (r.headers?.traceparent)
|
|
122
|
+
h.set('traceparent', r.headers.traceparent);
|
|
123
|
+
if (this.opts.signatureMode !== 'off' && this.opts.signer) {
|
|
124
|
+
h.set('Gen-Sig', await this.opts.signer({ eventId: r.id, subject: r.subject, juridicalId: r.juridicalId }));
|
|
125
|
+
}
|
|
126
|
+
await this.conn.jetstream.publish(r.subject, JSON.stringify(envelope), { msgID: r.id, headers: h, timeout: 10_000 });
|
|
127
|
+
}
|
|
128
|
+
async housekeeping() {
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
const prisma = this.prisma.get();
|
|
131
|
+
if (now - this.lastGauges > 5_000) {
|
|
132
|
+
this.lastGauges = now;
|
|
133
|
+
const [row] = await prisma.$queryRawUnsafe(`SELECT COUNT(*) AS pending, EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - MIN("createdAt")))::float8 AS oldest
|
|
134
|
+
FROM outbox_events WHERE "publishedAt" IS NULL`);
|
|
135
|
+
this.metrics.set('events_outbox_pending', Number(row?.pending ?? 0));
|
|
136
|
+
this.metrics.set('events_outbox_oldest_seconds', Number(row?.oldest ?? 0));
|
|
137
|
+
}
|
|
138
|
+
if (now - this.lastPrune > 600_000) {
|
|
139
|
+
this.lastPrune = now;
|
|
140
|
+
await prisma.$executeRawUnsafe(`DELETE FROM outbox_events WHERE "publishedAt" IS NOT NULL AND "publishedAt" < CURRENT_TIMESTAMP - make_interval(days => ${Math.floor(this.opts.outboxRetentionDays)})`);
|
|
141
|
+
await prisma.$executeRawUnsafe(`DELETE FROM inbox_processed WHERE "processedAt" < CURRENT_TIMESTAMP - make_interval(days => ${Math.floor(this.opts.inboxRetentionDays)})`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
exports.OutboxRelay = OutboxRelay;
|
|
146
|
+
exports.OutboxRelay = OutboxRelay = __decorate([
|
|
147
|
+
(0, common_1.Injectable)(),
|
|
148
|
+
__param(0, (0, common_1.Inject)(tokens_1.EVENTS_OPTIONS)),
|
|
149
|
+
__metadata("design:paramtypes", [Object, connection_1.EventsConnection,
|
|
150
|
+
prisma_resolver_1.PrismaResolver,
|
|
151
|
+
metrics_1.EventsMetrics])
|
|
152
|
+
], OutboxRelay);
|
|
153
|
+
//# sourceMappingURL=relay.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay.service.js","sourceRoot":"","sources":["../src/relay.service.ts"],"names":[],"mappings":"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"}
|
package/dist/tokens.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,eAAiC,CAAC;AAC7D,eAAO,MAAM,kBAAkB,eAAqC,CAAC;AACrE,eAAO,MAAM,iBAAiB,0BAA0B,CAAC"}
|
package/dist/tokens.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ON_EVENT_METADATA = exports.EVENTS_RAW_OPTIONS = exports.EVENTS_OPTIONS = void 0;
|
|
4
|
+
exports.EVENTS_OPTIONS = Symbol('GENAI_EVENTS_OPTIONS');
|
|
5
|
+
exports.EVENTS_RAW_OPTIONS = Symbol('GENAI_EVENTS_RAW_OPTIONS');
|
|
6
|
+
exports.ON_EVENT_METADATA = 'genai:events:on-event';
|
|
7
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":";;;AAAa,QAAA,cAAc,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAChD,QAAA,kBAAkB,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAC;AACxD,QAAA,iBAAiB,GAAG,uBAAuB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** Busta di ogni evento (versione 1). Il corpo del messaggio NATS è questo oggetto in JSON. */
|
|
2
|
+
export interface EventEnvelope<T = unknown> {
|
|
3
|
+
v: 1;
|
|
4
|
+
/** UUID v7, uguale a `Nats-Msg-Id`. */
|
|
5
|
+
id: string;
|
|
6
|
+
subject: string;
|
|
7
|
+
aggregateType: string;
|
|
8
|
+
aggregateId: string;
|
|
9
|
+
aggregateVersion: number;
|
|
10
|
+
/** ISO 8601 UTC del momento in cui l'evento è stato scritto nell'outbox. */
|
|
11
|
+
occurredAt: string;
|
|
12
|
+
/** Azienda di riferimento (anche in `Gen-Tenant`). */
|
|
13
|
+
juridicalId?: string;
|
|
14
|
+
/** Solo id e stati, mai dati personali. */
|
|
15
|
+
data: T;
|
|
16
|
+
}
|
|
17
|
+
/** Servizi che pubblicano o consumano eventi (contratto del treno 3+4). */
|
|
18
|
+
export type EventsService = 'id' | 'hr' | 'train' | 'ops' | 'notify' | 'ai' | 'sign' | 'bill' | 'audit';
|
|
19
|
+
/** `EVENTS_MODE`: off = niente; outbox = si scrive l'outbox ma non si pubblica né si consuma; on = tutto. */
|
|
20
|
+
export type EventsMode = 'off' | 'outbox' | 'on';
|
|
21
|
+
/** `EVENTS_SIGNATURE`: off = nessuna firma; shadow = firma e verifica senza rifiutare; enforce = rifiuta le firme assenti o errate. */
|
|
22
|
+
export type EventsSignatureMode = 'off' | 'shadow' | 'enforce';
|
|
23
|
+
/** Il pezzo di Prisma che serve alla libreria dentro una transazione (il `tx` di `$transaction(async tx => …)`). */
|
|
24
|
+
export interface PrismaTx {
|
|
25
|
+
$executeRawUnsafe(query: string, ...values: any[]): Promise<number>;
|
|
26
|
+
$queryRawUnsafe<T = unknown>(query: string, ...values: any[]): Promise<T>;
|
|
27
|
+
}
|
|
28
|
+
/** Il pezzo di `PrismaService` che serve alla libreria. Un client di transazione NON ha `$transaction`: così si riconosce. */
|
|
29
|
+
export interface PrismaLike extends PrismaTx {
|
|
30
|
+
$transaction<R>(fn: (tx: PrismaTx) => Promise<R>, options?: {
|
|
31
|
+
timeout?: number;
|
|
32
|
+
maxWait?: number;
|
|
33
|
+
}): Promise<R>;
|
|
34
|
+
}
|
|
35
|
+
export interface SignParams {
|
|
36
|
+
eventId: string;
|
|
37
|
+
subject: string;
|
|
38
|
+
juridicalId?: string | null;
|
|
39
|
+
}
|
|
40
|
+
/** Produce il JWT di `Gen-Sig` (audience `events`). Con authz 0.7: `(p) => signEventToken(ctx, { eventId: p.eventId, subject: p.subject })`. */
|
|
41
|
+
export type EventSigner = (params: SignParams) => string | Promise<string>;
|
|
42
|
+
export interface VerifyParams {
|
|
43
|
+
eventId: string;
|
|
44
|
+
subject: string;
|
|
45
|
+
mode: Exclude<EventsSignatureMode, 'off'>;
|
|
46
|
+
}
|
|
47
|
+
/** Verifica `Gen-Sig`; lancia se non valida. Con authz 0.7: `(t, p) => verifyEventToken(t, p)`. `token` è `undefined` se manca. */
|
|
48
|
+
export type EventVerifier = (token: string | undefined, params: VerifyParams) => void | Promise<void>;
|
|
49
|
+
export interface OnEventOptions {
|
|
50
|
+
/** Nome del consumer durevole: `<servizio>.<gestore>` (es. `hr.employment-changed`). Unico nel cluster. */
|
|
51
|
+
consumer: string;
|
|
52
|
+
/** Messaggi senza ack tollerati dal consumer (default 100). */
|
|
53
|
+
maxAckPending?: number;
|
|
54
|
+
}
|
|
55
|
+
export type EventHandler<T = any> = (evt: EventEnvelope<T>, tx: PrismaTx) => Promise<void>;
|
|
56
|
+
export interface EnqueueParams<T = unknown> {
|
|
57
|
+
/** `evt.<servizio>.<entità>.<fatto>` al passato. */
|
|
58
|
+
subject: string;
|
|
59
|
+
aggregate: {
|
|
60
|
+
type: string;
|
|
61
|
+
id: string;
|
|
62
|
+
version: number;
|
|
63
|
+
};
|
|
64
|
+
juridicalId?: string | null;
|
|
65
|
+
/** Diventa `data` della busta. Solo id e stati. */
|
|
66
|
+
data: T;
|
|
67
|
+
}
|
|
68
|
+
export interface EventsModuleOptions {
|
|
69
|
+
service: EventsService;
|
|
70
|
+
/** Default `EVT_<SERVICE>`. */
|
|
71
|
+
stream?: string;
|
|
72
|
+
/** La classe (o il token) di `PrismaService` da risolvere dal contenitore di Nest, oppure direttamente l'istanza. */
|
|
73
|
+
prisma: unknown;
|
|
74
|
+
/** Default: `EVENTS_MODE` o `off`. */
|
|
75
|
+
mode?: EventsMode;
|
|
76
|
+
/** Default: `EVENTS_SIGNATURE` o `off`. */
|
|
77
|
+
signatureMode?: EventsSignatureMode;
|
|
78
|
+
signer?: EventSigner;
|
|
79
|
+
verifier?: EventVerifier;
|
|
80
|
+
/** Default: `EVENTS_NATS_URL` o `NATS_URL`. */
|
|
81
|
+
natsUrl?: string;
|
|
82
|
+
/** Opzioni di connessione aggiuntive (`@nats-io/transport-node`); di serie `NATS_NKEY_SEED` → autenticazione nkey. */
|
|
83
|
+
connection?: Record<string, unknown>;
|
|
84
|
+
/** Se creare lo stream del servizio all'avvio (default true). */
|
|
85
|
+
createStream?: boolean;
|
|
86
|
+
/** Repliche dello stream (default 3; 1 in sviluppo). Env `EVENTS_STREAM_REPLICAS`. */
|
|
87
|
+
streamReplicas?: number;
|
|
88
|
+
/**
|
|
89
|
+
* Tetto in byte dello stream (default 5 GiB). JetStream lo **riserva** sul `max_file_store` del server alla creazione: con un NATS
|
|
90
|
+
* piccolo (sviluppo, staging, CI) due stream da 5 GiB possono non starci e l'avvio degli eventi resta a riprovare. Env `EVENTS_STREAM_MAX_BYTES`.
|
|
91
|
+
*/
|
|
92
|
+
streamMaxBytes?: number;
|
|
93
|
+
/** Attese fra le consegne: default 10s, 1m, 5m, 30m, 2h, 6h, 12h (8 consegne). */
|
|
94
|
+
retryScheduleMs?: number[];
|
|
95
|
+
/** Intervallo del relay (default 500 ms). */
|
|
96
|
+
relayIntervalMs?: number;
|
|
97
|
+
/** Durata di ogni attesa del consumer prima di ricontrollare lo stop (default 5000 ms, minimo 1000 imposto da JetStream). */
|
|
98
|
+
pollMs?: number;
|
|
99
|
+
/** Righe dell'outbox per giro (default 100). */
|
|
100
|
+
relayBatchSize?: number;
|
|
101
|
+
/** Giorni di conservazione delle righe pubblicate (default 7) e dell'inbox (default 30). */
|
|
102
|
+
outboxRetentionDays?: number;
|
|
103
|
+
inboxRetentionDays?: number;
|
|
104
|
+
/** Per leggere il `traceparent` corrente al momento di `enqueue` (lo fornisce `@generazioneai/telemetry`). */
|
|
105
|
+
traceparent?: () => string | undefined;
|
|
106
|
+
}
|
|
107
|
+
export declare const DEFAULT_RETRY_SCHEDULE_MS: number[];
|
|
108
|
+
export interface ResolvedEventsOptions extends Required<Pick<EventsModuleOptions, 'service' | 'stream' | 'mode' | 'signatureMode' | 'createStream' | 'streamReplicas' | 'streamMaxBytes' | 'retryScheduleMs' | 'relayIntervalMs' | 'relayBatchSize' | 'pollMs' | 'outboxRetentionDays' | 'inboxRetentionDays'>> {
|
|
109
|
+
natsUrl?: string;
|
|
110
|
+
signer?: EventSigner;
|
|
111
|
+
verifier?: EventVerifier;
|
|
112
|
+
connection?: Record<string, unknown>;
|
|
113
|
+
traceparent?: () => string | undefined;
|
|
114
|
+
}
|
|
115
|
+
export declare function resolveOptions(o: EventsModuleOptions, env?: NodeJS.ProcessEnv): ResolvedEventsOptions;
|
|
116
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|