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
@@ -124,7 +124,7 @@ const persistEffects = async (
await persistLogs(db, logs, year, month, at);
};
const refreshFrontStates = async (db: DatabaseClient, mapName: string, nationIds: number[]): Promise<void> => {
const refreshFrontStates = async (db: DatabaseClient, mapName: string, nationIds: number[]): Promise<number[]> => {
const [map, cities, diplomacy] = await Promise.all([
loadMapDefinitionByName(mapName),
db.city.findMany({
@@ -152,6 +152,7 @@ const refreshFrontStates = async (db: DatabaseClient, mapName: string, nationIds
data: { frontState: patch.frontState },
});
}
return patches.map((patch) => patch.id);
};
const buildFailureLog = (generalId: number, reason: string, actionName: string, response: boolean): LogEntryDraft[] => {
@@ -167,6 +168,9 @@ export interface DiplomaticMessageResponseResult {
result: boolean;
reason: string;
affectedMailboxes: number[];
affectedGeneralRecordIds: number[];
affectedNationIds: number[];
affectedCityIds: number[];
}
export const respondToDiplomaticMessage = async (options: {
@@ -201,7 +205,14 @@ export const respondToDiplomaticMessage = async (options: {
world.currentMonth,
now
);
return { result: false, reason, affectedMailboxes: [] };
return {
result: false,
reason,
affectedMailboxes: [],
affectedGeneralRecordIds: [actor.id],
affectedNationIds: [],
affectedCityIds: [],
};
};
const actorNationId = actor.nationId;
@@ -266,6 +277,9 @@ export const respondToDiplomaticMessage = async (options: {
result: true,
reason: 'success',
affectedMailboxes: [MESSAGE_MAILBOX_NATIONAL_BASE + actorNationId],
affectedGeneralRecordIds: [actor.id, proposerGeneralId],
affectedNationIds: [],
affectedCityIds: [],
};
}
@@ -369,11 +383,12 @@ export const respondToDiplomaticMessage = async (options: {
}
);
await persistEffects(db, resolution.effects, world.currentYear, world.currentMonth, now);
let affectedCityIds: number[] = [];
if (resolution.refreshFront) {
const worldConfig = asRecord(world.config);
const environment = asRecord(worldConfig.environment);
const mapName = typeof environment.mapName === 'string' ? environment.mapName : 'che';
await refreshFrontStates(db, mapName, [actorNationId, proposerNationId]);
affectedCityIds = await refreshFrontStates(db, mapName, [actorNationId, proposerNationId]);
}
const proposerMessageNationName = message.payload.src.nationName;
@@ -415,5 +430,8 @@ export const respondToDiplomaticMessage = async (options: {
MESSAGE_MAILBOX_NATIONAL_BASE + actorNationId,
MESSAGE_MAILBOX_NATIONAL_BASE + proposerNationId,
],
affectedGeneralRecordIds: [actor.id, proposerGeneralId],
affectedNationIds: [actorNationId, proposerNationId],
affectedCityIds,
};
};