feat: 직접 writer를 내구성 변화 저널에 연결

86개 API mutation을 분류하고 메시지 mailbox, 베팅, 국가 설정, 예약 명령의 revision/outbox 표식을 소유 transaction에 연결한다. 공개 SSE는 식별자 없는 invalidation만 노출한다.
This commit is contained in:
2026-08-16 18:38:08 +00:00
parent e4ac2a60b1
commit dd4645e4d0
22 changed files with 485 additions and 55 deletions
+8 -1
View File
@@ -11,7 +11,14 @@ import {
describe('ChangeJournal', () => {
it('keeps viewer-filtering semantics as distinct durable domains', () => {
expect(READ_MODEL_DOMAINS).toEqual(
expect.arrayContaining(['map.general', 'lobby.general', 'contacts.world', 'reserved.general'])
expect.arrayContaining([
'map.general',
'lobby.general',
'contacts.world',
'reserved.general',
'messages.mailbox',
'dashboard.global',
])
);
});
+18 -1
View File
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest';
import {
hasRealtimeReadModelChanges,
parseReadModelOutboxPayload,
readModelOutboxPayloadToMessageMailboxes,
readModelOutboxPayloadToChanges,
resolveRealtimeReadModelInvalidation,
} from '../src/index.js';
@@ -71,11 +72,12 @@ describe('read-model outbox payload', () => {
);
});
it('keeps access-only, tournament, and betting domains off the dashboard channel', () => {
it('keeps source-only, access-only, tournament, and betting domains off the dashboard channel', () => {
const payload = parseReadModelOutboxPayload({
version: 1,
changes: [
['access.general', 7, '1'],
['dashboard.global', 0, '1'],
['tournament', 0, '1'],
['betting', 0, '1'],
],
@@ -83,4 +85,19 @@ describe('read-model outbox payload', () => {
if (!payload) throw new Error('valid payload rejected');
expect(hasRealtimeReadModelChanges(readModelOutboxPayloadToChanges(payload))).toBe(false);
});
it('keeps durable mailbox revisions separate from dashboard invalidations', () => {
const payload = parseReadModelOutboxPayload({
version: 1,
changes: [
['messages.mailbox', 9999, '3'],
['messages.mailbox', 7, '2'],
['messages.mailbox', 7, '2'],
],
});
if (!payload) throw new Error('valid payload rejected');
expect(readModelOutboxPayloadToMessageMailboxes(payload)).toEqual([7, 9999]);
expect(hasRealtimeReadModelChanges(readModelOutboxPayloadToChanges(payload))).toBe(false);
});
});