@openora/core 0.4.1-canary.22 → 0.4.1-canary.26
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/dist/.tsbuildinfo +1 -1
- package/dist/audit/__tests__/audit.service.test.js +24 -1
- package/dist/audit/__tests__/audit.service.test.js.map +1 -1
- package/dist/audit/contract/index.d.ts +8 -8
- package/dist/audit/contract/index.js +2 -2
- package/dist/audit/contract/index.js.map +1 -1
- package/dist/audit/router/index.d.ts +4 -4
- package/dist/audit/service/audit.service.d.ts +2 -0
- package/dist/audit/service/audit.service.d.ts.map +1 -1
- package/dist/audit/service/audit.service.js +9 -1
- package/dist/audit/service/audit.service.js.map +1 -1
- package/dist/casino/lobby/__tests__/lobby.cache.test.js +1 -1
- package/dist/casino/lobby/__tests__/lobby.cache.test.js.map +1 -1
- package/dist/cms/__tests__/cms.reads.test.d.ts +2 -0
- package/dist/cms/__tests__/cms.reads.test.d.ts.map +1 -0
- package/dist/cms/__tests__/{cms.cache.test.js → cms.reads.test.js} +2 -2
- package/dist/cms/__tests__/cms.reads.test.js.map +1 -0
- package/dist/cms/__tests__/cms.router.test.js +25 -22
- package/dist/cms/__tests__/cms.router.test.js.map +1 -1
- package/dist/contracts/schemas/events.d.ts +1 -0
- package/dist/contracts/schemas/events.d.ts.map +1 -1
- package/dist/contracts/schemas/events.js +2 -1
- package/dist/contracts/schemas/events.js.map +1 -1
- package/dist/engagement/chat/__tests__/chat.service.test.js +1 -1
- package/dist/engagement/chat/__tests__/chat.service.test.js.map +1 -1
- package/dist/iam/__tests__/iam.service.test.js +4 -3
- package/dist/iam/__tests__/iam.service.test.js.map +1 -1
- package/dist/pam/identity/__tests__/identity.rate-limit.test.js +4 -3
- package/dist/pam/identity/__tests__/identity.rate-limit.test.js.map +1 -1
- package/dist/pam/identity/__tests__/identity.service.test.js +6 -1
- package/dist/pam/identity/__tests__/identity.service.test.js.map +1 -1
- package/dist/pam/identity/service/identity.service.d.ts.map +1 -1
- package/dist/pam/identity/service/identity.service.js +1 -0
- package/dist/pam/identity/service/identity.service.js.map +1 -1
- package/dist/server/kernel/__tests__/cache.test.js +11 -57
- package/dist/server/kernel/__tests__/cache.test.js.map +1 -1
- package/dist/server/kernel/__tests__/event-bus.test.js +14 -1
- package/dist/server/kernel/__tests__/event-bus.test.js.map +1 -1
- package/dist/server/kernel/__tests__/rate-limiter.test.js +3 -45
- package/dist/server/kernel/__tests__/rate-limiter.test.js.map +1 -1
- package/dist/server/kernel/__tests__/redis-streams-broker.test.d.ts +2 -0
- package/dist/server/kernel/__tests__/redis-streams-broker.test.d.ts.map +1 -0
- package/dist/server/kernel/__tests__/redis-streams-broker.test.js +293 -0
- package/dist/server/kernel/__tests__/redis-streams-broker.test.js.map +1 -0
- package/dist/server/kernel/cache.d.ts +0 -12
- package/dist/server/kernel/cache.d.ts.map +1 -1
- package/dist/server/kernel/cache.js +0 -55
- package/dist/server/kernel/cache.js.map +1 -1
- package/dist/server/kernel/event-bus.d.ts +1 -16
- package/dist/server/kernel/event-bus.d.ts.map +1 -1
- package/dist/server/kernel/event-bus.js +3 -32
- package/dist/server/kernel/event-bus.js.map +1 -1
- package/dist/server/kernel/index.d.ts +4 -6
- package/dist/server/kernel/index.d.ts.map +1 -1
- package/dist/server/kernel/index.js +4 -6
- package/dist/server/kernel/index.js.map +1 -1
- package/dist/server/kernel/rate-limiter.d.ts +1 -10
- package/dist/server/kernel/rate-limiter.d.ts.map +1 -1
- package/dist/server/kernel/rate-limiter.js +0 -38
- package/dist/server/kernel/rate-limiter.js.map +1 -1
- package/dist/server/kernel/redis-streams-broker.d.ts +65 -0
- package/dist/server/kernel/redis-streams-broker.d.ts.map +1 -0
- package/dist/server/kernel/redis-streams-broker.js +208 -0
- package/dist/server/kernel/redis-streams-broker.js.map +1 -0
- package/dist/server/runtime/__tests__/create-app.test.d.ts +2 -0
- package/dist/server/runtime/__tests__/create-app.test.d.ts.map +1 -0
- package/dist/server/runtime/__tests__/create-app.test.js +60 -0
- package/dist/server/runtime/__tests__/create-app.test.js.map +1 -0
- package/dist/server/runtime/assert-durable-seams.d.ts +18 -0
- package/dist/server/runtime/assert-durable-seams.d.ts.map +1 -0
- package/dist/server/runtime/assert-durable-seams.js +32 -0
- package/dist/server/runtime/assert-durable-seams.js.map +1 -0
- package/dist/server/runtime/create-app.d.ts +15 -9
- package/dist/server/runtime/create-app.d.ts.map +1 -1
- package/dist/server/runtime/create-app.js +61 -49
- package/dist/server/runtime/create-app.js.map +1 -1
- package/dist/testing/fakes/__tests__/cache.test.d.ts +2 -0
- package/dist/testing/fakes/__tests__/cache.test.d.ts.map +1 -0
- package/dist/testing/fakes/__tests__/cache.test.js +89 -0
- package/dist/testing/fakes/__tests__/cache.test.js.map +1 -0
- package/dist/testing/fakes/__tests__/job-queue.test.d.ts.map +1 -0
- package/dist/{server/kernel → testing/fakes}/__tests__/job-queue.test.js +1 -1
- package/dist/testing/fakes/__tests__/job-queue.test.js.map +1 -0
- package/dist/testing/fakes/__tests__/rate-limiter.test.d.ts +2 -0
- package/dist/testing/fakes/__tests__/rate-limiter.test.d.ts.map +1 -0
- package/dist/testing/fakes/__tests__/rate-limiter.test.js +83 -0
- package/dist/testing/fakes/__tests__/rate-limiter.test.js.map +1 -0
- package/dist/testing/fakes/__tests__/realtime-authorizer.test.d.ts.map +1 -0
- package/dist/{server/kernel → testing/fakes}/__tests__/realtime-authorizer.test.js.map +1 -1
- package/dist/testing/fakes/__tests__/realtime-transport.test.d.ts.map +1 -0
- package/dist/{server/kernel → testing/fakes}/__tests__/realtime-transport.test.js.map +1 -1
- package/dist/testing/fakes/cache.d.ts +14 -0
- package/dist/testing/fakes/cache.d.ts.map +1 -0
- package/dist/testing/fakes/cache.js +56 -0
- package/dist/testing/fakes/cache.js.map +1 -0
- package/dist/testing/fakes/event-bus.d.ts +17 -0
- package/dist/testing/fakes/event-bus.d.ts.map +1 -0
- package/dist/testing/fakes/event-bus.js +30 -0
- package/dist/testing/fakes/event-bus.js.map +1 -0
- package/dist/{server/kernel → testing/fakes}/job-queue.d.ts +9 -9
- package/dist/{server/kernel → testing/fakes}/job-queue.d.ts.map +1 -1
- package/dist/{server/kernel → testing/fakes}/job-queue.js +9 -9
- package/dist/{server/kernel → testing/fakes}/job-queue.js.map +1 -1
- package/dist/testing/fakes/rate-limiter.d.ts +11 -0
- package/dist/testing/fakes/rate-limiter.d.ts.map +1 -0
- package/dist/testing/fakes/rate-limiter.js +39 -0
- package/dist/testing/fakes/rate-limiter.js.map +1 -0
- package/dist/{server/kernel → testing/fakes}/realtime-authorizer.d.ts.map +1 -1
- package/dist/{server/kernel → testing/fakes}/realtime-authorizer.js.map +1 -1
- package/dist/{server/kernel → testing/fakes}/realtime-transport.d.ts.map +1 -1
- package/dist/{server/kernel → testing/fakes}/realtime-transport.js +3 -1
- package/dist/testing/fakes/realtime-transport.js.map +1 -0
- package/dist/testing/index.d.ts +7 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +11 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/wallet/__tests__/wallet.rate-limit.test.js +1 -1
- package/dist/wallet/__tests__/wallet.rate-limit.test.js.map +1 -1
- package/package.json +6 -1
- package/turbo-generators/src/templates/module/agents.hbs +16 -57
- package/dist/cms/__tests__/cms.cache.test.d.ts +0 -2
- package/dist/cms/__tests__/cms.cache.test.d.ts.map +0 -1
- package/dist/cms/__tests__/cms.cache.test.js.map +0 -1
- package/dist/server/kernel/__tests__/job-queue.test.d.ts.map +0 -1
- package/dist/server/kernel/__tests__/job-queue.test.js.map +0 -1
- package/dist/server/kernel/__tests__/realtime-authorizer.test.d.ts.map +0 -1
- package/dist/server/kernel/__tests__/realtime-transport.test.d.ts.map +0 -1
- package/dist/server/kernel/realtime-transport.js.map +0 -1
- /package/dist/{server/kernel → testing/fakes}/__tests__/job-queue.test.d.ts +0 -0
- /package/dist/{server/kernel → testing/fakes}/__tests__/realtime-authorizer.test.d.ts +0 -0
- /package/dist/{server/kernel → testing/fakes}/__tests__/realtime-authorizer.test.js +0 -0
- /package/dist/{server/kernel → testing/fakes}/__tests__/realtime-transport.test.d.ts +0 -0
- /package/dist/{server/kernel → testing/fakes}/__tests__/realtime-transport.test.js +0 -0
- /package/dist/{server/kernel → testing/fakes}/realtime-authorizer.d.ts +0 -0
- /package/dist/{server/kernel → testing/fakes}/realtime-authorizer.js +0 -0
- /package/dist/{server/kernel → testing/fakes}/realtime-transport.d.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-bus.test.js","sourceRoot":"","sources":["../../../../src/server/kernel/__tests__/event-bus.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"event-bus.test.js","sourceRoot":"","sources":["../../../../src/server/kernel/__tests__/event-bus.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,50 +1,8 @@
|
|
|
1
|
-
import { describe, it, expect, vi
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
2
|
import { ORPCError } from '@orpc/server';
|
|
3
|
-
import {
|
|
3
|
+
import { assertRateLimit, makeRateLimitError } from '../rate-limiter.js';
|
|
4
|
+
import { InProcessRateLimiter } from '@openora/core/testing';
|
|
4
5
|
const OPTS = { limit: 3, windowMs: 1000 };
|
|
5
|
-
describe('InProcessRateLimiter', () => {
|
|
6
|
-
beforeEach(() => vi.useFakeTimers());
|
|
7
|
-
afterEach(() => vi.useRealTimers());
|
|
8
|
-
it('allows up to the limit then denies within the same window', async () => {
|
|
9
|
-
const limiter = new InProcessRateLimiter();
|
|
10
|
-
const results = [];
|
|
11
|
-
for (let i = 0; i < 4; i++) {
|
|
12
|
-
results.push(await limiter.consume('k', OPTS));
|
|
13
|
-
}
|
|
14
|
-
expect(results.map((r) => r.allowed)).toEqual([true, true, true, false]);
|
|
15
|
-
limiter.close();
|
|
16
|
-
});
|
|
17
|
-
it('reports retryAfterMs equal to the time left in the window on denial', async () => {
|
|
18
|
-
const limiter = new InProcessRateLimiter();
|
|
19
|
-
for (let i = 0; i < 3; i++) {
|
|
20
|
-
await limiter.consume('k', OPTS);
|
|
21
|
-
}
|
|
22
|
-
vi.advanceTimersByTime(400);
|
|
23
|
-
const denied = await limiter.consume('k', OPTS);
|
|
24
|
-
expect(denied.allowed).toBe(false);
|
|
25
|
-
expect(denied.retryAfterMs).toBe(600);
|
|
26
|
-
limiter.close();
|
|
27
|
-
});
|
|
28
|
-
it('rolls over: a fresh budget is available once the window elapses', async () => {
|
|
29
|
-
const limiter = new InProcessRateLimiter();
|
|
30
|
-
for (let i = 0; i < 3; i++) {
|
|
31
|
-
await limiter.consume('k', OPTS);
|
|
32
|
-
}
|
|
33
|
-
expect((await limiter.consume('k', OPTS)).allowed).toBe(false);
|
|
34
|
-
vi.advanceTimersByTime(1000);
|
|
35
|
-
expect((await limiter.consume('k', OPTS)).allowed).toBe(true);
|
|
36
|
-
limiter.close();
|
|
37
|
-
});
|
|
38
|
-
it('isolates budgets between keys', async () => {
|
|
39
|
-
const limiter = new InProcessRateLimiter();
|
|
40
|
-
for (let i = 0; i < 3; i++) {
|
|
41
|
-
await limiter.consume('a', OPTS);
|
|
42
|
-
}
|
|
43
|
-
expect((await limiter.consume('a', OPTS)).allowed).toBe(false);
|
|
44
|
-
expect((await limiter.consume('b', OPTS)).allowed).toBe(true);
|
|
45
|
-
limiter.close();
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
6
|
describe('assertRateLimit / makeRateLimitError', () => {
|
|
49
7
|
it('throws a TOO_MANY_REQUESTS ORPCError carrying retryAfterMs once the limit is hit', async () => {
|
|
50
8
|
vi.useFakeTimers();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.test.js","sourceRoot":"","sources":["../../../../src/server/kernel/__tests__/rate-limiter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"rate-limiter.test.js","sourceRoot":"","sources":["../../../../src/server/kernel/__tests__/rate-limiter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAE1C,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;QAChG,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;YACtE,IAAI,EAAE,mBAAmB;YACzB,IAAI,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,QAAQ,EAAE;SACtC,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,OAAO,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC3C,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3E,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-streams-broker.test.d.ts","sourceRoot":"","sources":["../../../../src/server/kernel/__tests__/redis-streams-broker.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { RedisStreamsBroker } from '../redis-streams-broker.js';
|
|
3
|
+
import { mock } from '../../../testing/mock.js';
|
|
4
|
+
// Mirrors the un-exported STREAM_PREFIX in redis-streams-broker.ts.
|
|
5
|
+
const STREAM_PREFIX = 'oss:evt:';
|
|
6
|
+
// In-memory Redis Streams double: one Map<streamKey, entries[]> shared by the root
|
|
7
|
+
// client and every client.duplicate() (mirrors duplicate() opening a second
|
|
8
|
+
// connection to the SAME server/data), plus a per-(streamKey, group) read cursor.
|
|
9
|
+
// A blocked xReadGroup call parks on a per-stream waiter list, woken by the next
|
|
10
|
+
// xAdd (new data) or destroy() (reader torn down) - no timers, fully deterministic.
|
|
11
|
+
//
|
|
12
|
+
// Models the two node-redis behaviours the broker's reconnect path depends on:
|
|
13
|
+
// `connect()` throws 'Socket already opened' once `isOpen` (so a loop that
|
|
14
|
+
// re-connects blindly wedges here exactly as it would in production), and
|
|
15
|
+
// xGroupCreate honours the start id - '$' seeds the cursor at the current stream
|
|
16
|
+
// end (new entries only), '0' at the start (replays retained history).
|
|
17
|
+
function fakeStreamsClient() {
|
|
18
|
+
const streams = new Map();
|
|
19
|
+
const cursors = new Map();
|
|
20
|
+
const waiters = new Map();
|
|
21
|
+
const duplicates = [];
|
|
22
|
+
let seq = 0;
|
|
23
|
+
// Armed before subscribe(), since the reader connection this would target does not
|
|
24
|
+
// exist until the loop calls duplicate().
|
|
25
|
+
let nextGroupCreateError = null;
|
|
26
|
+
function wake(key) {
|
|
27
|
+
const pending = waiters.get(key) ?? [];
|
|
28
|
+
waiters.set(key, []);
|
|
29
|
+
for (const resolve of pending) {
|
|
30
|
+
resolve();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function makeRaw() {
|
|
34
|
+
let destroyed = false;
|
|
35
|
+
const raw = {
|
|
36
|
+
isReady: true,
|
|
37
|
+
isOpen: false,
|
|
38
|
+
on: vi.fn(),
|
|
39
|
+
connect: vi.fn(async () => {
|
|
40
|
+
// node-redis (socket.ts): connect() rejects once the socket is open, and
|
|
41
|
+
// isOpen stays true across reconnectStrategy retries.
|
|
42
|
+
if (raw.isOpen) {
|
|
43
|
+
throw new Error('Socket already opened');
|
|
44
|
+
}
|
|
45
|
+
raw.isOpen = true;
|
|
46
|
+
return raw;
|
|
47
|
+
}),
|
|
48
|
+
destroy: vi.fn(() => {
|
|
49
|
+
destroyed = true;
|
|
50
|
+
raw.isOpen = false;
|
|
51
|
+
// Every parked reader, not just those whose stream already has entries - a
|
|
52
|
+
// loop torn down before anything was ever published is parked on a key that
|
|
53
|
+
// `streams` has never seen, and would otherwise never wake to observe
|
|
54
|
+
// `destroyed` (hanging the `close()` that awaits it). Loops belonging to
|
|
55
|
+
// other connections re-check their own flag and re-park.
|
|
56
|
+
for (const key of waiters.keys()) {
|
|
57
|
+
wake(key);
|
|
58
|
+
}
|
|
59
|
+
}),
|
|
60
|
+
duplicate: vi.fn(() => {
|
|
61
|
+
const dup = makeRaw();
|
|
62
|
+
duplicates.push(dup);
|
|
63
|
+
return mock(dup);
|
|
64
|
+
}),
|
|
65
|
+
xAdd: vi.fn(async (key, _id, message) => {
|
|
66
|
+
const entries = streams.get(key) ?? [];
|
|
67
|
+
const entryId = `${++seq}-0`;
|
|
68
|
+
entries.push({ id: entryId, message });
|
|
69
|
+
streams.set(key, entries);
|
|
70
|
+
wake(key);
|
|
71
|
+
return entryId;
|
|
72
|
+
}),
|
|
73
|
+
xGroupCreate: vi.fn(async (key, group, startId) => {
|
|
74
|
+
if (nextGroupCreateError) {
|
|
75
|
+
const err = nextGroupCreateError;
|
|
76
|
+
nextGroupCreateError = null;
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
const cursorKey = `${key}::${group}`;
|
|
80
|
+
if (cursors.has(cursorKey)) {
|
|
81
|
+
throw new Error('BUSYGROUP Consumer Group name already exists');
|
|
82
|
+
}
|
|
83
|
+
cursors.set(cursorKey, startId === '0' ? 0 : (streams.get(key) ?? []).length);
|
|
84
|
+
return 'OK';
|
|
85
|
+
}),
|
|
86
|
+
xReadGroup: vi.fn(async (group, _consumer, stream, opts) => {
|
|
87
|
+
const { key } = stream;
|
|
88
|
+
const cursorKey = `${key}::${group}`;
|
|
89
|
+
for (;;) {
|
|
90
|
+
if (destroyed) {
|
|
91
|
+
throw new Error('reader destroyed');
|
|
92
|
+
}
|
|
93
|
+
const entries = streams.get(key) ?? [];
|
|
94
|
+
const cursor = cursors.get(cursorKey) ?? 0;
|
|
95
|
+
if (cursor < entries.length) {
|
|
96
|
+
const slice = entries.slice(cursor, cursor + (opts?.COUNT ?? entries.length));
|
|
97
|
+
cursors.set(cursorKey, cursor + slice.length);
|
|
98
|
+
return [{ name: key, messages: slice }];
|
|
99
|
+
}
|
|
100
|
+
await new Promise((resolve) => {
|
|
101
|
+
const pending = waiters.get(key) ?? [];
|
|
102
|
+
pending.push(resolve);
|
|
103
|
+
waiters.set(key, pending);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}),
|
|
107
|
+
xAck: vi.fn(async () => 1),
|
|
108
|
+
xAutoClaim: vi.fn(async () => ({ nextId: '0-0', messages: [], deletedMessages: [] })),
|
|
109
|
+
};
|
|
110
|
+
return raw;
|
|
111
|
+
}
|
|
112
|
+
const root = makeRaw();
|
|
113
|
+
const hasGroup = (topic, group) => cursors.has(`${STREAM_PREFIX}${topic}::${group}`);
|
|
114
|
+
const failNextGroupCreate = (err) => {
|
|
115
|
+
nextGroupCreateError = err;
|
|
116
|
+
};
|
|
117
|
+
return { client: mock(root), root, duplicates, hasGroup, failNextGroupCreate };
|
|
118
|
+
}
|
|
119
|
+
// `subscribe()` returns before its consumer group exists - the loop creates the group
|
|
120
|
+
// asynchronously, after `await reader.connect()`. Publishing into that window is the
|
|
121
|
+
// one case a '$' group genuinely drops (see the class docstring), so a test that
|
|
122
|
+
// means to exercise steady-state delivery must wait the group out first, the way a
|
|
123
|
+
// real deployment finishes booting before it serves traffic.
|
|
124
|
+
async function awaitGroup(fake, topic, group,
|
|
125
|
+
// Default 1s is under the loop's 2s retry backoff, so a test exercising a failed
|
|
126
|
+
// first attempt must allow for at least one of those.
|
|
127
|
+
timeout = 4_000) {
|
|
128
|
+
await vi.waitFor(() => {
|
|
129
|
+
expect(fake.hasGroup(topic, group)).toBe(true);
|
|
130
|
+
}, { timeout });
|
|
131
|
+
}
|
|
132
|
+
function makeEnvelope(topic, overrides = {}) {
|
|
133
|
+
return {
|
|
134
|
+
eventId: 'evt-1',
|
|
135
|
+
topic,
|
|
136
|
+
payload: { ok: true },
|
|
137
|
+
occurredAt: '2026-01-01T00:00:00.000Z',
|
|
138
|
+
schemaVersion: 1,
|
|
139
|
+
...overrides,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function deferred() {
|
|
143
|
+
let resolve;
|
|
144
|
+
const promise = new Promise((r) => {
|
|
145
|
+
resolve = r;
|
|
146
|
+
});
|
|
147
|
+
return { promise, resolve };
|
|
148
|
+
}
|
|
149
|
+
describe('RedisStreamsBroker', () => {
|
|
150
|
+
it('publish XADDs the serialized envelope with a MAXLEN trim, on the shared client', async () => {
|
|
151
|
+
const fake = fakeStreamsClient();
|
|
152
|
+
const broker = new RedisStreamsBroker(fake.client, { serviceName: 'svc' });
|
|
153
|
+
const envelope = makeEnvelope('wallet.deposit.completed');
|
|
154
|
+
await broker.publish(envelope);
|
|
155
|
+
expect(fake.root.xAdd).toHaveBeenCalledWith('oss:evt:wallet.deposit.completed', '*', { data: JSON.stringify(envelope) }, { TRIM: { strategy: 'MAXLEN', strategyModifier: '~', threshold: expect.any(Number) } });
|
|
156
|
+
// publish never touches a duplicated (blocking-read) connection.
|
|
157
|
+
expect(fake.duplicates).toHaveLength(0);
|
|
158
|
+
});
|
|
159
|
+
it('coalesces two subscribers on the same topic into one loop: both receive, default group is the service name, one XACK', async () => {
|
|
160
|
+
const fake = fakeStreamsClient();
|
|
161
|
+
const broker = new RedisStreamsBroker(fake.client, { serviceName: 'wallet-svc' });
|
|
162
|
+
const seen1 = deferred();
|
|
163
|
+
const seen2 = deferred();
|
|
164
|
+
broker.subscribe('wallet.deposit.completed', (env) => seen1.resolve(env));
|
|
165
|
+
broker.subscribe('wallet.deposit.completed', (env) => seen2.resolve(env));
|
|
166
|
+
expect(fake.duplicates).toHaveLength(1);
|
|
167
|
+
await awaitGroup(fake, 'wallet.deposit.completed', 'wallet-svc');
|
|
168
|
+
const envelope = makeEnvelope('wallet.deposit.completed');
|
|
169
|
+
await broker.publish(envelope);
|
|
170
|
+
expect(await seen1.promise).toEqual(envelope);
|
|
171
|
+
expect(await seen2.promise).toEqual(envelope);
|
|
172
|
+
await vi.waitFor(() => {
|
|
173
|
+
expect(fake.duplicates[0]?.xAck).toHaveBeenCalledTimes(1);
|
|
174
|
+
});
|
|
175
|
+
expect(fake.duplicates[0]?.xGroupCreate).toHaveBeenCalledWith('oss:evt:wallet.deposit.completed', 'wallet-svc', '$', { MKSTREAM: true });
|
|
176
|
+
await broker.close();
|
|
177
|
+
});
|
|
178
|
+
it('opts.consumerGroup overrides the default group and starts its own loop', async () => {
|
|
179
|
+
const fake = fakeStreamsClient();
|
|
180
|
+
const broker = new RedisStreamsBroker(fake.client, { serviceName: 'wallet-svc' });
|
|
181
|
+
const seenDefault = deferred();
|
|
182
|
+
const seenCustom = deferred();
|
|
183
|
+
broker.subscribe('wallet.deposit.completed', (env) => seenDefault.resolve(env));
|
|
184
|
+
broker.subscribe('wallet.deposit.completed', (env) => seenCustom.resolve(env), {
|
|
185
|
+
consumerGroup: 'analytics',
|
|
186
|
+
});
|
|
187
|
+
// distinct (topic, group) pairs -> distinct loops/connections.
|
|
188
|
+
expect(fake.duplicates).toHaveLength(2);
|
|
189
|
+
await awaitGroup(fake, 'wallet.deposit.completed', 'wallet-svc');
|
|
190
|
+
await awaitGroup(fake, 'wallet.deposit.completed', 'analytics');
|
|
191
|
+
const envelope = makeEnvelope('wallet.deposit.completed');
|
|
192
|
+
await broker.publish(envelope);
|
|
193
|
+
expect(await seenDefault.promise).toEqual(envelope);
|
|
194
|
+
expect(await seenCustom.promise).toEqual(envelope);
|
|
195
|
+
expect(fake.duplicates.map((d) => d.xGroupCreate.mock.calls[0]?.[1])).toEqual(expect.arrayContaining(['wallet-svc', 'analytics']));
|
|
196
|
+
await broker.close();
|
|
197
|
+
});
|
|
198
|
+
it('unsubscribe stops delivery to that handler and tears down the loop once the last handler leaves', async () => {
|
|
199
|
+
const fake = fakeStreamsClient();
|
|
200
|
+
const broker = new RedisStreamsBroker(fake.client, { serviceName: 'svc' });
|
|
201
|
+
const handler1 = vi.fn();
|
|
202
|
+
const seen2 = deferred();
|
|
203
|
+
const unsubscribe1 = broker.subscribe('wallet.deposit.completed', handler1);
|
|
204
|
+
const unsubscribe2 = broker.subscribe('wallet.deposit.completed', (env) => seen2.resolve(env));
|
|
205
|
+
unsubscribe1();
|
|
206
|
+
await awaitGroup(fake, 'wallet.deposit.completed', 'svc');
|
|
207
|
+
const envelope = makeEnvelope('wallet.deposit.completed');
|
|
208
|
+
await broker.publish(envelope);
|
|
209
|
+
expect(await seen2.promise).toEqual(envelope);
|
|
210
|
+
expect(handler1).not.toHaveBeenCalled();
|
|
211
|
+
const reader = fake.duplicates[0];
|
|
212
|
+
expect(reader?.destroy).not.toHaveBeenCalled();
|
|
213
|
+
unsubscribe2();
|
|
214
|
+
expect(reader?.destroy).toHaveBeenCalledTimes(1);
|
|
215
|
+
});
|
|
216
|
+
it('close stops every loop by destroying its duplicated reader connection, not the shared client', async () => {
|
|
217
|
+
const fake = fakeStreamsClient();
|
|
218
|
+
const broker = new RedisStreamsBroker(fake.client, { serviceName: 'svc' });
|
|
219
|
+
broker.subscribe('wallet.deposit.completed', vi.fn());
|
|
220
|
+
broker.subscribe('kyc.verification.completed', vi.fn());
|
|
221
|
+
expect(fake.duplicates).toHaveLength(2);
|
|
222
|
+
await broker.close();
|
|
223
|
+
for (const reader of fake.duplicates) {
|
|
224
|
+
expect(reader.destroy).toHaveBeenCalledTimes(1);
|
|
225
|
+
}
|
|
226
|
+
expect(fake.root.destroy).not.toHaveBeenCalled();
|
|
227
|
+
});
|
|
228
|
+
it('tolerates BUSYGROUP - a group a previous replica already created is not an error', async () => {
|
|
229
|
+
const fake = fakeStreamsClient();
|
|
230
|
+
const first = new RedisStreamsBroker(fake.client, { serviceName: 'svc' });
|
|
231
|
+
first.subscribe('wallet.deposit.completed', vi.fn());
|
|
232
|
+
await awaitGroup(fake, 'wallet.deposit.completed', 'svc');
|
|
233
|
+
await first.close();
|
|
234
|
+
// Same (topic, group) against the same Redis: xGroupCreate comes back BUSYGROUP,
|
|
235
|
+
// which must not stop this loop from consuming.
|
|
236
|
+
const second = new RedisStreamsBroker(fake.client, { serviceName: 'svc' });
|
|
237
|
+
const seen = deferred();
|
|
238
|
+
second.subscribe('wallet.deposit.completed', (env) => seen.resolve(env));
|
|
239
|
+
const envelope = makeEnvelope('wallet.deposit.completed');
|
|
240
|
+
await second.publish(envelope);
|
|
241
|
+
// Delivery is the proof: the second loop got past a BUSYGROUP rejection.
|
|
242
|
+
expect(await seen.promise).toEqual(envelope);
|
|
243
|
+
await expect(fake.duplicates[1]?.xGroupCreate.mock.results[0]?.value).rejects.toThrow(/BUSYGROUP/);
|
|
244
|
+
await second.close();
|
|
245
|
+
});
|
|
246
|
+
it('recovers from a failed group creation without re-opening the already-open socket', async () => {
|
|
247
|
+
const fake = fakeStreamsClient();
|
|
248
|
+
const broker = new RedisStreamsBroker(fake.client, { serviceName: 'svc' });
|
|
249
|
+
// Fail the first group creation - it runs after connect() has already opened the
|
|
250
|
+
// socket. A loop that reset its readiness and re-called connect() here would take
|
|
251
|
+
// 'Socket already opened' on every retry and never consume again.
|
|
252
|
+
fake.failNextGroupCreate(new Error('READONLY You cannot write against a replica'));
|
|
253
|
+
const seen = deferred();
|
|
254
|
+
broker.subscribe('wallet.deposit.completed', (env) => seen.resolve(env));
|
|
255
|
+
await awaitGroup(fake, 'wallet.deposit.completed', 'svc');
|
|
256
|
+
const envelope = makeEnvelope('wallet.deposit.completed');
|
|
257
|
+
await broker.publish(envelope);
|
|
258
|
+
expect(await seen.promise).toEqual(envelope);
|
|
259
|
+
const reader = fake.duplicates[0];
|
|
260
|
+
expect(reader?.xGroupCreate.mock.calls.length).toBeGreaterThan(1);
|
|
261
|
+
expect(reader?.connect).toHaveBeenCalledTimes(1);
|
|
262
|
+
await broker.close();
|
|
263
|
+
});
|
|
264
|
+
it('defaults the group to $ - a backlog published before it existed is not replayed', async () => {
|
|
265
|
+
const fake = fakeStreamsClient();
|
|
266
|
+
const broker = new RedisStreamsBroker(fake.client, { serviceName: 'svc' });
|
|
267
|
+
const before = makeEnvelope('wallet.deposit.completed', { eventId: 'before' });
|
|
268
|
+
await broker.publish(before);
|
|
269
|
+
const handler = vi.fn();
|
|
270
|
+
broker.subscribe('wallet.deposit.completed', handler);
|
|
271
|
+
await awaitGroup(fake, 'wallet.deposit.completed', 'svc');
|
|
272
|
+
const after = makeEnvelope('wallet.deposit.completed', { eventId: 'after' });
|
|
273
|
+
await broker.publish(after);
|
|
274
|
+
await vi.waitFor(() => {
|
|
275
|
+
expect(handler).toHaveBeenCalledWith(after);
|
|
276
|
+
});
|
|
277
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
278
|
+
expect(handler).not.toHaveBeenCalledWith(before);
|
|
279
|
+
await broker.close();
|
|
280
|
+
});
|
|
281
|
+
it("startId '0' replays the retained backlog into a group created after the fact", async () => {
|
|
282
|
+
const fake = fakeStreamsClient();
|
|
283
|
+
const broker = new RedisStreamsBroker(fake.client, { serviceName: 'svc', startId: '0' });
|
|
284
|
+
const before = makeEnvelope('wallet.deposit.completed', { eventId: 'before' });
|
|
285
|
+
await broker.publish(before);
|
|
286
|
+
const seen = deferred();
|
|
287
|
+
broker.subscribe('wallet.deposit.completed', (env) => seen.resolve(env));
|
|
288
|
+
expect(await seen.promise).toEqual(before);
|
|
289
|
+
expect(fake.duplicates[0]?.xGroupCreate).toHaveBeenCalledWith(`${STREAM_PREFIX}wallet.deposit.completed`, 'svc', '0', { MKSTREAM: true });
|
|
290
|
+
await broker.close();
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
//# sourceMappingURL=redis-streams-broker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-streams-broker.test.js","sourceRoot":"","sources":["../../../../src/server/kernel/__tests__/redis-streams-broker.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,4 @@
|
|
|
1
1
|
import type { CacheAdapter } from '@openora/core/contracts';
|
|
2
|
-
export declare class InProcessCache implements CacheAdapter {
|
|
3
|
-
private readonly entries;
|
|
4
|
-
private readonly sweeper;
|
|
5
|
-
constructor();
|
|
6
|
-
get<T>(key: string): Promise<T | undefined>;
|
|
7
|
-
set<T>(key: string, value: T, opts: {
|
|
8
|
-
ttlMs: number;
|
|
9
|
-
}): Promise<void>;
|
|
10
|
-
delete(key: string | string[]): Promise<void>;
|
|
11
|
-
private sweep;
|
|
12
|
-
close(): void;
|
|
13
|
-
}
|
|
14
2
|
export declare function cached<T>(cache: CacheAdapter | undefined, key: string, ttlMs: number, loader: () => Promise<T>): Promise<T>;
|
|
15
3
|
export declare function invalidate(cache: CacheAdapter | undefined, keys: string | string[]): Promise<void>;
|
|
16
4
|
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/server/kernel/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/server/kernel/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAQ5D,wBAAsB,MAAM,CAAC,CAAC,EAC5B,KAAK,EAAE,YAAY,GAAG,SAAS,EAC/B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAuBZ;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE,YAAY,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CASf"}
|
|
@@ -1,60 +1,5 @@
|
|
|
1
1
|
import { createLogger } from './logger.js';
|
|
2
2
|
const logger = createLogger('cache');
|
|
3
|
-
const SWEEP_INTERVAL_MS = 60_000;
|
|
4
|
-
// ponytail: hard cap bounds memory against unbounded key growth (eg per-slug churn);
|
|
5
|
-
// eviction is oldest-insert (Map iteration order), not LRU - swap for an LRU if
|
|
6
|
-
// hit-rate under heavy key churn ever matters.
|
|
7
|
-
const MAX_ENTRIES = 5_000;
|
|
8
|
-
// Zero-dependency in-process default (set REDIS_URL to bind the distributed Redis
|
|
9
|
-
// reference adapter instead). Expiry is lazy (checked on access) plus an unref'd
|
|
10
|
-
// sweep so keys never revisited don't accumulate.
|
|
11
|
-
export class InProcessCache {
|
|
12
|
-
entries = new Map();
|
|
13
|
-
sweeper;
|
|
14
|
-
constructor() {
|
|
15
|
-
this.sweeper = setInterval(() => this.sweep(), SWEEP_INTERVAL_MS);
|
|
16
|
-
this.sweeper.unref?.();
|
|
17
|
-
}
|
|
18
|
-
get(key) {
|
|
19
|
-
const entry = this.entries.get(key);
|
|
20
|
-
if (!entry) {
|
|
21
|
-
return Promise.resolve(undefined);
|
|
22
|
-
}
|
|
23
|
-
if (Date.now() >= entry.expiresAt) {
|
|
24
|
-
this.entries.delete(key);
|
|
25
|
-
return Promise.resolve(undefined);
|
|
26
|
-
}
|
|
27
|
-
return Promise.resolve(entry.value);
|
|
28
|
-
}
|
|
29
|
-
set(key, value, opts) {
|
|
30
|
-
if (!this.entries.has(key) && this.entries.size >= MAX_ENTRIES) {
|
|
31
|
-
const oldestKey = this.entries.keys().next().value;
|
|
32
|
-
if (oldestKey !== undefined) {
|
|
33
|
-
this.entries.delete(oldestKey);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
this.entries.set(key, { value, expiresAt: Date.now() + opts.ttlMs });
|
|
37
|
-
return Promise.resolve();
|
|
38
|
-
}
|
|
39
|
-
delete(key) {
|
|
40
|
-
for (const k of Array.isArray(key) ? key : [key]) {
|
|
41
|
-
this.entries.delete(k);
|
|
42
|
-
}
|
|
43
|
-
return Promise.resolve();
|
|
44
|
-
}
|
|
45
|
-
sweep() {
|
|
46
|
-
const now = Date.now();
|
|
47
|
-
for (const [key, entry] of this.entries) {
|
|
48
|
-
if (now >= entry.expiresAt) {
|
|
49
|
-
this.entries.delete(key);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
close() {
|
|
54
|
-
clearInterval(this.sweeper);
|
|
55
|
-
this.entries.clear();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
3
|
// ponytail: no single-flight guard - concurrent misses on the same key each run
|
|
59
4
|
// `loader`, so a hot key can stampede on cache-miss. Acceptable for the TTLs this
|
|
60
5
|
// is bound at (seconds); add a per-key in-flight promise map if that ever changes.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/server/kernel/cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/server/kernel/cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;AAErC,gFAAgF;AAChF,kFAAkF;AAClF,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,KAA+B,EAC/B,GAAW,EACX,KAAa,EACb,MAAwB;IAExB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,MAAM,EAAE,CAAC;IAClB,CAAC;IAED,IAAI,GAAkB,CAAC;IACvB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;QAC9C,GAAG,GAAG,SAAS,CAAC;IAClB,CAAC;IACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAA+B,EAC/B,IAAuB;IAEvB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,yBAAyB,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Token, type MessageBrokerAdapter, type OutboxWriter, type EventEnvelope, type
|
|
1
|
+
import { type Token, type MessageBrokerAdapter, type OutboxWriter, type EventEnvelope, type DomainEventName, type DomainEventPayload } from '@openora/core/contracts';
|
|
2
2
|
import type { Logger } from 'pino';
|
|
3
3
|
export type EventHandler<T = unknown> = (payload: T, envelope?: EventEnvelope) => void | Promise<void>;
|
|
4
4
|
export type EventBus = {
|
|
@@ -10,21 +10,6 @@ export type EventBus = {
|
|
|
10
10
|
on(event: string, handler: EventHandler): () => void;
|
|
11
11
|
};
|
|
12
12
|
export declare const EVENT_BUS: Token<EventBus>;
|
|
13
|
-
/**
|
|
14
|
-
* Default in-process `MESSAGE_BROKER` - `publish` fans out synchronously to
|
|
15
|
-
* whatever's subscribed in THIS process only; it does not survive a restart
|
|
16
|
-
* and does not reach other replicas. An overlay rebinds `MESSAGE_BROKER` to a
|
|
17
|
-
* durable `MessageBrokerAdapter` (eg RabbitMQ via `AMQP_URL`) once events must
|
|
18
|
-
* cross a process boundary. `subscribe`'s returned unsubscribe function is
|
|
19
|
-
* safe to call mid-dispatch: the handler list is copied on write, never
|
|
20
|
-
* mutated in place.
|
|
21
|
-
*/
|
|
22
|
-
export declare class InMemoryBroker implements MessageBrokerAdapter {
|
|
23
|
-
private readonly handlers;
|
|
24
|
-
publish(envelope: EventEnvelope): void;
|
|
25
|
-
subscribe(topic: string, handler: (env: EventEnvelope) => void | Promise<void>, _options?: SubscribeOptions): () => void;
|
|
26
|
-
close(): Promise<void>;
|
|
27
|
-
}
|
|
28
13
|
/** Typed facade over a MessageBrokerAdapter. Validates known payloads, isolates subscriber failures, and builds the envelope. */
|
|
29
14
|
export declare function createEventBus(broker: MessageBrokerAdapter, logger?: Logger, outbox?: OutboxWriter): EventBus;
|
|
30
15
|
//# sourceMappingURL=event-bus.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../../src/server/kernel/event-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,KAAK,EACV,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../../src/server/kernel/event-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,KAAK,EACV,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,aAAa,EAGlB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI,CACtC,OAAO,EAAE,CAAC,EACV,QAAQ,CAAC,EAAE,aAAa,KACrB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAK1B,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,CAAC,CAAC,SAAS,eAAe,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAChF,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAS5C,iBAAiB,CAAC,CAAC,SAAS,eAAe,EACzC,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,iBAAiB,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,EAAE,CAAC,CAAC,SAAS,eAAe,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAClG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,IAAI,CAAC;CACtD,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,QAAQ,CAA4B,CAAC;AAkBnE,iIAAiI;AACjI,wBAAgB,cAAc,CAC5B,MAAM,EAAE,oBAAoB,EAC5B,MAAM,GAAE,MAAkC,EAC1C,MAAM,CAAC,EAAE,YAAY,GACpB,QAAQ,CA2CV"}
|
|
@@ -2,35 +2,6 @@ import { createToken, domainEventSchemas, getEventVersion, } from '@openora/core
|
|
|
2
2
|
import { createLogger } from './logger.js';
|
|
3
3
|
import { getCurrentTraceId } from './request-context.js';
|
|
4
4
|
export const EVENT_BUS = createToken('EVENT_BUS');
|
|
5
|
-
/**
|
|
6
|
-
* Default in-process `MESSAGE_BROKER` - `publish` fans out synchronously to
|
|
7
|
-
* whatever's subscribed in THIS process only; it does not survive a restart
|
|
8
|
-
* and does not reach other replicas. An overlay rebinds `MESSAGE_BROKER` to a
|
|
9
|
-
* durable `MessageBrokerAdapter` (eg RabbitMQ via `AMQP_URL`) once events must
|
|
10
|
-
* cross a process boundary. `subscribe`'s returned unsubscribe function is
|
|
11
|
-
* safe to call mid-dispatch: the handler list is copied on write, never
|
|
12
|
-
* mutated in place.
|
|
13
|
-
*/
|
|
14
|
-
export class InMemoryBroker {
|
|
15
|
-
handlers = new Map();
|
|
16
|
-
publish(envelope) {
|
|
17
|
-
for (const fn of this.handlers.get(envelope.topic) ?? []) {
|
|
18
|
-
void fn(envelope);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
subscribe(topic, handler, _options) {
|
|
22
|
-
const fns = this.handlers.get(topic) ?? [];
|
|
23
|
-
const updated = [...fns, handler];
|
|
24
|
-
this.handlers.set(topic, updated);
|
|
25
|
-
return () => {
|
|
26
|
-
const current = this.handlers.get(topic) ?? [];
|
|
27
|
-
this.handlers.set(topic, current.filter((f) => f !== handler));
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
async close() {
|
|
31
|
-
this.handlers.clear();
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
5
|
function isKnownEvent(event) {
|
|
35
6
|
return event in domainEventSchemas;
|
|
36
7
|
}
|
|
@@ -61,13 +32,13 @@ export function createEventBus(broker, logger = createLogger('event-bus'), outbo
|
|
|
61
32
|
emit(event, payload) {
|
|
62
33
|
validate(event, payload);
|
|
63
34
|
const envelope = buildEnvelope(event, payload);
|
|
64
|
-
void broker.publish(envelope);
|
|
35
|
+
void Promise.resolve(broker.publish(envelope)).catch((err) => logger.error({ event, err }, 'event publish failed'));
|
|
65
36
|
},
|
|
66
37
|
async emitInTransaction(tx, event, payload) {
|
|
67
38
|
if (!outbox) {
|
|
68
39
|
throw new Error(`emitInTransaction('${event}') requires the transactional outbox, which is not bound. ` +
|
|
69
|
-
`Enable it (set OUTBOX_ENABLED=1
|
|
70
|
-
`
|
|
40
|
+
`Enable it (set OUTBOX_ENABLED=1) so the event is published reliably, or use emit() ` +
|
|
41
|
+
`for best-effort post-commit delivery.`);
|
|
71
42
|
}
|
|
72
43
|
validate(event, payload);
|
|
73
44
|
await outbox.write(tx, buildEnvelope(event, payload));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/server/kernel/event-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,
|
|
1
|
+
{"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/server/kernel/event-bus.ts"],"names":[],"mappings":"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"}
|