feat: dashboard source coverage를 안전하게 활성화

엔진의 부대·예약턴·집계 변화와 mailbox writer를 저널에 연결하고 dashboard.global 및 인증 아이콘 source를 dependency vector에 포함한다. post-deploy coverage v1 활성화는 shared head seed와 CAS를 한 transaction으로 수행한다.
This commit is contained in:
2026-08-16 18:51:17 +00:00
parent 346f796cfc
commit 1a77bb3df1
16 changed files with 404 additions and 22 deletions
@@ -24,6 +24,7 @@ export interface UnificationFinalizationInput {
export interface UnificationFinalizationResult {
status: 'APPLIED' | 'ALREADY_APPLIED';
generationKey: string;
messageMailboxes: number[];
}
const readNumber = (value: unknown): number => (typeof value === 'number' && Number.isFinite(value) ? value : 0);
@@ -140,7 +141,8 @@ const cancelPendingUniqueAuctions = async (
transaction: GamePrisma.TransactionClient,
input: UnificationFinalizationInput,
world: InMemoryTurnWorld
): Promise<void> => {
): Promise<number[]> => {
const messageMailboxes: number[] = [];
const lockedRows = await transaction.$queryRaw<LockedUnificationAuctionRow[]>`
SELECT
auction.id AS "auctionId",
@@ -245,9 +247,17 @@ const cancelPendingUniqueAuctions = async (
time: input.completedAt,
validUntil: new Date('9999-12-31T00:00:00.000Z'),
};
await sendMessage({ insertMessage: (draft) => insertMessage(transaction, draft) }, message, {
sendDestOnly: true,
});
await sendMessage(
{
insertMessage: async (draft) => {
const messageId = await insertMessage(transaction, draft);
messageMailboxes.push(draft.mailbox);
return messageId;
},
},
message,
{ sendDestOnly: true }
);
}
await transaction.auction.update({
@@ -255,6 +265,7 @@ const cancelPendingUniqueAuctions = async (
data: { status: 'CANCELED', finishedAt: input.completedAt },
});
}
return messageMailboxes;
};
export const persistUnificationFinalization = async (
@@ -267,7 +278,7 @@ export const persistUnificationFinalization = async (
}
const claim = await claimGeneration(transaction, input);
if (claim === 'ALREADY_APPLIED') {
return { status: 'ALREADY_APPLIED', generationKey: input.generationKey };
return { status: 'ALREADY_APPLIED', generationKey: input.generationKey, messageMailboxes: [] };
}
const state = world.getState();
@@ -298,7 +309,7 @@ export const persistUnificationFinalization = async (
// Ref cancels and refunds every unfinished unique auction before it merges
// inheritance. Keep that order inside the generation transaction.
await cancelPendingUniqueAuctions(transaction, input, world);
const messageMailboxes = await cancelPendingUniqueAuctions(transaction, input, world);
const pointRows = eligibleGenerals.length
? await transaction.inheritancePoint.findMany({
@@ -655,5 +666,5 @@ export const persistUnificationFinalization = async (
},
});
return { status: 'APPLIED', generationKey: input.generationKey };
return { status: 'APPLIED', generationKey: input.generationKey, messageMailboxes };
};