@pattern-stack/codegen 0.27.0 → 0.27.1
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 +24 -0
- package/dist/{chunk-IXAE6BN6.js → chunk-36NRG2EP.js} +8 -8
- package/dist/{chunk-COGHTKXY.js → chunk-7625PLY7.js} +4 -4
- package/dist/{chunk-IN3EWFB4.js → chunk-BHZP6LOV.js} +4 -4
- package/dist/{chunk-CZQUOIDY.js → chunk-DKKFTHHI.js} +4 -4
- package/dist/{chunk-AC6T2JUX.js → chunk-KS4BZHIA.js} +12 -12
- package/dist/{chunk-3VEVGL74.js → chunk-VNBC3VXM.js} +4 -4
- package/dist/{chunk-PNCOUFFI.js → chunk-Y6UZMYGX.js} +4 -3
- package/dist/chunk-Y6UZMYGX.js.map +1 -0
- package/dist/{chunk-VDVEGTSW.js → chunk-YHVZAL6U.js} +2 -2
- package/dist/{chunk-HEOISQ6W.js → chunk-Z7YFYK6H.js} +4 -4
- package/dist/runtime/base-classes/index.js +17 -17
- package/dist/runtime/subsystems/analytics/analytics.module.js +2 -2
- package/dist/runtime/subsystems/analytics/index.js +4 -4
- package/dist/runtime/subsystems/auth/auth.module.js +1 -1
- package/dist/runtime/subsystems/auth/index.js +3 -3
- package/dist/runtime/subsystems/bridge/bridge.module.js +11 -11
- package/dist/runtime/subsystems/bridge/index.js +17 -17
- package/dist/runtime/subsystems/cache/cache.module.js +2 -2
- package/dist/runtime/subsystems/cache/index.js +4 -4
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +1 -1
- package/dist/runtime/subsystems/events/events.module.js +2 -2
- package/dist/runtime/subsystems/events/index.js +2 -2
- package/dist/runtime/subsystems/index.js +30 -30
- package/dist/runtime/subsystems/jobs/index.js +15 -15
- package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js +2 -2
- package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js +2 -2
- package/dist/runtime/subsystems/jobs/job-worker.module.js +7 -7
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +6 -6
- package/package.json +1 -1
- package/runtime/subsystems/events/event-bus.drizzle-backend.ts +16 -4
- package/dist/chunk-PNCOUFFI.js.map +0 -1
- /package/dist/{chunk-IXAE6BN6.js.map → chunk-36NRG2EP.js.map} +0 -0
- /package/dist/{chunk-COGHTKXY.js.map → chunk-7625PLY7.js.map} +0 -0
- /package/dist/{chunk-IN3EWFB4.js.map → chunk-BHZP6LOV.js.map} +0 -0
- /package/dist/{chunk-CZQUOIDY.js.map → chunk-DKKFTHHI.js.map} +0 -0
- /package/dist/{chunk-AC6T2JUX.js.map → chunk-KS4BZHIA.js.map} +0 -0
- /package/dist/{chunk-3VEVGL74.js.map → chunk-VNBC3VXM.js.map} +0 -0
- /package/dist/{chunk-VDVEGTSW.js.map → chunk-YHVZAL6U.js.map} +0 -0
- /package/dist/{chunk-HEOISQ6W.js.map → chunk-Z7YFYK6H.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.27.1] — 2026-06-07
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **Scheduled-event drain no longer claims future slots early (#533).**
|
|
10
|
+
`DrizzleEventBus.processBatch()` composed a status-only claim
|
|
11
|
+
(`status='pending'` [+ pool IN …]) with no readiness predicate, so the 1s
|
|
12
|
+
fallback poll grabbed the `EventScheduler`'s pre-materialised *next* slot
|
|
13
|
+
(`occurred_at = slotStart`, in the future) on the very next cycle and stamped
|
|
14
|
+
`processed_at = now()` — contradicting `materializeScheduledEvent`'s own
|
|
15
|
+
contract ("a future slot is claimed by polling once `occurred_at` passes").
|
|
16
|
+
Symptoms: event-log rows reading "N minutes from now" yet already
|
|
17
|
+
`status:processed`, and schedule-driven triggers firing up to one interval
|
|
18
|
+
ahead of their slot. Fix: add `occurred_at <= now` to the claim WHERE (both
|
|
19
|
+
the pooled and pool-less branches). Normal events publish with
|
|
20
|
+
`occurred_at = now()`, so the gate is transparent to them.
|
|
21
|
+
|
|
22
|
+
## [0.27.0] — 2026-06-07
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Pagination by default (#532): `Page<T>` list emit + `store.<entity>.useData()`.**
|
|
27
|
+
See PR #532. (CHANGELOG entry backfilled in 0.27.1.)
|
|
28
|
+
|
|
5
29
|
## [0.26.1] — 2026-06-07
|
|
6
30
|
|
|
7
31
|
### Fixed
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
bridgeRegistry
|
|
3
3
|
} from "./chunk-5A432NZJ.js";
|
|
4
|
+
import {
|
|
5
|
+
BridgeOutboxDrainHook
|
|
6
|
+
} from "./chunk-E5FJWOMP.js";
|
|
4
7
|
import {
|
|
5
8
|
EventFlowService
|
|
6
9
|
} from "./chunk-7OVCARTQ.js";
|
|
7
10
|
import {
|
|
8
11
|
BRIDGE_RESERVED_POOLS
|
|
9
12
|
} from "./chunk-EDKJU5BO.js";
|
|
13
|
+
import {
|
|
14
|
+
BridgeDeliveryHandler
|
|
15
|
+
} from "./chunk-R6F6KFIL.js";
|
|
10
16
|
import {
|
|
11
17
|
DrizzleBridgeDeliveryRepo
|
|
12
18
|
} from "./chunk-MVKW2BCR.js";
|
|
13
19
|
import {
|
|
14
20
|
MemoryBridgeDeliveryRepo
|
|
15
21
|
} from "./chunk-4DOJBQTP.js";
|
|
16
|
-
import {
|
|
17
|
-
BridgeOutboxDrainHook
|
|
18
|
-
} from "./chunk-E5FJWOMP.js";
|
|
19
|
-
import {
|
|
20
|
-
BridgeDeliveryHandler
|
|
21
|
-
} from "./chunk-R6F6KFIL.js";
|
|
22
22
|
import {
|
|
23
23
|
BridgeReservedPoolsNotPolledError
|
|
24
24
|
} from "./chunk-NXXDZ6ZF.js";
|
|
25
25
|
import {
|
|
26
26
|
JOB_WORKER_MODULE_OPTIONS
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-Z7YFYK6H.js";
|
|
28
28
|
import {
|
|
29
29
|
BRIDGE_DELIVERY_REPO,
|
|
30
30
|
BRIDGE_MODULE_OPTIONS,
|
|
@@ -119,4 +119,4 @@ BridgeModule = __decorateClass([
|
|
|
119
119
|
export {
|
|
120
120
|
BridgeModule
|
|
121
121
|
};
|
|
122
|
-
//# sourceMappingURL=chunk-
|
|
122
|
+
//# sourceMappingURL=chunk-36NRG2EP.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DrizzleCacheService
|
|
3
|
-
} from "./chunk-T6C4LFLC.js";
|
|
4
1
|
import {
|
|
5
2
|
MemoryCacheService
|
|
6
3
|
} from "./chunk-IF5I3DAA.js";
|
|
4
|
+
import {
|
|
5
|
+
DrizzleCacheService
|
|
6
|
+
} from "./chunk-T6C4LFLC.js";
|
|
7
7
|
import {
|
|
8
8
|
CACHE,
|
|
9
9
|
CACHE_DEFAULT_TTL
|
|
@@ -81,4 +81,4 @@ CacheModule = __decorateClass([
|
|
|
81
81
|
export {
|
|
82
82
|
CacheModule
|
|
83
83
|
};
|
|
84
|
-
//# sourceMappingURL=chunk-
|
|
84
|
+
//# sourceMappingURL=chunk-7625PLY7.js.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MemoryJobStore
|
|
3
3
|
} from "./chunk-SNQ3TOWP.js";
|
|
4
|
+
import {
|
|
5
|
+
MissingTenantIdError
|
|
6
|
+
} from "./chunk-T4BIIU5E.js";
|
|
4
7
|
import {
|
|
5
8
|
clampLimit,
|
|
6
9
|
decodeKeysetCursor,
|
|
7
10
|
encodeKeysetCursor,
|
|
8
11
|
toJobRunSummary
|
|
9
12
|
} from "./chunk-L3LZWWSX.js";
|
|
10
|
-
import {
|
|
11
|
-
MissingTenantIdError
|
|
12
|
-
} from "./chunk-T4BIIU5E.js";
|
|
13
13
|
import {
|
|
14
14
|
JOBS_MULTI_TENANT,
|
|
15
15
|
JOB_ORCHESTRATOR
|
|
@@ -209,4 +209,4 @@ function compareBy(a, b, order) {
|
|
|
209
209
|
export {
|
|
210
210
|
MemoryJobRunService
|
|
211
211
|
};
|
|
212
|
-
//# sourceMappingURL=chunk-
|
|
212
|
+
//# sourceMappingURL=chunk-BHZP6LOV.js.map
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NoopAnalyticsBackend
|
|
3
|
+
} from "./chunk-J37YWU7Y.js";
|
|
1
4
|
import {
|
|
2
5
|
CubeAnalyticsBackend
|
|
3
6
|
} from "./chunk-7B3RYX45.js";
|
|
@@ -6,9 +9,6 @@ import {
|
|
|
6
9
|
CUBE_API_SECRET,
|
|
7
10
|
CUBE_API_URL
|
|
8
11
|
} from "./chunk-6I7ULIN6.js";
|
|
9
|
-
import {
|
|
10
|
-
NoopAnalyticsBackend
|
|
11
|
-
} from "./chunk-J37YWU7Y.js";
|
|
12
12
|
import {
|
|
13
13
|
__decorateClass
|
|
14
14
|
} from "./chunk-2E224ZSN.js";
|
|
@@ -50,4 +50,4 @@ AnalyticsModule = __decorateClass([
|
|
|
50
50
|
export {
|
|
51
51
|
AnalyticsModule
|
|
52
52
|
};
|
|
53
|
-
//# sourceMappingURL=chunk-
|
|
53
|
+
//# sourceMappingURL=chunk-DKKFTHHI.js.map
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MemoryJobRunService
|
|
3
|
+
} from "./chunk-BHZP6LOV.js";
|
|
4
|
+
import {
|
|
5
|
+
DrizzleJobStepService
|
|
6
|
+
} from "./chunk-DV4RV2DC.js";
|
|
7
|
+
import {
|
|
8
|
+
DrizzleJobOrchestrator
|
|
9
|
+
} from "./chunk-E6PLM6QG.js";
|
|
1
10
|
import {
|
|
2
11
|
MemoryJobOrchestrator
|
|
3
12
|
} from "./chunk-VQOAATIG.js";
|
|
4
13
|
import {
|
|
5
14
|
MemoryJobStepService
|
|
6
15
|
} from "./chunk-PNZSGAB2.js";
|
|
7
|
-
import {
|
|
8
|
-
DrizzleJobRunService
|
|
9
|
-
} from "./chunk-3VEVGL74.js";
|
|
10
|
-
import {
|
|
11
|
-
MemoryJobRunService
|
|
12
|
-
} from "./chunk-IN3EWFB4.js";
|
|
13
16
|
import {
|
|
14
17
|
MemoryJobStore
|
|
15
18
|
} from "./chunk-SNQ3TOWP.js";
|
|
16
19
|
import {
|
|
17
|
-
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import {
|
|
20
|
-
DrizzleJobOrchestrator
|
|
21
|
-
} from "./chunk-E6PLM6QG.js";
|
|
20
|
+
DrizzleJobRunService
|
|
21
|
+
} from "./chunk-VNBC3VXM.js";
|
|
22
22
|
import {
|
|
23
23
|
BULLMQ_CONNECTION,
|
|
24
24
|
BULLMQ_RESOLVED_CONFIG,
|
|
@@ -114,4 +114,4 @@ JobsDomainModule = __decorateClass([
|
|
|
114
114
|
export {
|
|
115
115
|
JobsDomainModule
|
|
116
116
|
};
|
|
117
|
-
//# sourceMappingURL=chunk-
|
|
117
|
+
//# sourceMappingURL=chunk-KS4BZHIA.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MissingTenantIdError
|
|
3
|
+
} from "./chunk-T4BIIU5E.js";
|
|
1
4
|
import {
|
|
2
5
|
clampLimit,
|
|
3
6
|
decodeKeysetCursor,
|
|
4
7
|
encodeKeysetCursor,
|
|
5
8
|
toJobRunSummary
|
|
6
9
|
} from "./chunk-L3LZWWSX.js";
|
|
7
|
-
import {
|
|
8
|
-
MissingTenantIdError
|
|
9
|
-
} from "./chunk-T4BIIU5E.js";
|
|
10
10
|
import {
|
|
11
11
|
JOBS_MULTI_TENANT,
|
|
12
12
|
JOB_ORCHESTRATOR
|
|
@@ -198,4 +198,4 @@ DrizzleJobRunService = __decorateClass([
|
|
|
198
198
|
export {
|
|
199
199
|
DrizzleJobRunService
|
|
200
200
|
};
|
|
201
|
-
//# sourceMappingURL=chunk-
|
|
201
|
+
//# sourceMappingURL=chunk-VNBC3VXM.js.map
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
// runtime/subsystems/events/event-bus.drizzle-backend.ts
|
|
29
29
|
import { randomUUID } from "crypto";
|
|
30
30
|
import { Injectable, Inject, Logger, Optional } from "@nestjs/common";
|
|
31
|
-
import { eq, and, inArray, asc, desc, gte, lt, or, sql } from "drizzle-orm";
|
|
31
|
+
import { eq, and, inArray, asc, desc, gte, lt, lte, or, sql } from "drizzle-orm";
|
|
32
32
|
var POLL_INTERVAL_MS = 1e3;
|
|
33
33
|
var POLL_BATCH_SIZE = 50;
|
|
34
34
|
function toInsertValues(event, multiTenant) {
|
|
@@ -388,7 +388,8 @@ var DrizzleEventBus = class {
|
|
|
388
388
|
*/
|
|
389
389
|
async processBatch() {
|
|
390
390
|
const pools = this.opts.pools;
|
|
391
|
-
const
|
|
391
|
+
const ready = lte(domainEvents.occurredAt, /* @__PURE__ */ new Date());
|
|
392
|
+
const whereClause = pools && pools.length > 0 ? and(eq(domainEvents.status, "pending"), ready, inArray(domainEvents.pool, pools)) : and(eq(domainEvents.status, "pending"), ready);
|
|
392
393
|
const rows = await this.db.transaction(async (tx) => {
|
|
393
394
|
return tx.select().from(domainEvents).where(whereClause).orderBy(asc(domainEvents.occurredAt)).limit(POLL_BATCH_SIZE).for("update", { skipLocked: true });
|
|
394
395
|
});
|
|
@@ -462,4 +463,4 @@ DrizzleEventBus = __decorateClass([
|
|
|
462
463
|
export {
|
|
463
464
|
DrizzleEventBus
|
|
464
465
|
};
|
|
465
|
-
//# sourceMappingURL=chunk-
|
|
466
|
+
//# sourceMappingURL=chunk-Y6UZMYGX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../runtime/subsystems/events/event-bus.drizzle-backend.ts"],"sourcesContent":["/**\n * DrizzleEventBus — Postgres-backed event bus using the transactional outbox pattern.\n *\n * Events are inserted into the `domain_events` table within the caller's\n * Drizzle transaction. A background polling loop (started on module init)\n * reads unprocessed events and dispatches them to registered subscribers.\n *\n * When the transaction rolls back, the event is never persisted — no\n * phantom events.\n *\n * Pool awareness (EVT-4):\n * - On `publish`/`publishMany` the backend writes `metadata.pool`,\n * `metadata.direction`, and `metadata.tenantId` into the first-class\n * `pool` / `direction` / `tenant_id` columns (metadata JSON is still\n * written unchanged for protocol stability).\n * - The drain loop filters by `opts.pools` when provided, so separate\n * processes (e.g. one per `events_inbound` / `events_change` /\n * `events_outbound`) can claim only their own lane. `pools: undefined`\n * drains all pending rows (backwards-compatible behaviour).\n *\n * EVT-Q7: No stale-event sweeper. `FOR UPDATE SKIP LOCKED` is\n * self-healing — the row is only locked for the duration of the\n * enclosing polling transaction; the `status='processed'` update happens\n * within that same transaction. There is no `claimed_at` semantic (unlike\n * jobs), so no stale rows can exist.\n *\n * This backend is suitable until you need real-time fan-out or very high\n * throughput. At that point, swap the backend for Redis Streams or similar\n * via EventsModule.forRoot({ backend: '...' }) without touching use cases.\n */\nimport { randomUUID } from 'node:crypto';\nimport { Injectable, OnModuleDestroy, OnModuleInit, Inject, Logger, Optional } from '@nestjs/common';\nimport { eq, and, inArray, asc, desc, gte, lt, lte, or, sql, type SQL } from 'drizzle-orm';\nimport type {\n DomainEvent,\n DrizzleTransaction,\n IEventBus,\n ScheduledEventSpec,\n} from './event-bus.protocol';\nimport type {\n EventPage,\n IEventReadPort,\n ListEventsQuery,\n} from './event-read.protocol';\nimport {\n clampEventLimit,\n decodeEventCursor,\n encodeEventCursor,\n} from './event-keyset-cursor';\nimport type { DrizzleClient } from '../../types/drizzle';\nimport { domainEvents, type DomainEventRecord } from './domain-events.schema';\nimport { DRIZZLE } from '../../constants/tokens';\nimport { EVENTS_MODULE_OPTIONS } from './events.tokens';\nimport type { EventsModuleOptions } from './events.module';\nimport { BRIDGE_OUTBOX_DRAIN_HOOK } from '../bridge/bridge.tokens';\nimport type { IBridgeOutboxDrainHook } from '../bridge/bridge.protocol';\nimport {\n EVENTS_WAKE_CHANNEL,\n PgNotifyListener,\n pgNotify,\n} from '../jobs/pg-notify';\n\n/** How long to wait between polling cycles (ms). */\nconst POLL_INTERVAL_MS = 1_000;\n/** Max events claimed per polling cycle to bound memory usage. */\nconst POLL_BATCH_SIZE = 50;\n\n/**\n * Row shape built from `metadata` for writing into `domain_events`. Keeps\n * the per-event extraction logic in one place so publish/publishMany stay\n * in sync.\n */\nfunction toInsertValues(event: DomainEvent, multiTenant: boolean) {\n const metadata = event.metadata ?? undefined;\n const pool = (metadata?.['pool'] as string | undefined) ?? null;\n const direction = (metadata?.['direction'] as string | undefined) ?? null;\n // AUDIT-1: tier defaults to 'domain' when absent. The DB CHECK\n // constraint (`domain_events_tier_routing_check`) enforces the\n // tier ⇔ routing-fields invariant at the storage boundary; no\n // JS-side assertion is needed here.\n const tier = (metadata?.['tier'] as string | undefined) ?? 'domain';\n const base = {\n id: event.id,\n type: event.type,\n aggregateId: event.aggregateId,\n aggregateType: event.aggregateType,\n payload: event.payload,\n occurredAt: event.occurredAt,\n processedAt: null,\n status: 'pending' as const,\n metadata: event.metadata,\n pool,\n direction,\n tier,\n };\n // EVT-8: `tenant_id` is a scaffold-time conditional column, emitted only\n // when `events.multi_tenant: true`. Only write it when multi-tenancy is\n // on — under single-tenant scaffolds the column does not exist, so the\n // key must be omitted from the insert.\n if (!multiTenant) return base;\n const tenantId = (metadata?.['tenantId'] as string | undefined) ?? null;\n return { ...base, tenantId };\n}\n\n/**\n * Project a raw `domain_events` row into the narrow `EventSummary` shape.\n * Shared with the memory backend via this helper kept module-local to each\n * backend (the events subsystem has no cross-backend projection file yet;\n * the two are byte-identical and small).\n */\nfunction toEventSummary(r: DomainEventRecord) {\n const metadata = (r.metadata ?? undefined) as\n | Record<string, unknown>\n | undefined;\n const rootRunId = metadata?.['rootRunId'];\n return {\n id: r.id,\n type: r.type,\n aggregateId: r.aggregateId,\n aggregateType: r.aggregateType,\n status: r.status,\n pool: r.pool,\n direction: r.direction,\n tier: r.tier,\n rootRunId: typeof rootRunId === 'string' ? rootRunId : null,\n // EVT-8: `tenant_id` is a scaffold-time conditional column. Read it\n // structurally so this projection typechecks against both the\n // multi-tenant schema (column present) and the single-tenant schema\n // (column absent → undefined → null).\n tenantId: (r as { tenantId?: string | null }).tenantId ?? null,\n occurredAt:\n r.occurredAt instanceof Date\n ? r.occurredAt\n : new Date(r.occurredAt as unknown as string),\n processedAt:\n r.processedAt == null\n ? null\n : r.processedAt instanceof Date\n ? r.processedAt\n : new Date(r.processedAt as unknown as string),\n };\n}\n\n/**\n * Postgres unique-violation (SQLSTATE 23505) test. Used by the scheduled-event\n * materialiser (ADR-039) to treat a slot-key collision as the\n * already-materialised no-op. Reads `.code` defensively across driver shapes\n * (node-postgres surfaces it on the error, some wrappers nest it on `.cause`).\n */\nfunction isUniqueViolation(err: unknown): boolean {\n const code = (err as { code?: unknown; cause?: { code?: unknown } } | undefined);\n return code?.code === '23505' || code?.cause?.code === '23505';\n}\n\n@Injectable()\nexport class DrizzleEventBus implements IEventBus, IEventReadPort, OnModuleInit, OnModuleDestroy {\n private readonly logger = new Logger(DrizzleEventBus.name);\n private polling = false;\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly handlers = new Map<string, Set<(event: DomainEvent) => Promise<void>>>();\n private readonly opts: EventsModuleOptions;\n\n // LISTEN-NOTIFY-1 — dedicated wake listener + debounce state. `null` when\n // `listenNotify` is off (the common case); polling is the only driver then.\n private notifyListener: PgNotifyListener | null = null;\n /** True while a wake-driven drain is in flight (debounce gate). */\n private wakeDraining = false;\n /** A notify arrived mid-drain → re-drain once when the current drain ends. */\n private wakeRecheckPending = false;\n\n constructor(\n @Inject(DRIZZLE) private readonly db: DrizzleClient,\n @Optional() @Inject(EVENTS_MODULE_OPTIONS) opts?: EventsModuleOptions,\n /**\n * Bridge subsystem hook (BRIDGE-4). Optional — when the bridge\n * subsystem is not installed in the consuming app, this token is\n * undefined and the drain skips the bridge block entirely (preserves\n * EVT-4 baseline behaviour).\n *\n * When provided, `processEvent` is invoked once per drained event\n * INSIDE the per-event tx, before `processed_at` is stamped. The\n * hook owns all knowledge of `bridge_delivery + wrapper job_run`\n * shapes; the events subsystem stays unaware of bridge schemas.\n */\n @Optional()\n @Inject(BRIDGE_OUTBOX_DRAIN_HOOK)\n private readonly bridgeHook: IBridgeOutboxDrainHook | null = null,\n ) {\n // Default so direct construction (e.g. integration tests not going\n // through Nest DI) keeps working without an explicit options object.\n this.opts = opts ?? { backend: 'drizzle' };\n }\n\n // ============================================================================\n // Lifecycle\n // ============================================================================\n\n async onModuleInit(): Promise<void> {\n this.polling = true;\n this.schedulePoll();\n\n // LISTEN-NOTIFY-1 — start the wake listener ALONGSIDE the poll timer. A\n // notify for one of this drainer's pools triggers an immediate drain; the\n // interval timer above stays the durability heartbeat. Startup is\n // fire-and-forget — a connect failure self-heals via the listener's backoff.\n if (this.opts.listenNotify) {\n const pool = (this.db as unknown as { $client?: unknown }).$client;\n if (!pool || typeof (pool as { connect?: unknown }).connect !== 'function') {\n this.logger.warn(\n `listen_notify enabled but the Drizzle client exposes no pg Pool ` +\n `($client.connect missing) — falling back to interval polling only.`,\n );\n } else {\n this.notifyListener = new PgNotifyListener({\n channel: EVENTS_WAKE_CHANNEL,\n pool: pool as { connect(): Promise<never> },\n label: 'events',\n onNotify: (payload) => this.onWake(payload),\n });\n await this.notifyListener.start();\n }\n }\n }\n\n async onModuleDestroy(): Promise<void> {\n this.polling = false;\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.notifyListener) {\n try {\n await this.notifyListener.stop();\n } catch (err) {\n this.logger.error(`notify listener stop failed: ${err}`);\n }\n this.notifyListener = null;\n }\n }\n\n /**\n * Wake handler — a `codegen_events_wake` notification arrived. A pool-filtered\n * drainer (`opts.pools` set) ignores payloads naming a pool it doesn't own; an\n * all-pools drainer wakes for any. Debounced: a notify mid-drain just flags a\n * re-check so a burst collapses to at most one extra drain (D3).\n */\n private onWake(payload: string): void {\n if (!this.polling) return;\n const pools = this.opts.pools;\n if (pools && pools.length > 0 && !pools.includes(payload)) return;\n if (this.wakeDraining) {\n this.wakeRecheckPending = true;\n return;\n }\n void this.drainOnWake();\n }\n\n private async drainOnWake(): Promise<void> {\n this.wakeDraining = true;\n try {\n do {\n this.wakeRecheckPending = false;\n await this.processBatch();\n } while (this.wakeRecheckPending && this.polling);\n } catch (err) {\n this.logger.error(`wake drain error: ${err}`);\n } finally {\n this.wakeDraining = false;\n }\n }\n\n // ============================================================================\n // IEventBus\n // ============================================================================\n\n async publish(event: DomainEvent, tx?: DrizzleTransaction): Promise<void> {\n const client = (tx ?? this.db) as DrizzleClient;\n const multiTenant = this.opts.multiTenant ?? false;\n const values = toInsertValues(event, multiTenant);\n await client.insert(domainEvents).values(values);\n // LISTEN-NOTIFY-1 — wake the drainer on commit (D2: emitted through the same\n // `client`, so a rolled-back publish emits no phantom wake). The pool is the\n // payload; the drainer re-runs its own pool-filtered claim on wake.\n await this.emitWakeNotify(client, [values.pool]);\n }\n\n async publishMany(events: DomainEvent[], tx?: DrizzleTransaction): Promise<void> {\n if (events.length === 0) return;\n const client = (tx ?? this.db) as DrizzleClient;\n const multiTenant = this.opts.multiTenant ?? false;\n const valuesList = events.map((e) => toInsertValues(e, multiTenant));\n await client.insert(domainEvents).values(valuesList);\n // De-dup pools so a batch into one lane emits a single wake.\n await this.emitWakeNotify(client, valuesList.map((v) => v.pool));\n }\n\n /**\n * Emit one in-tx `pg_notify(codegen_events_wake, <pool>)` per distinct pool in\n * the just-inserted batch. No-op unless `listenNotify` is on. Best-effort: a\n * notify failure is non-fatal (interval polling still drains the rows), so we\n * log + swallow rather than failing the publish.\n */\n private async emitWakeNotify(\n client: DrizzleClient,\n pools: Array<string | null>,\n ): Promise<void> {\n if (!this.opts.listenNotify) return;\n const distinct = new Set(pools.map((p) => p ?? ''));\n for (const pool of distinct) {\n try {\n await pgNotify(client, EVENTS_WAKE_CHANNEL, pool);\n } catch (err) {\n this.logger.warn(\n `pg_notify(${EVENTS_WAKE_CHANNEL}, '${pool}') failed: ${err} ` +\n `(non-fatal — interval polling still drains the outbox).`,\n );\n }\n }\n }\n\n async findById(eventId: string): Promise<DomainEvent | null> {\n const rows = await this.db\n .select()\n .from(domainEvents)\n .where(eq(domainEvents.id, eventId))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n return {\n id: row.id,\n type: row.type,\n aggregateId: row.aggregateId,\n aggregateType: row.aggregateType,\n payload: row.payload as Record<string, unknown>,\n occurredAt:\n row.occurredAt instanceof Date\n ? row.occurredAt\n : new Date(row.occurredAt as unknown as string),\n metadata: (row.metadata ?? undefined) as\n | Record<string, unknown>\n | undefined,\n };\n }\n\n subscribe<T extends DomainEvent = DomainEvent>(\n eventType: string,\n handler: (event: T) => Promise<void>,\n ): () => void {\n if (!this.handlers.has(eventType)) {\n this.handlers.set(eventType, new Set());\n }\n const set = this.handlers.get(eventType)!;\n const h = handler as (event: DomainEvent) => Promise<void>;\n set.add(h);\n return () => {\n set.delete(h);\n };\n }\n\n // ============================================================================\n // ADR-039 — scheduled-event materialisation (time as an event source)\n // ============================================================================\n\n /**\n * Insert one scheduled tick event idempotently. The slot key is stamped onto\n * `metadata.scheduleSlot`; `ON CONFLICT DO NOTHING` against the partial UNIQUE\n * expression index `idx_domain_events_schedule_slot` makes a duplicate insert\n * a no-op — the DB constraint is the exactly-one-event-per-slot invariant.\n *\n * Reuses the standard outbox row shape (pool/direction/metadata) so the\n * existing drain carries the tick like any other event. A LISTEN/NOTIFY wake\n * fires for an immediately-due tick (boot/catch-up rows whose slot is already\n * in the past); a future slot is claimed by polling once `occurred_at` passes.\n */\n async materializeScheduledEvent(\n spec: ScheduledEventSpec,\n ): Promise<{ created: boolean }> {\n const multiTenant = this.opts.multiTenant ?? false;\n const metadata: Record<string, unknown> = {\n pool: spec.pool,\n direction: spec.direction,\n scheduleSlot: spec.slotKey,\n triggerSource: 'schedule',\n };\n const base = {\n id: randomUUID(),\n type: spec.type,\n // Payload-free scheduled fact (the dealbrain strict-producer pattern).\n aggregateId: spec.type,\n aggregateType: spec.type,\n payload: {} as Record<string, unknown>,\n occurredAt: spec.slotStart,\n processedAt: null,\n status: 'pending' as const,\n metadata,\n pool: spec.pool,\n direction: spec.direction,\n tier: 'domain' as const,\n };\n const values = multiTenant ? { ...base, tenantId: null } : base;\n\n // The idempotency guard is the partial UNIQUE expression index\n // `idx_domain_events_schedule_slot` on (type, metadata->>'scheduleSlot').\n // Use a BARE (no-target) `ON CONFLICT DO NOTHING`: Drizzle 0.45's typed\n // `onConflictDoNothing({ target })` only accepts columns so it can't NAME\n // the expression index, but the no-arg form emits target-less\n // `ON CONFLICT DO NOTHING`, which Postgres applies to ANY unique\n // constraint/index — including this expression index. `.returning({ id })`\n // then gives us the rowcount discriminator: zero rows back == the slot was\n // already materialised (DO NOTHING fired), so `created: false`. This keeps\n // the happy path off the exception channel — a repeat materialise no longer\n // raises SQLSTATE 23505, so Postgres logs no scary `duplicate key value\n // violates unique constraint` ERROR line on every colliding boot/tick.\n //\n // The unique-violation catch is retained as a fallback for the genuine\n // concurrent-insert race window (two sessions clear the conflict check and\n // both attempt the insert in the same instant) and for backends whose\n // driver surfaces a 23505 rather than honouring DO NOTHING; in both cases\n // it collapses to the same `created: false` no-op.\n let inserted: Array<{ id: string }>;\n try {\n inserted = await this.db\n .insert(domainEvents)\n .values(values)\n .onConflictDoNothing()\n .returning({ id: domainEvents.id });\n } catch (err) {\n if (isUniqueViolation(err)) return { created: false };\n throw err;\n }\n if (inserted.length === 0) return { created: false };\n\n // Wake the drainer for an already-due tick. A future slot waits for polling.\n if (spec.slotStart.getTime() <= Date.now()) {\n await this.emitWakeNotify(this.db, [spec.pool]);\n }\n return { created: true };\n }\n\n /** Most recent scheduled tick's `occurred_at` (epoch ms) for `type`, or null.\n * Read by the scheduler's catch-up backfill. */\n async lastScheduledSlotMs(type: string): Promise<number | null> {\n const rows = await this.db\n .select({ occurredAt: domainEvents.occurredAt })\n .from(domainEvents)\n .where(\n and(\n eq(domainEvents.type, type),\n sql`${domainEvents.metadata} ->> 'triggerSource' = 'schedule'`,\n ),\n )\n .orderBy(desc(domainEvents.occurredAt))\n .limit(1);\n const row = rows[0];\n if (!row?.occurredAt) return null;\n return row.occurredAt instanceof Date\n ? row.occurredAt.getTime()\n : new Date(row.occurredAt as unknown as string).getTime();\n }\n\n // ============================================================================\n // IEventReadPort (OBS-LIST-1)\n // ============================================================================\n\n async listEvents(query: ListEventsQuery = {}): Promise<EventPage> {\n const limit = clampEventLimit(query.limit);\n const conditions: SQL<unknown>[] = [];\n\n if (query.poolId) conditions.push(eq(domainEvents.pool, query.poolId));\n if (query.direction)\n conditions.push(eq(domainEvents.direction, query.direction));\n if (query.since) conditions.push(gte(domainEvents.occurredAt, query.since));\n if (query.rootRunId) {\n // Filter on the JSON correlation id: metadata->>'rootRunId'.\n conditions.push(\n sql`${domainEvents.metadata}->>'rootRunId' = ${query.rootRunId}`,\n );\n }\n // EVT-8: `tenant_id` is a scaffold-time conditional column (emitted only\n // under `events.multi_tenant: true`). Guard the filter behind the same\n // `multiTenant` flag, and read the column structurally so this backend\n // typechecks against both the multi-tenant schema (column present) and\n // the single-tenant schema (column absent). When multi-tenancy is off\n // there is no `tenant_id` column to filter on.\n if (this.opts.multiTenant && query.tenantId !== undefined) {\n const tenantIdColumn = (\n domainEvents as unknown as { tenantId: typeof domainEvents.pool }\n ).tenantId;\n conditions.push(\n query.tenantId === null\n ? (sql`${tenantIdColumn} is null` as SQL<unknown>)\n : eq(tenantIdColumn, query.tenantId),\n );\n }\n\n // Keyset seek: WHERE (occurred_at, id) < (cursorOccurredAt, cursorId).\n if (query.cursor) {\n const keyset = decodeEventCursor(query.cursor);\n if (keyset) {\n conditions.push(\n or(\n lt(domainEvents.occurredAt, keyset.occurredAt),\n and(\n eq(domainEvents.occurredAt, keyset.occurredAt),\n lt(domainEvents.id, keyset.id),\n ),\n )!,\n );\n }\n }\n\n const rows = (await this.db\n .select()\n .from(domainEvents)\n .where(conditions.length > 0 ? and(...conditions) : undefined)\n .orderBy(desc(domainEvents.occurredAt), desc(domainEvents.id))\n .limit(limit + 1)) as DomainEventRecord[];\n\n const hasMore = rows.length > limit;\n const page = hasMore ? rows.slice(0, limit) : rows;\n const items = page.map(toEventSummary);\n const last = page[page.length - 1];\n const nextCursor =\n hasMore && last\n ? encodeEventCursor({ occurredAt: last.occurredAt, id: last.id })\n : null;\n\n return { items, nextCursor };\n }\n\n // ============================================================================\n // Polling\n // ============================================================================\n\n /**\n * Test-only hook. Runs exactly one drain cycle and returns. Production\n * code goes through `onModuleInit` → `schedulePoll`, which calls the\n * same `processBatch` under a timer.\n */\n async drainOnce(): Promise<void> {\n await this.processBatch();\n }\n\n private schedulePoll(): void {\n if (!this.polling) return;\n this.pollTimer = setTimeout(async () => {\n try {\n await this.processBatch();\n } catch (err) {\n this.logger.error(`Poll cycle error: ${err}`);\n } finally {\n this.schedulePoll();\n }\n }, POLL_INTERVAL_MS);\n }\n\n /**\n * Drain one batch (BRIDGE-4 restructure of EVT-4).\n *\n * Two-phase per drained event:\n *\n * 1. **Per-event transaction** — bridge fanout (`bridgeHook.processEvent`)\n * + `processed_at` stamp. Both write through the same `tx`. A throw\n * inside the tx (only infra-level failures should reach here, since\n * the hook tolerates null direction and registry misses inline)\n * rolls back the bridge inserts AND the `processed_at` stamp; the\n * event re-claims on the next drain cycle. Bridge `UNIQUE\n * (event_id, trigger_id)` makes the retry idempotent.\n *\n * 2. **After commit** — dispatch in-process subscribers (`IEventBus.subscribe`\n * handlers). This deliberately runs OUTSIDE the per-event tx (lead\n * decision 2026-04-22): subscribers are best-effort and must not\n * gate forward progress or roll back bridge fanout. Subscriber\n * errors are caught + logged; `processed_at` is already committed.\n * The old `MAX_RETRIES=3` in-process retry loop and the\n * `failed`-stamping path were removed in BRIDGE-4 along with their\n * coupling.\n *\n * The `processed_at` UPDATE carries `AND status='pending'` (BRIDGE-4\n * tightening — without it, a hypothetical double-claim could double-stamp\n * the timestamp). The per-event tx + `FOR UPDATE SKIP LOCKED` claim\n * make this defensive belt-and-suspenders.\n */\n private async processBatch(): Promise<void> {\n const pools = this.opts.pools;\n\n // Build WHERE: status='pending' AND occurred_at <= now [AND pool IN (...)].\n //\n // The readiness gate (`occurred_at <= now`) is what makes a scheduler-\n // materialised *future* slot wait. The EventScheduler pre-inserts the next\n // slot with `occurred_at = slotStart` in the future and deliberately does\n // NOT NOTIFY-wake the drainer for it (see materializeScheduledEvent: a\n // future slot is claimed by polling once its `occurred_at` passes). Without\n // this predicate the claim is status-only, so the very next poll grabs the\n // future-dated row and stamps `processed_at = now()` early — surfacing rows\n // that read \"N minutes from now\" yet are already processed, and firing\n // scheduled triggers up to one interval ahead of their slot. Normal events\n // publish with `occurred_at = now()`, so the gate is transparent to them.\n const ready = lte(domainEvents.occurredAt, new Date());\n const whereClause: SQL<unknown> = pools && pools.length > 0\n ? (and(eq(domainEvents.status, 'pending'), ready, inArray(domainEvents.pool, pools)) as SQL<unknown>)\n : (and(eq(domainEvents.status, 'pending'), ready) as SQL<unknown>);\n\n // Claim a batch with FOR UPDATE SKIP LOCKED so multiple pollers don't\n // double-dispatch. The lock is released when the outer transaction\n // commits — which is fine because the immediately-following per-event\n // tx flips status='processed' under its own `AND status='pending'`\n // guard, so a re-claim of the same row in a subsequent batch is a\n // no-op UPDATE.\n const rows = await this.db.transaction(async (tx) => {\n return tx\n .select()\n .from(domainEvents)\n .where(whereClause)\n .orderBy(asc(domainEvents.occurredAt))\n .limit(POLL_BATCH_SIZE)\n .for('update', { skipLocked: true });\n }) as Array<typeof domainEvents.$inferSelect>;\n\n for (const row of rows) {\n const event: DomainEvent = {\n id: row.id,\n type: row.type,\n aggregateId: row.aggregateId,\n aggregateType: row.aggregateType,\n payload: row.payload as Record<string, unknown>,\n occurredAt: row.occurredAt instanceof Date ? row.occurredAt : new Date(row.occurredAt as unknown as string),\n metadata: (row.metadata ?? undefined) as Record<string, unknown> | undefined,\n };\n\n // Phase 1 — per-event tx: bridge fanout + processed_at stamp.\n try {\n await this.db.transaction(async (tx) => {\n if (this.bridgeHook) {\n await this.bridgeHook.processEvent(event, tx);\n }\n await tx\n .update(domainEvents)\n .set({ status: 'processed', processedAt: new Date() })\n .where(\n and(\n eq(domainEvents.id, event.id),\n eq(domainEvents.status, 'pending'),\n ),\n );\n });\n } catch (err) {\n // Infra-level failure inside the per-event tx — bridge inserts\n // and processed_at both rolled back. Log and move on; the next\n // drain cycle re-claims the row. UNIQUE on bridge_delivery makes\n // the retry idempotent.\n this.logger.error(\n `Per-event tx failed for event id=${event.id} type=${event.type}: ${err}`,\n );\n continue;\n }\n\n // Phase 2 — best-effort subscriber dispatch. Errors are logged\n // and discarded; processed_at is already committed. Subscribers\n // are observability + cache-busts + small ancillary work; they\n // must not gate forward progress.\n try {\n await this.dispatch(event);\n } catch (err) {\n this.logger.error(\n `Subscriber dispatch failed for event id=${event.id} type=${event.type} ` +\n `(processed_at already committed; failure does not retry): ${err}`,\n );\n }\n }\n }\n\n private async dispatch(event: DomainEvent): Promise<void> {\n const set = this.handlers.get(event.type);\n if (!set) return;\n\n let firstError: unknown;\n for (const handler of set) {\n try {\n await handler(event);\n } catch (err) {\n this.logger.error(\n `Handler error for event type \"${event.type}\" (id: ${event.id}): ${err}`,\n );\n if (firstError === undefined) {\n firstError = err;\n }\n }\n }\n\n if (firstError !== undefined) {\n throw firstError;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./chunk-DUUCU77W.js";
|
|
11
11
|
import {
|
|
12
12
|
DrizzleEventBus
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-Y6UZMYGX.js";
|
|
14
14
|
import {
|
|
15
15
|
EVENTS_MODULE_OPTIONS,
|
|
16
16
|
EVENTS_MULTI_TENANT,
|
|
@@ -200,4 +200,4 @@ export {
|
|
|
200
200
|
EventSchedulerLifecycle,
|
|
201
201
|
EventsModule
|
|
202
202
|
};
|
|
203
|
-
//# sourceMappingURL=chunk-
|
|
203
|
+
//# sourceMappingURL=chunk-YHVZAL6U.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
JobsDomainModule
|
|
3
|
+
} from "./chunk-KS4BZHIA.js";
|
|
1
4
|
import {
|
|
2
5
|
JobWorker
|
|
3
6
|
} from "./chunk-7B7MMDOJ.js";
|
|
4
|
-
import {
|
|
5
|
-
JobsDomainModule
|
|
6
|
-
} from "./chunk-AC6T2JUX.js";
|
|
7
7
|
import {
|
|
8
8
|
BootValidationError,
|
|
9
9
|
ReservedPoolViolationError
|
|
@@ -295,4 +295,4 @@ export {
|
|
|
295
295
|
JobWorkerOrchestrator,
|
|
296
296
|
JobWorkerModule
|
|
297
297
|
};
|
|
298
|
-
//# sourceMappingURL=chunk-
|
|
298
|
+
//# sourceMappingURL=chunk-Z7YFYK6H.js.map
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
JunctionIntegrationRepository,
|
|
3
|
+
buildCompositeExternalId,
|
|
4
|
+
parseCompositeExternalId
|
|
5
|
+
} from "../../chunk-2FTZLDBP.js";
|
|
1
6
|
import {
|
|
2
7
|
KnowledgeEntityRepository
|
|
3
8
|
} from "../../chunk-NN7XZEGF.js";
|
|
@@ -13,6 +18,9 @@ import {
|
|
|
13
18
|
import {
|
|
14
19
|
WithAnalytics
|
|
15
20
|
} from "../../chunk-IBGER4YK.js";
|
|
21
|
+
import {
|
|
22
|
+
ActivityEntityService
|
|
23
|
+
} from "../../chunk-SJGEBMJT.js";
|
|
16
24
|
import {
|
|
17
25
|
BaseFindByIdUseCase,
|
|
18
26
|
BaseListUseCase
|
|
@@ -24,10 +32,15 @@ import {
|
|
|
24
32
|
IntegratedEntityService
|
|
25
33
|
} from "../../chunk-5AAA4LTE.js";
|
|
26
34
|
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
BaseService
|
|
36
|
+
} from "../../chunk-BPYZCEHS.js";
|
|
37
|
+
import {
|
|
38
|
+
buildChangeEvents,
|
|
39
|
+
buildLifecycleEvent,
|
|
40
|
+
diffSnapshots,
|
|
41
|
+
emitSafely,
|
|
42
|
+
entitySnapshot
|
|
43
|
+
} from "../../chunk-DAHWN63L.js";
|
|
31
44
|
import {
|
|
32
45
|
ActivityEntityRepository
|
|
33
46
|
} from "../../chunk-MKWQKKK7.js";
|
|
@@ -43,19 +56,6 @@ import {
|
|
|
43
56
|
withSuperuserScope,
|
|
44
57
|
withUserScope
|
|
45
58
|
} from "../../chunk-ZUKFQL6E.js";
|
|
46
|
-
import {
|
|
47
|
-
ActivityEntityService
|
|
48
|
-
} from "../../chunk-SJGEBMJT.js";
|
|
49
|
-
import {
|
|
50
|
-
BaseService
|
|
51
|
-
} from "../../chunk-BPYZCEHS.js";
|
|
52
|
-
import {
|
|
53
|
-
buildChangeEvents,
|
|
54
|
-
buildLifecycleEvent,
|
|
55
|
-
diffSnapshots,
|
|
56
|
-
emitSafely,
|
|
57
|
-
entitySnapshot
|
|
58
|
-
} from "../../chunk-DAHWN63L.js";
|
|
59
59
|
import "../../chunk-2E224ZSN.js";
|
|
60
60
|
export {
|
|
61
61
|
ActivityEntityRepository,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AnalyticsModule
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-DKKFTHHI.js";
|
|
4
|
+
import "../../../chunk-J37YWU7Y.js";
|
|
4
5
|
import "../../../chunk-7B3RYX45.js";
|
|
5
6
|
import "../../../chunk-6I7ULIN6.js";
|
|
6
|
-
import "../../../chunk-J37YWU7Y.js";
|
|
7
7
|
import "../../../chunk-GYGNEQSC.js";
|
|
8
8
|
import "../../../chunk-2E224ZSN.js";
|
|
9
9
|
export {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AnalyticsModule
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-DKKFTHHI.js";
|
|
4
|
+
import {
|
|
5
|
+
NoopAnalyticsBackend
|
|
6
|
+
} from "../../../chunk-J37YWU7Y.js";
|
|
4
7
|
import {
|
|
5
8
|
CubeAnalyticsBackend
|
|
6
9
|
} from "../../../chunk-7B3RYX45.js";
|
|
@@ -9,9 +12,6 @@ import {
|
|
|
9
12
|
CUBE_API_SECRET,
|
|
10
13
|
CUBE_API_URL
|
|
11
14
|
} from "../../../chunk-6I7ULIN6.js";
|
|
12
|
-
import {
|
|
13
|
-
NoopAnalyticsBackend
|
|
14
|
-
} from "../../../chunk-J37YWU7Y.js";
|
|
15
15
|
import "../../../chunk-GYGNEQSC.js";
|
|
16
16
|
import "../../../chunk-2E224ZSN.js";
|
|
17
17
|
export {
|
|
@@ -6,8 +6,8 @@ import "../../../chunk-N5OTOWTP.js";
|
|
|
6
6
|
import "../../../chunk-QLTJSCE6.js";
|
|
7
7
|
import "../../../chunk-BPARRK6F.js";
|
|
8
8
|
import "../../../chunk-SZVPIHWE.js";
|
|
9
|
-
import "../../../chunk-6XY6ZMMD.js";
|
|
10
9
|
import "../../../chunk-NPFPZ2HO.js";
|
|
10
|
+
import "../../../chunk-6XY6ZMMD.js";
|
|
11
11
|
import "../../../chunk-GYGNEQSC.js";
|
|
12
12
|
import "../../../chunk-U64T4YZE.js";
|
|
13
13
|
import "../../../chunk-2E224ZSN.js";
|
|
@@ -35,6 +35,9 @@ import {
|
|
|
35
35
|
import {
|
|
36
36
|
AuthController
|
|
37
37
|
} from "../../../chunk-SZVPIHWE.js";
|
|
38
|
+
import {
|
|
39
|
+
authOAuthState
|
|
40
|
+
} from "../../../chunk-NPFPZ2HO.js";
|
|
38
41
|
import {
|
|
39
42
|
AUTH_CONNECTION_GRANT_SINK,
|
|
40
43
|
AUTH_CONNECTION_READER,
|
|
@@ -45,9 +48,6 @@ import {
|
|
|
45
48
|
OAUTH_STATE_STORE,
|
|
46
49
|
STRATEGY_REGISTRY
|
|
47
50
|
} from "../../../chunk-6XY6ZMMD.js";
|
|
48
|
-
import {
|
|
49
|
-
authOAuthState
|
|
50
|
-
} from "../../../chunk-NPFPZ2HO.js";
|
|
51
51
|
import "../../../chunk-GYGNEQSC.js";
|
|
52
52
|
import "../../../chunk-U64T4YZE.js";
|
|
53
53
|
import "../../../chunk-ZUKFQL6E.js";
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BridgeModule
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-36NRG2EP.js";
|
|
4
4
|
import "../../../chunk-5A432NZJ.js";
|
|
5
|
+
import "../../../chunk-E5FJWOMP.js";
|
|
5
6
|
import "../../../chunk-7OVCARTQ.js";
|
|
6
7
|
import "../../../chunk-EDKJU5BO.js";
|
|
7
|
-
import "../../../chunk-MVKW2BCR.js";
|
|
8
|
-
import "../../../chunk-4DOJBQTP.js";
|
|
9
|
-
import "../../../chunk-E5FJWOMP.js";
|
|
10
8
|
import "../../../chunk-R6F6KFIL.js";
|
|
9
|
+
import "../../../chunk-MVKW2BCR.js";
|
|
11
10
|
import "../../../chunk-6DWFJNIK.js";
|
|
11
|
+
import "../../../chunk-4DOJBQTP.js";
|
|
12
12
|
import "../../../chunk-BORNCTH3.js";
|
|
13
13
|
import "../../../chunk-NXXDZ6ZF.js";
|
|
14
|
-
import "../../../chunk-
|
|
14
|
+
import "../../../chunk-Z7YFYK6H.js";
|
|
15
|
+
import "../../../chunk-KS4BZHIA.js";
|
|
16
|
+
import "../../../chunk-BHZP6LOV.js";
|
|
17
|
+
import "../../../chunk-DV4RV2DC.js";
|
|
15
18
|
import "../../../chunk-7B7MMDOJ.js";
|
|
16
|
-
import "../../../chunk-
|
|
19
|
+
import "../../../chunk-E6PLM6QG.js";
|
|
17
20
|
import "../../../chunk-VQOAATIG.js";
|
|
18
21
|
import "../../../chunk-PNZSGAB2.js";
|
|
19
|
-
import "../../../chunk-3VEVGL74.js";
|
|
20
|
-
import "../../../chunk-IN3EWFB4.js";
|
|
21
22
|
import "../../../chunk-SNQ3TOWP.js";
|
|
22
|
-
import "../../../chunk-
|
|
23
|
-
import "../../../chunk-DV4RV2DC.js";
|
|
24
|
-
import "../../../chunk-E6PLM6QG.js";
|
|
23
|
+
import "../../../chunk-VNBC3VXM.js";
|
|
25
24
|
import "../../../chunk-T4BIIU5E.js";
|
|
25
|
+
import "../../../chunk-L3LZWWSX.js";
|
|
26
26
|
import "../../../chunk-I6MVCB5A.js";
|
|
27
27
|
import "../../../chunk-RHVN6NA7.js";
|
|
28
28
|
import "../../../chunk-Q6LRJ4VI.js";
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BridgeModule
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-36NRG2EP.js";
|
|
4
4
|
import "../../../chunk-5A432NZJ.js";
|
|
5
|
+
import {
|
|
6
|
+
BridgeOutboxDrainHook
|
|
7
|
+
} from "../../../chunk-E5FJWOMP.js";
|
|
5
8
|
import {
|
|
6
9
|
EventFlowService
|
|
7
10
|
} from "../../../chunk-7OVCARTQ.js";
|
|
8
11
|
import {
|
|
9
12
|
BRIDGE_RESERVED_POOLS
|
|
10
13
|
} from "../../../chunk-EDKJU5BO.js";
|
|
11
|
-
import {
|
|
12
|
-
DrizzleBridgeDeliveryRepo
|
|
13
|
-
} from "../../../chunk-MVKW2BCR.js";
|
|
14
|
-
import {
|
|
15
|
-
MemoryBridgeDeliveryRepo
|
|
16
|
-
} from "../../../chunk-4DOJBQTP.js";
|
|
17
|
-
import {
|
|
18
|
-
BridgeOutboxDrainHook
|
|
19
|
-
} from "../../../chunk-E5FJWOMP.js";
|
|
20
14
|
import {
|
|
21
15
|
BRIDGE_DELIVERY_JOB_TYPE,
|
|
22
16
|
BridgeDeliveryHandler
|
|
23
17
|
} from "../../../chunk-R6F6KFIL.js";
|
|
18
|
+
import {
|
|
19
|
+
DrizzleBridgeDeliveryRepo
|
|
20
|
+
} from "../../../chunk-MVKW2BCR.js";
|
|
24
21
|
import {
|
|
25
22
|
assertTenantId
|
|
26
23
|
} from "../../../chunk-6DWFJNIK.js";
|
|
24
|
+
import {
|
|
25
|
+
MemoryBridgeDeliveryRepo
|
|
26
|
+
} from "../../../chunk-4DOJBQTP.js";
|
|
27
27
|
import {
|
|
28
28
|
bridgeDelivery,
|
|
29
29
|
bridgeDeliveryStatusEnum
|
|
@@ -33,18 +33,18 @@ import {
|
|
|
33
33
|
MissingTenantIdError,
|
|
34
34
|
UniqueConstraintError
|
|
35
35
|
} from "../../../chunk-NXXDZ6ZF.js";
|
|
36
|
-
import "../../../chunk-
|
|
36
|
+
import "../../../chunk-Z7YFYK6H.js";
|
|
37
|
+
import "../../../chunk-KS4BZHIA.js";
|
|
38
|
+
import "../../../chunk-BHZP6LOV.js";
|
|
39
|
+
import "../../../chunk-DV4RV2DC.js";
|
|
37
40
|
import "../../../chunk-7B7MMDOJ.js";
|
|
38
|
-
import "../../../chunk-
|
|
41
|
+
import "../../../chunk-E6PLM6QG.js";
|
|
39
42
|
import "../../../chunk-VQOAATIG.js";
|
|
40
43
|
import "../../../chunk-PNZSGAB2.js";
|
|
41
|
-
import "../../../chunk-3VEVGL74.js";
|
|
42
|
-
import "../../../chunk-IN3EWFB4.js";
|
|
43
44
|
import "../../../chunk-SNQ3TOWP.js";
|
|
44
|
-
import "../../../chunk-
|
|
45
|
-
import "../../../chunk-DV4RV2DC.js";
|
|
46
|
-
import "../../../chunk-E6PLM6QG.js";
|
|
45
|
+
import "../../../chunk-VNBC3VXM.js";
|
|
47
46
|
import "../../../chunk-T4BIIU5E.js";
|
|
47
|
+
import "../../../chunk-L3LZWWSX.js";
|
|
48
48
|
import "../../../chunk-I6MVCB5A.js";
|
|
49
49
|
import "../../../chunk-RHVN6NA7.js";
|
|
50
50
|
import "../../../chunk-Q6LRJ4VI.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CacheModule
|
|
3
|
-
} from "../../../chunk-
|
|
4
|
-
import "../../../chunk-T6C4LFLC.js";
|
|
3
|
+
} from "../../../chunk-7625PLY7.js";
|
|
5
4
|
import "../../../chunk-IF5I3DAA.js";
|
|
5
|
+
import "../../../chunk-T6C4LFLC.js";
|
|
6
6
|
import "../../../chunk-FASRXRX5.js";
|
|
7
7
|
import "../../../chunk-L6FTY45T.js";
|
|
8
8
|
import "../../../chunk-GYGNEQSC.js";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import "../../../chunk-IWAOY6KC.js";
|
|
2
2
|
import {
|
|
3
3
|
CacheModule
|
|
4
|
-
} from "../../../chunk-
|
|
5
|
-
import {
|
|
6
|
-
DrizzleCacheService
|
|
7
|
-
} from "../../../chunk-T6C4LFLC.js";
|
|
4
|
+
} from "../../../chunk-7625PLY7.js";
|
|
8
5
|
import {
|
|
9
6
|
MemoryCacheService
|
|
10
7
|
} from "../../../chunk-IF5I3DAA.js";
|
|
8
|
+
import {
|
|
9
|
+
DrizzleCacheService
|
|
10
|
+
} from "../../../chunk-T6C4LFLC.js";
|
|
11
11
|
import {
|
|
12
12
|
cacheEntries
|
|
13
13
|
} from "../../../chunk-FASRXRX5.js";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EventSchedulerLifecycle,
|
|
3
3
|
EventsModule
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-YHVZAL6U.js";
|
|
5
5
|
import "../../../chunk-PBENHIN2.js";
|
|
6
6
|
import "../../../chunk-LQZESSM3.js";
|
|
7
7
|
import "../../../chunk-MU54DZCC.js";
|
|
8
8
|
import "../../../chunk-GOO5ZMYO.js";
|
|
9
9
|
import "../../../chunk-DUUCU77W.js";
|
|
10
10
|
import "../../../chunk-DUBZOXJC.js";
|
|
11
|
-
import "../../../chunk-
|
|
11
|
+
import "../../../chunk-Y6UZMYGX.js";
|
|
12
12
|
import "../../../chunk-UQ5EHOH2.js";
|
|
13
13
|
import "../../../chunk-Q6LRJ4VI.js";
|
|
14
14
|
import "../../../chunk-H5NH7KPE.js";
|
|
@@ -2,7 +2,7 @@ import "../../../chunk-SYVZ4MD2.js";
|
|
|
2
2
|
import {
|
|
3
3
|
EventSchedulerLifecycle,
|
|
4
4
|
EventsModule
|
|
5
|
-
} from "../../../chunk-
|
|
5
|
+
} from "../../../chunk-YHVZAL6U.js";
|
|
6
6
|
import {
|
|
7
7
|
TypedEventBus
|
|
8
8
|
} from "../../../chunk-PBENHIN2.js";
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from "../../../chunk-DUBZOXJC.js";
|
|
29
29
|
import {
|
|
30
30
|
DrizzleEventBus
|
|
31
|
-
} from "../../../chunk-
|
|
31
|
+
} from "../../../chunk-Y6UZMYGX.js";
|
|
32
32
|
import "../../../chunk-UQ5EHOH2.js";
|
|
33
33
|
import "../../../chunk-Q6LRJ4VI.js";
|
|
34
34
|
import {
|
|
@@ -26,39 +26,52 @@ import {
|
|
|
26
26
|
import {
|
|
27
27
|
ObservabilityError
|
|
28
28
|
} from "../../chunk-EWYCWP4H.js";
|
|
29
|
+
import "../../chunk-W4HOHZVF.js";
|
|
29
30
|
import "../../chunk-SYVZ4MD2.js";
|
|
30
31
|
import {
|
|
31
32
|
EventsModule
|
|
32
|
-
} from "../../chunk-
|
|
33
|
+
} from "../../chunk-YHVZAL6U.js";
|
|
33
34
|
import "../../chunk-PBENHIN2.js";
|
|
34
35
|
import "../../chunk-LQZESSM3.js";
|
|
35
36
|
import "../../chunk-MU54DZCC.js";
|
|
36
|
-
import "../../chunk-W4HOHZVF.js";
|
|
37
37
|
import {
|
|
38
38
|
MemoryEventBus
|
|
39
39
|
} from "../../chunk-GOO5ZMYO.js";
|
|
40
40
|
import "../../chunk-DUUCU77W.js";
|
|
41
41
|
import "../../chunk-DUBZOXJC.js";
|
|
42
|
-
import "../../chunk-
|
|
42
|
+
import "../../chunk-IWAOY6KC.js";
|
|
43
|
+
import {
|
|
44
|
+
CacheModule
|
|
45
|
+
} from "../../chunk-7625PLY7.js";
|
|
46
|
+
import {
|
|
47
|
+
MemoryCacheService
|
|
48
|
+
} from "../../chunk-IF5I3DAA.js";
|
|
49
|
+
import {
|
|
50
|
+
DrizzleEventBus
|
|
51
|
+
} from "../../chunk-Y6UZMYGX.js";
|
|
52
|
+
import "../../chunk-UQ5EHOH2.js";
|
|
53
|
+
import "../../chunk-Z7YFYK6H.js";
|
|
54
|
+
import "../../chunk-KS4BZHIA.js";
|
|
55
|
+
import "../../chunk-BHZP6LOV.js";
|
|
56
|
+
import "../../chunk-DV4RV2DC.js";
|
|
43
57
|
import "../../chunk-7B7MMDOJ.js";
|
|
44
|
-
import "../../chunk-
|
|
58
|
+
import "../../chunk-E6PLM6QG.js";
|
|
45
59
|
import "../../chunk-VQOAATIG.js";
|
|
46
60
|
import "../../chunk-PNZSGAB2.js";
|
|
47
|
-
import "../../chunk-3VEVGL74.js";
|
|
48
|
-
import "../../chunk-IN3EWFB4.js";
|
|
49
61
|
import "../../chunk-SNQ3TOWP.js";
|
|
50
|
-
import "../../chunk-
|
|
51
|
-
import "../../chunk-DV4RV2DC.js";
|
|
52
|
-
import "../../chunk-E6PLM6QG.js";
|
|
62
|
+
import "../../chunk-VNBC3VXM.js";
|
|
53
63
|
import "../../chunk-T4BIIU5E.js";
|
|
64
|
+
import "../../chunk-L3LZWWSX.js";
|
|
54
65
|
import "../../chunk-I6MVCB5A.js";
|
|
55
66
|
import "../../chunk-RHVN6NA7.js";
|
|
56
|
-
import {
|
|
57
|
-
DrizzleEventBus
|
|
58
|
-
} from "../../chunk-PNCOUFFI.js";
|
|
59
|
-
import "../../chunk-UQ5EHOH2.js";
|
|
60
|
-
import "../../chunk-IWAOY6KC.js";
|
|
61
67
|
import "../../chunk-Q6LRJ4VI.js";
|
|
68
|
+
import {
|
|
69
|
+
DrizzleCacheService
|
|
70
|
+
} from "../../chunk-T6C4LFLC.js";
|
|
71
|
+
import "../../chunk-FASRXRX5.js";
|
|
72
|
+
import {
|
|
73
|
+
CACHE
|
|
74
|
+
} from "../../chunk-L6FTY45T.js";
|
|
62
75
|
import "../../chunk-7P5ODGLA.js";
|
|
63
76
|
import "../../chunk-ZPL74UQN.js";
|
|
64
77
|
import {
|
|
@@ -95,19 +108,6 @@ import {
|
|
|
95
108
|
isSessionExpiredError
|
|
96
109
|
} from "../../chunk-7RELQJIN.js";
|
|
97
110
|
import "../../chunk-OSQRXVG2.js";
|
|
98
|
-
import {
|
|
99
|
-
CacheModule
|
|
100
|
-
} from "../../chunk-COGHTKXY.js";
|
|
101
|
-
import {
|
|
102
|
-
DrizzleCacheService
|
|
103
|
-
} from "../../chunk-T6C4LFLC.js";
|
|
104
|
-
import {
|
|
105
|
-
MemoryCacheService
|
|
106
|
-
} from "../../chunk-IF5I3DAA.js";
|
|
107
|
-
import "../../chunk-FASRXRX5.js";
|
|
108
|
-
import {
|
|
109
|
-
CACHE
|
|
110
|
-
} from "../../chunk-L6FTY45T.js";
|
|
111
111
|
import {
|
|
112
112
|
AuthModule
|
|
113
113
|
} from "../../chunk-7LKAMLV4.js";
|
|
@@ -126,6 +126,9 @@ import {
|
|
|
126
126
|
import {
|
|
127
127
|
AuthController
|
|
128
128
|
} from "../../chunk-SZVPIHWE.js";
|
|
129
|
+
import {
|
|
130
|
+
authOAuthState
|
|
131
|
+
} from "../../chunk-NPFPZ2HO.js";
|
|
129
132
|
import {
|
|
130
133
|
AUTH_CONNECTION_GRANT_SINK,
|
|
131
134
|
AUTH_CONNECTION_READER,
|
|
@@ -136,9 +139,6 @@ import {
|
|
|
136
139
|
OAUTH_STATE_STORE,
|
|
137
140
|
STRATEGY_REGISTRY
|
|
138
141
|
} from "../../chunk-6XY6ZMMD.js";
|
|
139
|
-
import {
|
|
140
|
-
authOAuthState
|
|
141
|
-
} from "../../chunk-NPFPZ2HO.js";
|
|
142
142
|
import "../../chunk-GYGNEQSC.js";
|
|
143
143
|
import "../../chunk-KVOWSC5S.js";
|
|
144
144
|
import "../../chunk-VCXOPBYY.js";
|
|
@@ -2,7 +2,16 @@ import "../../../chunk-W4HOHZVF.js";
|
|
|
2
2
|
import {
|
|
3
3
|
JobWorkerModule,
|
|
4
4
|
JobWorkerOrchestrator
|
|
5
|
-
} from "../../../chunk-
|
|
5
|
+
} from "../../../chunk-Z7YFYK6H.js";
|
|
6
|
+
import {
|
|
7
|
+
JobsDomainModule
|
|
8
|
+
} from "../../../chunk-KS4BZHIA.js";
|
|
9
|
+
import {
|
|
10
|
+
MemoryJobRunService
|
|
11
|
+
} from "../../../chunk-BHZP6LOV.js";
|
|
12
|
+
import {
|
|
13
|
+
DrizzleJobStepService
|
|
14
|
+
} from "../../../chunk-DV4RV2DC.js";
|
|
6
15
|
import {
|
|
7
16
|
JOB_WORKER_OPTIONS,
|
|
8
17
|
JobWorker,
|
|
@@ -12,30 +21,20 @@ import {
|
|
|
12
21
|
computeBackoff
|
|
13
22
|
} from "../../../chunk-7B7MMDOJ.js";
|
|
14
23
|
import {
|
|
15
|
-
|
|
16
|
-
} from "../../../chunk-
|
|
24
|
+
DrizzleJobOrchestrator
|
|
25
|
+
} from "../../../chunk-E6PLM6QG.js";
|
|
17
26
|
import {
|
|
18
27
|
MemoryJobOrchestrator
|
|
19
28
|
} from "../../../chunk-VQOAATIG.js";
|
|
20
29
|
import {
|
|
21
30
|
MemoryJobStepService
|
|
22
31
|
} from "../../../chunk-PNZSGAB2.js";
|
|
23
|
-
import {
|
|
24
|
-
DrizzleJobRunService
|
|
25
|
-
} from "../../../chunk-3VEVGL74.js";
|
|
26
|
-
import {
|
|
27
|
-
MemoryJobRunService
|
|
28
|
-
} from "../../../chunk-IN3EWFB4.js";
|
|
29
32
|
import {
|
|
30
33
|
MemoryJobStore
|
|
31
34
|
} from "../../../chunk-SNQ3TOWP.js";
|
|
32
|
-
import "../../../chunk-L3LZWWSX.js";
|
|
33
35
|
import {
|
|
34
|
-
|
|
35
|
-
} from "../../../chunk-
|
|
36
|
-
import {
|
|
37
|
-
DrizzleJobOrchestrator
|
|
38
|
-
} from "../../../chunk-E6PLM6QG.js";
|
|
36
|
+
DrizzleJobRunService
|
|
37
|
+
} from "../../../chunk-VNBC3VXM.js";
|
|
39
38
|
import {
|
|
40
39
|
BootValidationError,
|
|
41
40
|
JobCollisionError,
|
|
@@ -45,6 +44,7 @@ import {
|
|
|
45
44
|
MissingTenantIdError,
|
|
46
45
|
ReservedPoolViolationError
|
|
47
46
|
} from "../../../chunk-T4BIIU5E.js";
|
|
47
|
+
import "../../../chunk-L3LZWWSX.js";
|
|
48
48
|
import {
|
|
49
49
|
BULLMQ_CONNECTION,
|
|
50
50
|
BULLMQ_RESOLVED_CONFIG,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DrizzleJobRunService
|
|
3
|
-
} from "../../../chunk-
|
|
4
|
-
import "../../../chunk-L3LZWWSX.js";
|
|
3
|
+
} from "../../../chunk-VNBC3VXM.js";
|
|
5
4
|
import "../../../chunk-T4BIIU5E.js";
|
|
5
|
+
import "../../../chunk-L3LZWWSX.js";
|
|
6
6
|
import "../../../chunk-ZPL74UQN.js";
|
|
7
7
|
import "../../../chunk-OKXZ63IA.js";
|
|
8
8
|
import "../../../chunk-GYGNEQSC.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MemoryJobRunService
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-BHZP6LOV.js";
|
|
4
4
|
import "../../../chunk-SNQ3TOWP.js";
|
|
5
|
-
import "../../../chunk-L3LZWWSX.js";
|
|
6
5
|
import "../../../chunk-T4BIIU5E.js";
|
|
6
|
+
import "../../../chunk-L3LZWWSX.js";
|
|
7
7
|
import "../../../chunk-ZPL74UQN.js";
|
|
8
8
|
import "../../../chunk-GYGNEQSC.js";
|
|
9
9
|
import "../../../chunk-2E224ZSN.js";
|
|
@@ -2,18 +2,18 @@ import {
|
|
|
2
2
|
JOB_WORKER_MODULE_OPTIONS,
|
|
3
3
|
JobWorkerModule,
|
|
4
4
|
JobWorkerOrchestrator
|
|
5
|
-
} from "../../../chunk-
|
|
5
|
+
} from "../../../chunk-Z7YFYK6H.js";
|
|
6
|
+
import "../../../chunk-KS4BZHIA.js";
|
|
7
|
+
import "../../../chunk-BHZP6LOV.js";
|
|
8
|
+
import "../../../chunk-DV4RV2DC.js";
|
|
6
9
|
import "../../../chunk-7B7MMDOJ.js";
|
|
7
|
-
import "../../../chunk-
|
|
10
|
+
import "../../../chunk-E6PLM6QG.js";
|
|
8
11
|
import "../../../chunk-VQOAATIG.js";
|
|
9
12
|
import "../../../chunk-PNZSGAB2.js";
|
|
10
|
-
import "../../../chunk-3VEVGL74.js";
|
|
11
|
-
import "../../../chunk-IN3EWFB4.js";
|
|
12
13
|
import "../../../chunk-SNQ3TOWP.js";
|
|
13
|
-
import "../../../chunk-
|
|
14
|
-
import "../../../chunk-DV4RV2DC.js";
|
|
15
|
-
import "../../../chunk-E6PLM6QG.js";
|
|
14
|
+
import "../../../chunk-VNBC3VXM.js";
|
|
16
15
|
import "../../../chunk-T4BIIU5E.js";
|
|
16
|
+
import "../../../chunk-L3LZWWSX.js";
|
|
17
17
|
import "../../../chunk-I6MVCB5A.js";
|
|
18
18
|
import "../../../chunk-RHVN6NA7.js";
|
|
19
19
|
import "../../../chunk-Q6LRJ4VI.js";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
JobsDomainModule
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-KS4BZHIA.js";
|
|
4
|
+
import "../../../chunk-BHZP6LOV.js";
|
|
5
|
+
import "../../../chunk-DV4RV2DC.js";
|
|
6
|
+
import "../../../chunk-E6PLM6QG.js";
|
|
4
7
|
import "../../../chunk-VQOAATIG.js";
|
|
5
8
|
import "../../../chunk-PNZSGAB2.js";
|
|
6
|
-
import "../../../chunk-3VEVGL74.js";
|
|
7
|
-
import "../../../chunk-IN3EWFB4.js";
|
|
8
9
|
import "../../../chunk-SNQ3TOWP.js";
|
|
9
|
-
import "../../../chunk-
|
|
10
|
-
import "../../../chunk-DV4RV2DC.js";
|
|
11
|
-
import "../../../chunk-E6PLM6QG.js";
|
|
10
|
+
import "../../../chunk-VNBC3VXM.js";
|
|
12
11
|
import "../../../chunk-T4BIIU5E.js";
|
|
12
|
+
import "../../../chunk-L3LZWWSX.js";
|
|
13
13
|
import "../../../chunk-I6MVCB5A.js";
|
|
14
14
|
import "../../../chunk-RHVN6NA7.js";
|
|
15
15
|
import "../../../chunk-Q6LRJ4VI.js";
|
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
*/
|
|
31
31
|
import { randomUUID } from 'node:crypto';
|
|
32
32
|
import { Injectable, OnModuleDestroy, OnModuleInit, Inject, Logger, Optional } from '@nestjs/common';
|
|
33
|
-
import { eq, and, inArray, asc, desc, gte, lt, or, sql, type SQL } from 'drizzle-orm';
|
|
33
|
+
import { eq, and, inArray, asc, desc, gte, lt, lte, or, sql, type SQL } from 'drizzle-orm';
|
|
34
34
|
import type {
|
|
35
35
|
DomainEvent,
|
|
36
36
|
DrizzleTransaction,
|
|
@@ -584,10 +584,22 @@ export class DrizzleEventBus implements IEventBus, IEventReadPort, OnModuleInit,
|
|
|
584
584
|
private async processBatch(): Promise<void> {
|
|
585
585
|
const pools = this.opts.pools;
|
|
586
586
|
|
|
587
|
-
// Build WHERE: status='pending' [AND pool IN (...)]
|
|
587
|
+
// Build WHERE: status='pending' AND occurred_at <= now [AND pool IN (...)].
|
|
588
|
+
//
|
|
589
|
+
// The readiness gate (`occurred_at <= now`) is what makes a scheduler-
|
|
590
|
+
// materialised *future* slot wait. The EventScheduler pre-inserts the next
|
|
591
|
+
// slot with `occurred_at = slotStart` in the future and deliberately does
|
|
592
|
+
// NOT NOTIFY-wake the drainer for it (see materializeScheduledEvent: a
|
|
593
|
+
// future slot is claimed by polling once its `occurred_at` passes). Without
|
|
594
|
+
// this predicate the claim is status-only, so the very next poll grabs the
|
|
595
|
+
// future-dated row and stamps `processed_at = now()` early — surfacing rows
|
|
596
|
+
// that read "N minutes from now" yet are already processed, and firing
|
|
597
|
+
// scheduled triggers up to one interval ahead of their slot. Normal events
|
|
598
|
+
// publish with `occurred_at = now()`, so the gate is transparent to them.
|
|
599
|
+
const ready = lte(domainEvents.occurredAt, new Date());
|
|
588
600
|
const whereClause: SQL<unknown> = pools && pools.length > 0
|
|
589
|
-
? (and(eq(domainEvents.status, 'pending'), inArray(domainEvents.pool, pools)) as SQL<unknown>)
|
|
590
|
-
: eq(domainEvents.status, 'pending');
|
|
601
|
+
? (and(eq(domainEvents.status, 'pending'), ready, inArray(domainEvents.pool, pools)) as SQL<unknown>)
|
|
602
|
+
: (and(eq(domainEvents.status, 'pending'), ready) as SQL<unknown>);
|
|
591
603
|
|
|
592
604
|
// Claim a batch with FOR UPDATE SKIP LOCKED so multiple pollers don't
|
|
593
605
|
// double-dispatch. The lock is released when the outer transaction
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../runtime/subsystems/events/event-bus.drizzle-backend.ts"],"sourcesContent":["/**\n * DrizzleEventBus — Postgres-backed event bus using the transactional outbox pattern.\n *\n * Events are inserted into the `domain_events` table within the caller's\n * Drizzle transaction. A background polling loop (started on module init)\n * reads unprocessed events and dispatches them to registered subscribers.\n *\n * When the transaction rolls back, the event is never persisted — no\n * phantom events.\n *\n * Pool awareness (EVT-4):\n * - On `publish`/`publishMany` the backend writes `metadata.pool`,\n * `metadata.direction`, and `metadata.tenantId` into the first-class\n * `pool` / `direction` / `tenant_id` columns (metadata JSON is still\n * written unchanged for protocol stability).\n * - The drain loop filters by `opts.pools` when provided, so separate\n * processes (e.g. one per `events_inbound` / `events_change` /\n * `events_outbound`) can claim only their own lane. `pools: undefined`\n * drains all pending rows (backwards-compatible behaviour).\n *\n * EVT-Q7: No stale-event sweeper. `FOR UPDATE SKIP LOCKED` is\n * self-healing — the row is only locked for the duration of the\n * enclosing polling transaction; the `status='processed'` update happens\n * within that same transaction. There is no `claimed_at` semantic (unlike\n * jobs), so no stale rows can exist.\n *\n * This backend is suitable until you need real-time fan-out or very high\n * throughput. At that point, swap the backend for Redis Streams or similar\n * via EventsModule.forRoot({ backend: '...' }) without touching use cases.\n */\nimport { randomUUID } from 'node:crypto';\nimport { Injectable, OnModuleDestroy, OnModuleInit, Inject, Logger, Optional } from '@nestjs/common';\nimport { eq, and, inArray, asc, desc, gte, lt, or, sql, type SQL } from 'drizzle-orm';\nimport type {\n DomainEvent,\n DrizzleTransaction,\n IEventBus,\n ScheduledEventSpec,\n} from './event-bus.protocol';\nimport type {\n EventPage,\n IEventReadPort,\n ListEventsQuery,\n} from './event-read.protocol';\nimport {\n clampEventLimit,\n decodeEventCursor,\n encodeEventCursor,\n} from './event-keyset-cursor';\nimport type { DrizzleClient } from '../../types/drizzle';\nimport { domainEvents, type DomainEventRecord } from './domain-events.schema';\nimport { DRIZZLE } from '../../constants/tokens';\nimport { EVENTS_MODULE_OPTIONS } from './events.tokens';\nimport type { EventsModuleOptions } from './events.module';\nimport { BRIDGE_OUTBOX_DRAIN_HOOK } from '../bridge/bridge.tokens';\nimport type { IBridgeOutboxDrainHook } from '../bridge/bridge.protocol';\nimport {\n EVENTS_WAKE_CHANNEL,\n PgNotifyListener,\n pgNotify,\n} from '../jobs/pg-notify';\n\n/** How long to wait between polling cycles (ms). */\nconst POLL_INTERVAL_MS = 1_000;\n/** Max events claimed per polling cycle to bound memory usage. */\nconst POLL_BATCH_SIZE = 50;\n\n/**\n * Row shape built from `metadata` for writing into `domain_events`. Keeps\n * the per-event extraction logic in one place so publish/publishMany stay\n * in sync.\n */\nfunction toInsertValues(event: DomainEvent, multiTenant: boolean) {\n const metadata = event.metadata ?? undefined;\n const pool = (metadata?.['pool'] as string | undefined) ?? null;\n const direction = (metadata?.['direction'] as string | undefined) ?? null;\n // AUDIT-1: tier defaults to 'domain' when absent. The DB CHECK\n // constraint (`domain_events_tier_routing_check`) enforces the\n // tier ⇔ routing-fields invariant at the storage boundary; no\n // JS-side assertion is needed here.\n const tier = (metadata?.['tier'] as string | undefined) ?? 'domain';\n const base = {\n id: event.id,\n type: event.type,\n aggregateId: event.aggregateId,\n aggregateType: event.aggregateType,\n payload: event.payload,\n occurredAt: event.occurredAt,\n processedAt: null,\n status: 'pending' as const,\n metadata: event.metadata,\n pool,\n direction,\n tier,\n };\n // EVT-8: `tenant_id` is a scaffold-time conditional column, emitted only\n // when `events.multi_tenant: true`. Only write it when multi-tenancy is\n // on — under single-tenant scaffolds the column does not exist, so the\n // key must be omitted from the insert.\n if (!multiTenant) return base;\n const tenantId = (metadata?.['tenantId'] as string | undefined) ?? null;\n return { ...base, tenantId };\n}\n\n/**\n * Project a raw `domain_events` row into the narrow `EventSummary` shape.\n * Shared with the memory backend via this helper kept module-local to each\n * backend (the events subsystem has no cross-backend projection file yet;\n * the two are byte-identical and small).\n */\nfunction toEventSummary(r: DomainEventRecord) {\n const metadata = (r.metadata ?? undefined) as\n | Record<string, unknown>\n | undefined;\n const rootRunId = metadata?.['rootRunId'];\n return {\n id: r.id,\n type: r.type,\n aggregateId: r.aggregateId,\n aggregateType: r.aggregateType,\n status: r.status,\n pool: r.pool,\n direction: r.direction,\n tier: r.tier,\n rootRunId: typeof rootRunId === 'string' ? rootRunId : null,\n // EVT-8: `tenant_id` is a scaffold-time conditional column. Read it\n // structurally so this projection typechecks against both the\n // multi-tenant schema (column present) and the single-tenant schema\n // (column absent → undefined → null).\n tenantId: (r as { tenantId?: string | null }).tenantId ?? null,\n occurredAt:\n r.occurredAt instanceof Date\n ? r.occurredAt\n : new Date(r.occurredAt as unknown as string),\n processedAt:\n r.processedAt == null\n ? null\n : r.processedAt instanceof Date\n ? r.processedAt\n : new Date(r.processedAt as unknown as string),\n };\n}\n\n/**\n * Postgres unique-violation (SQLSTATE 23505) test. Used by the scheduled-event\n * materialiser (ADR-039) to treat a slot-key collision as the\n * already-materialised no-op. Reads `.code` defensively across driver shapes\n * (node-postgres surfaces it on the error, some wrappers nest it on `.cause`).\n */\nfunction isUniqueViolation(err: unknown): boolean {\n const code = (err as { code?: unknown; cause?: { code?: unknown } } | undefined);\n return code?.code === '23505' || code?.cause?.code === '23505';\n}\n\n@Injectable()\nexport class DrizzleEventBus implements IEventBus, IEventReadPort, OnModuleInit, OnModuleDestroy {\n private readonly logger = new Logger(DrizzleEventBus.name);\n private polling = false;\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly handlers = new Map<string, Set<(event: DomainEvent) => Promise<void>>>();\n private readonly opts: EventsModuleOptions;\n\n // LISTEN-NOTIFY-1 — dedicated wake listener + debounce state. `null` when\n // `listenNotify` is off (the common case); polling is the only driver then.\n private notifyListener: PgNotifyListener | null = null;\n /** True while a wake-driven drain is in flight (debounce gate). */\n private wakeDraining = false;\n /** A notify arrived mid-drain → re-drain once when the current drain ends. */\n private wakeRecheckPending = false;\n\n constructor(\n @Inject(DRIZZLE) private readonly db: DrizzleClient,\n @Optional() @Inject(EVENTS_MODULE_OPTIONS) opts?: EventsModuleOptions,\n /**\n * Bridge subsystem hook (BRIDGE-4). Optional — when the bridge\n * subsystem is not installed in the consuming app, this token is\n * undefined and the drain skips the bridge block entirely (preserves\n * EVT-4 baseline behaviour).\n *\n * When provided, `processEvent` is invoked once per drained event\n * INSIDE the per-event tx, before `processed_at` is stamped. The\n * hook owns all knowledge of `bridge_delivery + wrapper job_run`\n * shapes; the events subsystem stays unaware of bridge schemas.\n */\n @Optional()\n @Inject(BRIDGE_OUTBOX_DRAIN_HOOK)\n private readonly bridgeHook: IBridgeOutboxDrainHook | null = null,\n ) {\n // Default so direct construction (e.g. integration tests not going\n // through Nest DI) keeps working without an explicit options object.\n this.opts = opts ?? { backend: 'drizzle' };\n }\n\n // ============================================================================\n // Lifecycle\n // ============================================================================\n\n async onModuleInit(): Promise<void> {\n this.polling = true;\n this.schedulePoll();\n\n // LISTEN-NOTIFY-1 — start the wake listener ALONGSIDE the poll timer. A\n // notify for one of this drainer's pools triggers an immediate drain; the\n // interval timer above stays the durability heartbeat. Startup is\n // fire-and-forget — a connect failure self-heals via the listener's backoff.\n if (this.opts.listenNotify) {\n const pool = (this.db as unknown as { $client?: unknown }).$client;\n if (!pool || typeof (pool as { connect?: unknown }).connect !== 'function') {\n this.logger.warn(\n `listen_notify enabled but the Drizzle client exposes no pg Pool ` +\n `($client.connect missing) — falling back to interval polling only.`,\n );\n } else {\n this.notifyListener = new PgNotifyListener({\n channel: EVENTS_WAKE_CHANNEL,\n pool: pool as { connect(): Promise<never> },\n label: 'events',\n onNotify: (payload) => this.onWake(payload),\n });\n await this.notifyListener.start();\n }\n }\n }\n\n async onModuleDestroy(): Promise<void> {\n this.polling = false;\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.notifyListener) {\n try {\n await this.notifyListener.stop();\n } catch (err) {\n this.logger.error(`notify listener stop failed: ${err}`);\n }\n this.notifyListener = null;\n }\n }\n\n /**\n * Wake handler — a `codegen_events_wake` notification arrived. A pool-filtered\n * drainer (`opts.pools` set) ignores payloads naming a pool it doesn't own; an\n * all-pools drainer wakes for any. Debounced: a notify mid-drain just flags a\n * re-check so a burst collapses to at most one extra drain (D3).\n */\n private onWake(payload: string): void {\n if (!this.polling) return;\n const pools = this.opts.pools;\n if (pools && pools.length > 0 && !pools.includes(payload)) return;\n if (this.wakeDraining) {\n this.wakeRecheckPending = true;\n return;\n }\n void this.drainOnWake();\n }\n\n private async drainOnWake(): Promise<void> {\n this.wakeDraining = true;\n try {\n do {\n this.wakeRecheckPending = false;\n await this.processBatch();\n } while (this.wakeRecheckPending && this.polling);\n } catch (err) {\n this.logger.error(`wake drain error: ${err}`);\n } finally {\n this.wakeDraining = false;\n }\n }\n\n // ============================================================================\n // IEventBus\n // ============================================================================\n\n async publish(event: DomainEvent, tx?: DrizzleTransaction): Promise<void> {\n const client = (tx ?? this.db) as DrizzleClient;\n const multiTenant = this.opts.multiTenant ?? false;\n const values = toInsertValues(event, multiTenant);\n await client.insert(domainEvents).values(values);\n // LISTEN-NOTIFY-1 — wake the drainer on commit (D2: emitted through the same\n // `client`, so a rolled-back publish emits no phantom wake). The pool is the\n // payload; the drainer re-runs its own pool-filtered claim on wake.\n await this.emitWakeNotify(client, [values.pool]);\n }\n\n async publishMany(events: DomainEvent[], tx?: DrizzleTransaction): Promise<void> {\n if (events.length === 0) return;\n const client = (tx ?? this.db) as DrizzleClient;\n const multiTenant = this.opts.multiTenant ?? false;\n const valuesList = events.map((e) => toInsertValues(e, multiTenant));\n await client.insert(domainEvents).values(valuesList);\n // De-dup pools so a batch into one lane emits a single wake.\n await this.emitWakeNotify(client, valuesList.map((v) => v.pool));\n }\n\n /**\n * Emit one in-tx `pg_notify(codegen_events_wake, <pool>)` per distinct pool in\n * the just-inserted batch. No-op unless `listenNotify` is on. Best-effort: a\n * notify failure is non-fatal (interval polling still drains the rows), so we\n * log + swallow rather than failing the publish.\n */\n private async emitWakeNotify(\n client: DrizzleClient,\n pools: Array<string | null>,\n ): Promise<void> {\n if (!this.opts.listenNotify) return;\n const distinct = new Set(pools.map((p) => p ?? ''));\n for (const pool of distinct) {\n try {\n await pgNotify(client, EVENTS_WAKE_CHANNEL, pool);\n } catch (err) {\n this.logger.warn(\n `pg_notify(${EVENTS_WAKE_CHANNEL}, '${pool}') failed: ${err} ` +\n `(non-fatal — interval polling still drains the outbox).`,\n );\n }\n }\n }\n\n async findById(eventId: string): Promise<DomainEvent | null> {\n const rows = await this.db\n .select()\n .from(domainEvents)\n .where(eq(domainEvents.id, eventId))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n return {\n id: row.id,\n type: row.type,\n aggregateId: row.aggregateId,\n aggregateType: row.aggregateType,\n payload: row.payload as Record<string, unknown>,\n occurredAt:\n row.occurredAt instanceof Date\n ? row.occurredAt\n : new Date(row.occurredAt as unknown as string),\n metadata: (row.metadata ?? undefined) as\n | Record<string, unknown>\n | undefined,\n };\n }\n\n subscribe<T extends DomainEvent = DomainEvent>(\n eventType: string,\n handler: (event: T) => Promise<void>,\n ): () => void {\n if (!this.handlers.has(eventType)) {\n this.handlers.set(eventType, new Set());\n }\n const set = this.handlers.get(eventType)!;\n const h = handler as (event: DomainEvent) => Promise<void>;\n set.add(h);\n return () => {\n set.delete(h);\n };\n }\n\n // ============================================================================\n // ADR-039 — scheduled-event materialisation (time as an event source)\n // ============================================================================\n\n /**\n * Insert one scheduled tick event idempotently. The slot key is stamped onto\n * `metadata.scheduleSlot`; `ON CONFLICT DO NOTHING` against the partial UNIQUE\n * expression index `idx_domain_events_schedule_slot` makes a duplicate insert\n * a no-op — the DB constraint is the exactly-one-event-per-slot invariant.\n *\n * Reuses the standard outbox row shape (pool/direction/metadata) so the\n * existing drain carries the tick like any other event. A LISTEN/NOTIFY wake\n * fires for an immediately-due tick (boot/catch-up rows whose slot is already\n * in the past); a future slot is claimed by polling once `occurred_at` passes.\n */\n async materializeScheduledEvent(\n spec: ScheduledEventSpec,\n ): Promise<{ created: boolean }> {\n const multiTenant = this.opts.multiTenant ?? false;\n const metadata: Record<string, unknown> = {\n pool: spec.pool,\n direction: spec.direction,\n scheduleSlot: spec.slotKey,\n triggerSource: 'schedule',\n };\n const base = {\n id: randomUUID(),\n type: spec.type,\n // Payload-free scheduled fact (the dealbrain strict-producer pattern).\n aggregateId: spec.type,\n aggregateType: spec.type,\n payload: {} as Record<string, unknown>,\n occurredAt: spec.slotStart,\n processedAt: null,\n status: 'pending' as const,\n metadata,\n pool: spec.pool,\n direction: spec.direction,\n tier: 'domain' as const,\n };\n const values = multiTenant ? { ...base, tenantId: null } : base;\n\n // The idempotency guard is the partial UNIQUE expression index\n // `idx_domain_events_schedule_slot` on (type, metadata->>'scheduleSlot').\n // Use a BARE (no-target) `ON CONFLICT DO NOTHING`: Drizzle 0.45's typed\n // `onConflictDoNothing({ target })` only accepts columns so it can't NAME\n // the expression index, but the no-arg form emits target-less\n // `ON CONFLICT DO NOTHING`, which Postgres applies to ANY unique\n // constraint/index — including this expression index. `.returning({ id })`\n // then gives us the rowcount discriminator: zero rows back == the slot was\n // already materialised (DO NOTHING fired), so `created: false`. This keeps\n // the happy path off the exception channel — a repeat materialise no longer\n // raises SQLSTATE 23505, so Postgres logs no scary `duplicate key value\n // violates unique constraint` ERROR line on every colliding boot/tick.\n //\n // The unique-violation catch is retained as a fallback for the genuine\n // concurrent-insert race window (two sessions clear the conflict check and\n // both attempt the insert in the same instant) and for backends whose\n // driver surfaces a 23505 rather than honouring DO NOTHING; in both cases\n // it collapses to the same `created: false` no-op.\n let inserted: Array<{ id: string }>;\n try {\n inserted = await this.db\n .insert(domainEvents)\n .values(values)\n .onConflictDoNothing()\n .returning({ id: domainEvents.id });\n } catch (err) {\n if (isUniqueViolation(err)) return { created: false };\n throw err;\n }\n if (inserted.length === 0) return { created: false };\n\n // Wake the drainer for an already-due tick. A future slot waits for polling.\n if (spec.slotStart.getTime() <= Date.now()) {\n await this.emitWakeNotify(this.db, [spec.pool]);\n }\n return { created: true };\n }\n\n /** Most recent scheduled tick's `occurred_at` (epoch ms) for `type`, or null.\n * Read by the scheduler's catch-up backfill. */\n async lastScheduledSlotMs(type: string): Promise<number | null> {\n const rows = await this.db\n .select({ occurredAt: domainEvents.occurredAt })\n .from(domainEvents)\n .where(\n and(\n eq(domainEvents.type, type),\n sql`${domainEvents.metadata} ->> 'triggerSource' = 'schedule'`,\n ),\n )\n .orderBy(desc(domainEvents.occurredAt))\n .limit(1);\n const row = rows[0];\n if (!row?.occurredAt) return null;\n return row.occurredAt instanceof Date\n ? row.occurredAt.getTime()\n : new Date(row.occurredAt as unknown as string).getTime();\n }\n\n // ============================================================================\n // IEventReadPort (OBS-LIST-1)\n // ============================================================================\n\n async listEvents(query: ListEventsQuery = {}): Promise<EventPage> {\n const limit = clampEventLimit(query.limit);\n const conditions: SQL<unknown>[] = [];\n\n if (query.poolId) conditions.push(eq(domainEvents.pool, query.poolId));\n if (query.direction)\n conditions.push(eq(domainEvents.direction, query.direction));\n if (query.since) conditions.push(gte(domainEvents.occurredAt, query.since));\n if (query.rootRunId) {\n // Filter on the JSON correlation id: metadata->>'rootRunId'.\n conditions.push(\n sql`${domainEvents.metadata}->>'rootRunId' = ${query.rootRunId}`,\n );\n }\n // EVT-8: `tenant_id` is a scaffold-time conditional column (emitted only\n // under `events.multi_tenant: true`). Guard the filter behind the same\n // `multiTenant` flag, and read the column structurally so this backend\n // typechecks against both the multi-tenant schema (column present) and\n // the single-tenant schema (column absent). When multi-tenancy is off\n // there is no `tenant_id` column to filter on.\n if (this.opts.multiTenant && query.tenantId !== undefined) {\n const tenantIdColumn = (\n domainEvents as unknown as { tenantId: typeof domainEvents.pool }\n ).tenantId;\n conditions.push(\n query.tenantId === null\n ? (sql`${tenantIdColumn} is null` as SQL<unknown>)\n : eq(tenantIdColumn, query.tenantId),\n );\n }\n\n // Keyset seek: WHERE (occurred_at, id) < (cursorOccurredAt, cursorId).\n if (query.cursor) {\n const keyset = decodeEventCursor(query.cursor);\n if (keyset) {\n conditions.push(\n or(\n lt(domainEvents.occurredAt, keyset.occurredAt),\n and(\n eq(domainEvents.occurredAt, keyset.occurredAt),\n lt(domainEvents.id, keyset.id),\n ),\n )!,\n );\n }\n }\n\n const rows = (await this.db\n .select()\n .from(domainEvents)\n .where(conditions.length > 0 ? and(...conditions) : undefined)\n .orderBy(desc(domainEvents.occurredAt), desc(domainEvents.id))\n .limit(limit + 1)) as DomainEventRecord[];\n\n const hasMore = rows.length > limit;\n const page = hasMore ? rows.slice(0, limit) : rows;\n const items = page.map(toEventSummary);\n const last = page[page.length - 1];\n const nextCursor =\n hasMore && last\n ? encodeEventCursor({ occurredAt: last.occurredAt, id: last.id })\n : null;\n\n return { items, nextCursor };\n }\n\n // ============================================================================\n // Polling\n // ============================================================================\n\n /**\n * Test-only hook. Runs exactly one drain cycle and returns. Production\n * code goes through `onModuleInit` → `schedulePoll`, which calls the\n * same `processBatch` under a timer.\n */\n async drainOnce(): Promise<void> {\n await this.processBatch();\n }\n\n private schedulePoll(): void {\n if (!this.polling) return;\n this.pollTimer = setTimeout(async () => {\n try {\n await this.processBatch();\n } catch (err) {\n this.logger.error(`Poll cycle error: ${err}`);\n } finally {\n this.schedulePoll();\n }\n }, POLL_INTERVAL_MS);\n }\n\n /**\n * Drain one batch (BRIDGE-4 restructure of EVT-4).\n *\n * Two-phase per drained event:\n *\n * 1. **Per-event transaction** — bridge fanout (`bridgeHook.processEvent`)\n * + `processed_at` stamp. Both write through the same `tx`. A throw\n * inside the tx (only infra-level failures should reach here, since\n * the hook tolerates null direction and registry misses inline)\n * rolls back the bridge inserts AND the `processed_at` stamp; the\n * event re-claims on the next drain cycle. Bridge `UNIQUE\n * (event_id, trigger_id)` makes the retry idempotent.\n *\n * 2. **After commit** — dispatch in-process subscribers (`IEventBus.subscribe`\n * handlers). This deliberately runs OUTSIDE the per-event tx (lead\n * decision 2026-04-22): subscribers are best-effort and must not\n * gate forward progress or roll back bridge fanout. Subscriber\n * errors are caught + logged; `processed_at` is already committed.\n * The old `MAX_RETRIES=3` in-process retry loop and the\n * `failed`-stamping path were removed in BRIDGE-4 along with their\n * coupling.\n *\n * The `processed_at` UPDATE carries `AND status='pending'` (BRIDGE-4\n * tightening — without it, a hypothetical double-claim could double-stamp\n * the timestamp). The per-event tx + `FOR UPDATE SKIP LOCKED` claim\n * make this defensive belt-and-suspenders.\n */\n private async processBatch(): Promise<void> {\n const pools = this.opts.pools;\n\n // Build WHERE: status='pending' [AND pool IN (...)]\n const whereClause: SQL<unknown> = pools && pools.length > 0\n ? (and(eq(domainEvents.status, 'pending'), inArray(domainEvents.pool, pools)) as SQL<unknown>)\n : eq(domainEvents.status, 'pending');\n\n // Claim a batch with FOR UPDATE SKIP LOCKED so multiple pollers don't\n // double-dispatch. The lock is released when the outer transaction\n // commits — which is fine because the immediately-following per-event\n // tx flips status='processed' under its own `AND status='pending'`\n // guard, so a re-claim of the same row in a subsequent batch is a\n // no-op UPDATE.\n const rows = await this.db.transaction(async (tx) => {\n return tx\n .select()\n .from(domainEvents)\n .where(whereClause)\n .orderBy(asc(domainEvents.occurredAt))\n .limit(POLL_BATCH_SIZE)\n .for('update', { skipLocked: true });\n }) as Array<typeof domainEvents.$inferSelect>;\n\n for (const row of rows) {\n const event: DomainEvent = {\n id: row.id,\n type: row.type,\n aggregateId: row.aggregateId,\n aggregateType: row.aggregateType,\n payload: row.payload as Record<string, unknown>,\n occurredAt: row.occurredAt instanceof Date ? row.occurredAt : new Date(row.occurredAt as unknown as string),\n metadata: (row.metadata ?? undefined) as Record<string, unknown> | undefined,\n };\n\n // Phase 1 — per-event tx: bridge fanout + processed_at stamp.\n try {\n await this.db.transaction(async (tx) => {\n if (this.bridgeHook) {\n await this.bridgeHook.processEvent(event, tx);\n }\n await tx\n .update(domainEvents)\n .set({ status: 'processed', processedAt: new Date() })\n .where(\n and(\n eq(domainEvents.id, event.id),\n eq(domainEvents.status, 'pending'),\n ),\n );\n });\n } catch (err) {\n // Infra-level failure inside the per-event tx — bridge inserts\n // and processed_at both rolled back. Log and move on; the next\n // drain cycle re-claims the row. UNIQUE on bridge_delivery makes\n // the retry idempotent.\n this.logger.error(\n `Per-event tx failed for event id=${event.id} type=${event.type}: ${err}`,\n );\n continue;\n }\n\n // Phase 2 — best-effort subscriber dispatch. Errors are logged\n // and discarded; processed_at is already committed. Subscribers\n // are observability + cache-busts + small ancillary work; they\n // must not gate forward progress.\n try {\n await this.dispatch(event);\n } catch (err) {\n this.logger.error(\n `Subscriber dispatch failed for event id=${event.id} type=${event.type} ` +\n `(processed_at already committed; failure does not retry): ${err}`,\n );\n }\n }\n }\n\n private async dispatch(event: DomainEvent): Promise<void> {\n const set = this.handlers.get(event.type);\n if (!set) return;\n\n let firstError: unknown;\n for (const handler of set) {\n try {\n await handler(event);\n } catch (err) {\n this.logger.error(\n `Handler error for event type \"${event.type}\" (id: ${event.id}): ${err}`,\n );\n if (firstError === undefined) {\n firstError = err;\n }\n }\n }\n\n if (firstError !== undefined) {\n throw firstError;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|