외교 메시지 응답과 알림 권한 정리

This commit is contained in:
2026-09-04 04:39:00 +00:00
parent 38e516de6d
commit f009c50df5
19 changed files with 225 additions and 45 deletions
@@ -18,6 +18,7 @@ export const READ_MODEL_DOMAINS = [
'contacts.world',
'reserved.general',
'messages.mailbox',
'messages.diplomacyMailbox',
'tournament',
'betting',
] as const;
@@ -15,6 +15,11 @@ export const readModelOutboxPayloadToMessageMailboxes = (
payload.changes.flatMap(([domain, entityId]) => (domain === 'messages.mailbox' ? [entityId] : []))
);
export const readModelOutboxPayloadToDiplomacyMailboxes = (payload: ReadModelOutboxPayloadV1): readonly number[] =>
uniqueSortedIds(
payload.changes.flatMap(([domain, entityId]) => (domain === 'messages.diplomacyMailbox' ? [entityId] : []))
);
export const parseReadModelOutboxPayload = (value: unknown): ReadModelOutboxPayloadV1 | null => {
if (!value || typeof value !== 'object' || Array.isArray(value)) {
return null;
@@ -123,6 +128,7 @@ export const readModelOutboxPayloadToChanges = (
break;
case 'access.general':
case 'messages.mailbox':
case 'messages.diplomacyMailbox':
case 'tournament':
case 'betting':
// These domains have no browser-wide dashboard invalidation.
+4
View File
@@ -59,6 +59,8 @@ export interface RealtimeViewerIdentity {
generalId: number | null;
cityId: number | null;
nationId: number | null;
/** Omitted by older internal producers; absence is treated as no access. */
canReadDiplomacy?: boolean;
}
export const createEmptyRealtimeReadModelInvalidation = (): RealtimeReadModelInvalidation => ({
@@ -216,6 +218,8 @@ export interface MessageCreatedEvent {
export interface MessagesChangedEvent {
type: 'messagesChanged';
mailboxes: number[];
/** Nation mailboxes whose committed changes contain only diplomacy messages. */
diplomacyMailboxes?: number[];
}
/** Redis-owned tournament stage changed after its atomic source revision commit. */
@@ -17,6 +17,7 @@ describe('ChangeJournal', () => {
'contacts.world',
'reserved.general',
'messages.mailbox',
'messages.diplomacyMailbox',
'dashboard.global',
])
);
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest';
import {
hasRealtimeReadModelChanges,
parseReadModelOutboxPayload,
readModelOutboxPayloadToDiplomacyMailboxes,
readModelOutboxPayloadToMessageMailboxes,
readModelOutboxPayloadToChanges,
resolveRealtimeReadModelInvalidation,
@@ -93,11 +94,13 @@ describe('read-model outbox payload', () => {
['messages.mailbox', 9999, '3'],
['messages.mailbox', 7, '2'],
['messages.mailbox', 7, '2'],
['messages.diplomacyMailbox', 9007, '4'],
],
});
if (!payload) throw new Error('valid payload rejected');
expect(readModelOutboxPayloadToMessageMailboxes(payload)).toEqual([7, 9999]);
expect(readModelOutboxPayloadToDiplomacyMailboxes(payload)).toEqual([9007]);
expect(hasRealtimeReadModelChanges(readModelOutboxPayloadToChanges(payload))).toBe(false);
});
});