81 lines
2.8 KiB
TypeScript
81 lines
2.8 KiB
TypeScript
import { content } from "@deadhead/content";
|
|
import { boardPeriodIndex, boardPeriodMs } from "@deadhead/sim";
|
|
import { describe, expect, it } from "vitest";
|
|
import { acceptedContracts, contractBoards } from "../src/db/schema";
|
|
import { BOARD_RETENTION_PERIODS, cleanupExpiredContracts } from "../src/jobs/cleanup";
|
|
import { appJobs, CLEANUP_CONTRACTS_JOB } from "../src/jobs/definitions";
|
|
import { makeOwner, TEST_NOW, useTestDatabase } from "./db";
|
|
import { insertDispatch, putBoard, signUp, testContract, useTestApp } from "./game";
|
|
|
|
const database = useTestDatabase();
|
|
const testApp = useTestApp(database);
|
|
|
|
describe("expired contract cleanup", () => {
|
|
it("deletes old boards and accepted contracts and keeps current ones", async () => {
|
|
const { db } = database();
|
|
const guest = await signUp(testApp().app);
|
|
const shipId = await makeOwner(db, guest.playerId, guest.avatarId);
|
|
const period = boardPeriodMs(content.config);
|
|
const current = boardPeriodIndex(TEST_NOW, content.config);
|
|
const old = current - BOARD_RETENTION_PERIODS - 1;
|
|
|
|
// A board from long ago and one from the current period.
|
|
await putBoard(db, guest.playerId, [testContract()], TEST_NOW - (current - old) * period);
|
|
await putBoard(db, guest.playerId, [testContract()], TEST_NOW);
|
|
|
|
// An accepted contract from each period, both pointing at real dispatches.
|
|
const record = await insertDispatch(db, {
|
|
playerId: guest.playerId,
|
|
shipId,
|
|
pilotId: guest.avatarId,
|
|
departAt: TEST_NOW,
|
|
});
|
|
await db.insert(acceptedContracts).values([
|
|
{
|
|
playerId: guest.playerId,
|
|
contractId: "old",
|
|
periodIndex: old,
|
|
dispatchId: record.id,
|
|
acceptedAt: TEST_NOW,
|
|
},
|
|
{
|
|
playerId: guest.playerId,
|
|
contractId: "new",
|
|
periodIndex: current,
|
|
dispatchId: record.id,
|
|
acceptedAt: TEST_NOW,
|
|
},
|
|
]);
|
|
|
|
expect(await cleanupExpiredContracts(db, TEST_NOW)).toEqual({
|
|
boards: 1,
|
|
acceptedContracts: 1,
|
|
});
|
|
expect((await db.select().from(contractBoards)).map((b) => b.periodIndex)).toEqual([current]);
|
|
expect((await db.select().from(acceptedContracts)).map((a) => a.contractId)).toEqual(["new"]);
|
|
});
|
|
|
|
it("keeps boards inside the retention window", async () => {
|
|
const { db } = database();
|
|
const guest = await signUp(testApp().app);
|
|
const period = boardPeriodMs(content.config);
|
|
await putBoard(
|
|
db,
|
|
guest.playerId,
|
|
[testContract()],
|
|
TEST_NOW - BOARD_RETENTION_PERIODS * period,
|
|
);
|
|
expect(await cleanupExpiredContracts(db, TEST_NOW)).toEqual({
|
|
boards: 0,
|
|
acceptedContracts: 0,
|
|
});
|
|
});
|
|
|
|
it("runs as an hourly job", () => {
|
|
const job = appJobs({ db: database().db, clock: () => TEST_NOW }).find(
|
|
(j) => j.name === CLEANUP_CONTRACTS_JOB,
|
|
);
|
|
expect(job?.cron).toBe("0 * * * *");
|
|
});
|
|
});
|