fix(housekeeping): align poll deletion lock order

This commit is contained in:
Simo committed 2026-09-02 18:45:50 +02:00
1 parent b4193bea6c
commit 6e16b948e6
2 files changed
+33 -2

No files matched your search

@@ -19,6 +19,7 @@ const database = vi.hoisted(() => {
let selectedQueue: Record<string, unknown>[] = [];
let selectedTable: string | undefined;
let lockedTables: Array<readonly [string | undefined, string]> = [];
let mutationSteps: string[] = [];
const insertedValues = vi.fn(async (_values: Record<string, unknown>) => [
{ insertId: 8 },
]);
@@ -32,6 +33,7 @@ const database = vi.hoisted(() => {
const limit = vi.fn(async () => nextSelected());
const lock = vi.fn(async (strength: string) => {
lockedTables.push([selectedTable, strength]);
mutationSteps.push(`lock:${selectedTable ?? "unknown"}`);
return nextSelected();
});
const where = vi.fn(() => ({ for: lock, limit }));
@@ -42,7 +44,12 @@ const database = vi.hoisted(() => {
const select = vi.fn(() => ({ from }));
const execute = vi.fn(async () => undefined);
const deleteWhere = vi.fn(async () => undefined);
const remove = vi.fn((_table: unknown) => ({ where: deleteWhere }));
const remove = vi.fn((table: unknown) => {
mutationSteps.push(
`delete:${(table as { tableName?: string }).tableName ?? "unknown"}`,
);
return { where: deleteWhere };
});
return {
execute,
insert,
@@ -51,6 +58,9 @@ const database = vi.hoisted(() => {
lockedTables() {
return [...lockedTables];
},
mutationSteps() {
return [...mutationSteps];
},
set,
update,
select,
@@ -66,6 +76,7 @@ const database = vi.hoisted(() => {
selectedQueue = [];
selectedTable = undefined;
lockedTables = [];
mutationSteps = [];
},
queueSelected(...values: Record<string, unknown>[]) {
selectedQueue = [...values];
@@ -186,7 +197,17 @@ describe("Content database mutation runtime partial updates", () => {
"WebsitePollQuestion",
"WebsitePoll",
]);
expect(database.lockedTables()).toEqual([["WebsitePoll", "update"]]);
expect(database.lockedTables()).toEqual([
["WebsitePoll", "update"],
["WebsitePollQuestion", "update"],
]);
expect(database.mutationSteps()).toEqual([
"lock:WebsitePoll",
"lock:WebsitePollQuestion",
"delete:WebsitePollVote",
"delete:WebsitePollQuestion",
"delete:WebsitePoll",
]);
});
it("deletes question votes before the question and retains its audit snapshot", async () => {
@@ -219,6 +240,11 @@ describe("Content database mutation runtime partial updates", () => {
expect(database.lockedTables()).toEqual([
["WebsitePollQuestion", "update"],
]);
expect(database.mutationSteps()).toEqual([
"lock:WebsitePollQuestion",
"delete:WebsitePollVote",
"delete:WebsitePollQuestion",
]);
});
it("rejects moving a question to another poll during update", async () => {
@@ -635,6 +635,11 @@ async function pollChange(
.for("update");
if (!existing) throw notFound();
if (action === "delete") {
await connection
.select({ id: WebsitePollQuestion.id })
.from(WebsitePollQuestion)
.where(eq(WebsitePollQuestion.pollId, id))
.for("update");
await connection
.delete(WebsitePollVote)
.where(