fix: skip deleted reserved turn queues during flush
This commit is contained in:
@@ -26,7 +26,7 @@ import { asRecord } from '@sammo-ts/common';
|
||||
|
||||
import type { TurnDaemonCommandResult, TurnDaemonHooks } from '../lifecycle/types.js';
|
||||
import type { InMemoryTurnWorld } from './inMemoryWorld.js';
|
||||
import type { InMemoryReservedTurnStore } from './reservedTurnStore.js';
|
||||
import type { InMemoryReservedTurnStore, ReservedTurnChanges } from './reservedTurnStore.js';
|
||||
import { buildDiplomacyMeta } from '@sammo-ts/logic';
|
||||
import { ensureItemInventory, withSerializedItemInventory } from '@sammo-ts/logic/items/index.js';
|
||||
import { persistGeneralLifecycleEvents } from './generalTurnLifecyclePersistence.js';
|
||||
@@ -43,6 +43,26 @@ export interface DatabaseTurnHooks {
|
||||
close(): Promise<void>;
|
||||
}
|
||||
|
||||
export const excludeDeletedReservedTurnQueues = (
|
||||
changes: ReservedTurnChanges,
|
||||
deletedGeneralIds: readonly number[],
|
||||
deletedNationIds: readonly number[]
|
||||
): ReservedTurnChanges => {
|
||||
const deletedGenerals = new Set(deletedGeneralIds);
|
||||
const deletedNations = new Set(deletedNationIds);
|
||||
const keepGeneral = (generalId: number): boolean => !deletedGenerals.has(generalId);
|
||||
const keepNation = (key: string): boolean => !deletedNations.has(Number(key.split(':', 1)[0]));
|
||||
|
||||
return {
|
||||
generalIds: changes.generalIds.filter(keepGeneral),
|
||||
generalInitializationIds: changes.generalInitializationIds.filter(keepGeneral),
|
||||
generalLeaseIds: changes.generalLeaseIds.filter(keepGeneral),
|
||||
nationKeys: changes.nationKeys.filter(keepNation),
|
||||
nationInitializationKeys: changes.nationInitializationKeys.filter(keepNation),
|
||||
nationLeaseKeys: changes.nationLeaseKeys.filter(keepNation),
|
||||
};
|
||||
};
|
||||
|
||||
const asJson = (value: unknown): InputJsonValue => value as InputJsonValue;
|
||||
const formatLegacyNumber = (value: number): string => Math.round(value).toLocaleString('en-US');
|
||||
|
||||
@@ -602,6 +622,9 @@ export const createDatabaseTurnHooks = async (
|
||||
pendingUnificationFinalizations,
|
||||
} = changes;
|
||||
const reservedTurnChanges = options?.reservedTurns?.peekDirtyState();
|
||||
const persistedReservedTurnChanges = reservedTurnChanges
|
||||
? excludeDeletedReservedTurnQueues(reservedTurnChanges, deletedGenerals, deletedNations)
|
||||
: undefined;
|
||||
|
||||
const worldStateUpdate: TurnEngineWorldStateUpdateInput = {
|
||||
currentYear: state.currentYear,
|
||||
@@ -1010,8 +1033,8 @@ export const createDatabaseTurnHooks = async (
|
||||
message
|
||||
);
|
||||
}
|
||||
if (options?.reservedTurns && reservedTurnChanges) {
|
||||
await options.reservedTurns.persistChanges(prisma, reservedTurnChanges);
|
||||
if (options?.reservedTurns && persistedReservedTurnChanges) {
|
||||
await options.reservedTurns.persistChanges(prisma, persistedReservedTurnChanges);
|
||||
}
|
||||
if (commandCompletion) {
|
||||
await prisma.inputEvent.update({
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { excludeDeletedReservedTurnQueues } from '../src/turn/databaseHooks.js';
|
||||
|
||||
describe('excludeDeletedReservedTurnQueues', () => {
|
||||
it('omits dirty, initialization, and leased queues owned by deleted entities', () => {
|
||||
expect(
|
||||
excludeDeletedReservedTurnQueues(
|
||||
{
|
||||
generalIds: [1, 2],
|
||||
generalInitializationIds: [2, 3],
|
||||
generalLeaseIds: [1, 2, 3],
|
||||
nationKeys: ['10:12', '20:11'],
|
||||
nationInitializationKeys: ['20:9', '30:12'],
|
||||
nationLeaseKeys: ['10:12', '20:11', '30:12'],
|
||||
},
|
||||
[2],
|
||||
[20]
|
||||
)
|
||||
).toEqual({
|
||||
generalIds: [1],
|
||||
generalInitializationIds: [3],
|
||||
generalLeaseIds: [1, 3],
|
||||
nationKeys: ['10:12'],
|
||||
nationInitializationKeys: ['30:12'],
|
||||
nationLeaseKeys: ['10:12', '30:12'],
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -524,6 +524,12 @@ integration('RaiseInvader database persistence', () => {
|
||||
).toBe(30);
|
||||
}
|
||||
|
||||
await reservedTurns.prepareTurnsForExecution(firstCreatedGeneralId, {
|
||||
nationId: createdNationId,
|
||||
officerLevel: 12,
|
||||
});
|
||||
reservedTurns.shiftGeneralTurns(firstCreatedGeneralId, -1);
|
||||
reservedTurns.shiftNationTurns(createdNationId, 12, -1);
|
||||
for (const generalId of createdGeneralIds) {
|
||||
expect(world.removeGeneral(generalId)).toBe(true);
|
||||
}
|
||||
@@ -539,6 +545,20 @@ integration('RaiseInvader database persistence', () => {
|
||||
});
|
||||
|
||||
expect(await db.event.findUnique({ where: { id: createdEventIds[1]! } })).toBeNull();
|
||||
expect(await db.generalTurnRevision.findUnique({ where: { generalId: firstCreatedGeneralId } })).toBeNull();
|
||||
expect(
|
||||
await db.nationTurnRevision.findUnique({
|
||||
where: {
|
||||
nationId_officerLevel: { nationId: createdNationId, officerLevel: 12 },
|
||||
},
|
||||
})
|
||||
).toBeNull();
|
||||
expect(reservedTurns.inspectState()).toMatchObject({
|
||||
dirtyGeneralIds: [],
|
||||
dirtyNationKeys: [],
|
||||
leasedGeneralIds: [],
|
||||
leasedNationKeys: [],
|
||||
});
|
||||
expect(await db.worldState.findUniqueOrThrow({ where: { id: stateRow.id } })).toMatchObject({
|
||||
meta: expect.objectContaining({ isunited: 3, isUnited: 3, refreshLimit: 300 }),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user