fix: 시즌별 설문 알림 상태를 분리

설문 확인 cursor와 메인 실시간 탭 범위를 reset 고유 serverId로 구분한다. 설문 생성의 daemon 비의존 outbox 경로와 이전 시즌 cursor 회귀를 테스트한다.
This commit is contained in:
2026-08-19 12:20:26 +00:00
parent 17a3072ba7
commit 54a5b91ca9
9 changed files with 81 additions and 4 deletions
@@ -6,10 +6,23 @@ import type { ReadModelOutboxDatabase } from '@sammo-ts/infra';
import { ReadModelOutboxWorker } from '../src/realtime/outboxWorker.js';
const payload = (
domain: 'front.general' | 'access.general' | 'dashboard.global' | 'messages.mailbox' | 'tournament' | 'betting'
domain:
| 'front.global'
| 'front.general'
| 'access.general'
| 'dashboard.global'
| 'messages.mailbox'
| 'tournament'
| 'betting'
) => ({
version: 1,
changes: [[domain, domain === 'front.general' || domain === 'access.general' ? 7 : domain === 'messages.mailbox' ? 9999 : 0, '1']],
changes: [
[
domain,
domain === 'front.general' || domain === 'access.general' ? 7 : domain === 'messages.mailbox' ? 9999 : 0,
'1',
],
],
});
const createFixture = (rows: readonly object[]) => {
@@ -26,6 +39,23 @@ const createFixture = (rows: readonly object[]) => {
};
describe('ReadModelOutboxWorker', () => {
it('publishes a survey-style global front-status invalidation without a turn daemon', async () => {
const fixture = createFixture([{ id: 10n, payload: payload('front.global'), attempts: 1 }]);
const worker = new ReadModelOutboxWorker(fixture.db, fixture.redis, 'che:default', {
owner: 'worker-test',
intervalMs: 60_000,
});
worker.start();
await vi.waitFor(() => expect(fixture.updateMany).toHaveBeenCalledTimes(1));
await worker.stop();
expect(JSON.parse(String(fixture.publish.mock.calls[0]?.[1]))).toMatchObject({
type: 'readModelChanged',
changes: { frontStatusChanged: true },
});
});
it('publishes a legacy internal readModelChanged event and acknowledges the durable row', async () => {
const fixture = createFixture([{ id: 11n, payload: payload('front.general'), attempts: 1 }]);
const worker = new ReadModelOutboxWorker(fixture.db, fixture.redis, 'che:default', {