fix: Ref 게임 로직과 시나리오 풀 호환을 보정
월 경계, 전투 기술 상한, 연감과 베팅·설문·경매 정산 순서를 Ref 계약에 맞춘다.\n\n시나리오 일반 풀을 ENGINE mutation과 logical tick 기반으로 직렬화하고 914·915 catalog 및 조건부 100기 pool 실행 경계를 추가한다.\n\n경매 worker는 세대별 durable event만 만들고 ENGINE이 row lock 후 상태 전이와 정산을 단일 transaction으로 소유한다.
This commit is contained in:
@@ -221,6 +221,25 @@ integration('scenario 903 select pool through the durable turn daemon', () => {
|
||||
expect(concurrentReservation).toEqual(firstReservation);
|
||||
expect(firstReservation.candidates).toHaveLength(14);
|
||||
expect(await db.selectPoolEntry.count({ where: { ownerUserId: userId } })).toBe(14);
|
||||
const reservedNames = new Set(firstReservation.candidates.map((candidate) => candidate.uniqueName));
|
||||
expect(
|
||||
runtime!.world
|
||||
.listGeneralPoolCandidates(new Date(firstReservation.validUntil))
|
||||
?.some((candidate) => reservedNames.has(candidate.uniqueName))
|
||||
).toBe(false);
|
||||
await expect(
|
||||
db.inputEvent.findUniqueOrThrow({
|
||||
where: { requestId: `select-pool:${userId}:select-pool-reserve-a:reserve` },
|
||||
})
|
||||
).resolves.toMatchObject({
|
||||
eventType: 'selectPoolReserve',
|
||||
status: 'SUCCEEDED',
|
||||
actorUserId: userId,
|
||||
payload: {
|
||||
acceptedGameAt: expect.any(String),
|
||||
acceptedGameTick: expect.any(Number),
|
||||
},
|
||||
});
|
||||
|
||||
const attempts = await Promise.allSettled([
|
||||
appRouter.createCaller(buildContext('select-pool-create-a')).join.selectPoolGeneral({
|
||||
@@ -290,6 +309,10 @@ integration('scenario 903 select pool through the durable turn daemon', () => {
|
||||
expect(initialRankRows.every(({ nationId, value }) => nationId === 0 && value === 0)).toBe(true);
|
||||
expect(await db.selectPoolEntry.count({ where: { generalId: initial.id } })).toBe(1);
|
||||
expect(await db.selectPoolEntry.count({ where: { ownerUserId: userId } })).toBe(0);
|
||||
expect(runtime!.world.listGeneralPoolEntries()?.filter((entry) => entry.ownerUserId === userId)).toEqual([]);
|
||||
expect(
|
||||
runtime!.world.listGeneralPoolEntries()?.find((entry) => entry.generalId === initial.id)?.candidate.name
|
||||
).toBe(initial.name);
|
||||
expect(
|
||||
await db.logEntry.count({
|
||||
where: { meta: { path: ['ownerUserId'], equals: userId } },
|
||||
@@ -336,6 +359,16 @@ integration('scenario 903 select pool through the durable turn daemon', () => {
|
||||
.createCaller(buildContext('select-pool-reselect'))
|
||||
.join.reselectPoolGeneral({ uniqueName: target.uniqueName })
|
||||
).resolves.toEqual({ ok: true, generalId: initial.id });
|
||||
await expect(
|
||||
db.inputEvent.findUniqueOrThrow({ where: { requestId: 'select-pool-reselect:join.reselectPoolGeneral' } })
|
||||
).resolves.toMatchObject({
|
||||
eventType: 'selectPoolReselect',
|
||||
actorUserId: userId,
|
||||
payload: {
|
||||
acceptedGameAt: expect.any(String),
|
||||
acceptedGameTick: expect.any(Number),
|
||||
},
|
||||
});
|
||||
|
||||
const updated = await db.general.findUniqueOrThrow({ where: { id: initial.id } });
|
||||
expect(updated).toMatchObject({
|
||||
@@ -368,6 +401,10 @@ integration('scenario 903 select pool through the durable turn daemon', () => {
|
||||
ownerUserId: null,
|
||||
reservedUntil: null,
|
||||
});
|
||||
expect(runtime!.world.listGeneralPoolEntries()?.filter((entry) => entry.ownerUserId === userId)).toEqual([]);
|
||||
expect(
|
||||
runtime!.world.listGeneralPoolEntries()?.find((entry) => entry.generalId === initial.id)?.uniqueName
|
||||
).toBe(target.uniqueName);
|
||||
expect(
|
||||
await db.logEntry.count({
|
||||
where: { meta: { path: ['ownerUserId'], equals: userId } },
|
||||
@@ -518,6 +555,10 @@ integration('scenario 903 select pool through the durable turn daemon', () => {
|
||||
status: 'SUCCEEDED',
|
||||
attempts: 1,
|
||||
actorUserId: otherUserId,
|
||||
payload: {
|
||||
acceptedGameAt: expect.any(String),
|
||||
acceptedGameTick: expect.any(Number),
|
||||
},
|
||||
});
|
||||
}, 30_000);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user