fix(housekeeping): lock poll mutation snapshots
This commit is contained in:
1 parent
3e52965292
commit
b4193bea6c
2 files changed
+26
-4
No files matched your search
+24
-2
@@ -17,6 +17,8 @@ const sqlMocks = vi.hoisted(() => ({
|
|||||||
const database = vi.hoisted(() => {
|
const database = vi.hoisted(() => {
|
||||||
let selected: Record<string, unknown> = { id: 7, title: "Existing" };
|
let selected: Record<string, unknown> = { id: 7, title: "Existing" };
|
||||||
let selectedQueue: Record<string, unknown>[] = [];
|
let selectedQueue: Record<string, unknown>[] = [];
|
||||||
|
let selectedTable: string | undefined;
|
||||||
|
let lockedTables: Array<readonly [string | undefined, string]> = [];
|
||||||
const insertedValues = vi.fn(async (_values: Record<string, unknown>) => [
|
const insertedValues = vi.fn(async (_values: Record<string, unknown>) => [
|
||||||
{ insertId: 8 },
|
{ insertId: 8 },
|
||||||
]);
|
]);
|
||||||
@@ -28,9 +30,15 @@ const database = vi.hoisted(() => {
|
|||||||
const update = vi.fn(() => ({ set }));
|
const update = vi.fn(() => ({ set }));
|
||||||
const nextSelected = () => [selectedQueue.shift() ?? selected];
|
const nextSelected = () => [selectedQueue.shift() ?? selected];
|
||||||
const limit = vi.fn(async () => nextSelected());
|
const limit = vi.fn(async () => nextSelected());
|
||||||
const lock = vi.fn(async () => nextSelected());
|
const lock = vi.fn(async (strength: string) => {
|
||||||
|
lockedTables.push([selectedTable, strength]);
|
||||||
|
return nextSelected();
|
||||||
|
});
|
||||||
const where = vi.fn(() => ({ for: lock, limit }));
|
const where = vi.fn(() => ({ for: lock, limit }));
|
||||||
const from = vi.fn(() => ({ where }));
|
const from = vi.fn((table: unknown) => {
|
||||||
|
selectedTable = (table as { tableName?: string }).tableName;
|
||||||
|
return { where };
|
||||||
|
});
|
||||||
const select = vi.fn(() => ({ from }));
|
const select = vi.fn(() => ({ from }));
|
||||||
const execute = vi.fn(async () => undefined);
|
const execute = vi.fn(async () => undefined);
|
||||||
const deleteWhere = vi.fn(async () => undefined);
|
const deleteWhere = vi.fn(async () => undefined);
|
||||||
@@ -40,6 +48,9 @@ const database = vi.hoisted(() => {
|
|||||||
insert,
|
insert,
|
||||||
insertedValues,
|
insertedValues,
|
||||||
lock,
|
lock,
|
||||||
|
lockedTables() {
|
||||||
|
return [...lockedTables];
|
||||||
|
},
|
||||||
set,
|
set,
|
||||||
update,
|
update,
|
||||||
select,
|
select,
|
||||||
@@ -53,6 +64,8 @@ const database = vi.hoisted(() => {
|
|||||||
selected(value: Record<string, unknown>) {
|
selected(value: Record<string, unknown>) {
|
||||||
selected = value;
|
selected = value;
|
||||||
selectedQueue = [];
|
selectedQueue = [];
|
||||||
|
selectedTable = undefined;
|
||||||
|
lockedTables = [];
|
||||||
},
|
},
|
||||||
queueSelected(...values: Record<string, unknown>[]) {
|
queueSelected(...values: Record<string, unknown>[]) {
|
||||||
selectedQueue = [...values];
|
selectedQueue = [...values];
|
||||||
@@ -173,6 +186,7 @@ describe("Content database mutation runtime partial updates", () => {
|
|||||||
"WebsitePollQuestion",
|
"WebsitePollQuestion",
|
||||||
"WebsitePoll",
|
"WebsitePoll",
|
||||||
]);
|
]);
|
||||||
|
expect(database.lockedTables()).toEqual([["WebsitePoll", "update"]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("deletes question votes before the question and retains its audit snapshot", async () => {
|
it("deletes question votes before the question and retains its audit snapshot", async () => {
|
||||||
@@ -202,6 +216,9 @@ describe("Content database mutation runtime partial updates", () => {
|
|||||||
question: "Favourite colour?",
|
question: "Favourite colour?",
|
||||||
});
|
});
|
||||||
expect(snapshot?.after).toBeNull();
|
expect(snapshot?.after).toBeNull();
|
||||||
|
expect(database.lockedTables()).toEqual([
|
||||||
|
["WebsitePollQuestion", "update"],
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("rejects moving a question to another poll during update", async () => {
|
it("rejects moving a question to another poll during update", async () => {
|
||||||
@@ -246,6 +263,7 @@ describe("Content database mutation runtime partial updates", () => {
|
|||||||
expect.objectContaining({ options: "" }),
|
expect.objectContaining({ options: "" }),
|
||||||
);
|
);
|
||||||
expect(database.lock).toHaveBeenCalledWith("update");
|
expect(database.lock).toHaveBeenCalledWith("update");
|
||||||
|
expect(database.lockedTables()).toEqual([["WebsitePoll", "update"]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("maps duplicate question options to an options field error", async () => {
|
it("maps duplicate question options to an options field error", async () => {
|
||||||
@@ -332,6 +350,7 @@ describe("Content database mutation runtime partial updates", () => {
|
|||||||
]) {
|
]) {
|
||||||
expect(values).not.toHaveProperty(omitted);
|
expect(values).not.toHaveProperty(omitted);
|
||||||
}
|
}
|
||||||
|
expect(database.lockedTables()).toEqual([["WebsitePoll", "update"]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("rejects question 101 without inserting it", async () => {
|
it("rejects question 101 without inserting it", async () => {
|
||||||
@@ -418,6 +437,9 @@ describe("Content database mutation runtime partial updates", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(database.set).toHaveBeenCalledWith({ options: "Green\nYellow" });
|
expect(database.set).toHaveBeenCalledWith({ options: "Green\nYellow" });
|
||||||
|
expect(database.lockedTables()).toEqual([
|
||||||
|
["WebsitePollQuestion", "update"],
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("blocks deletion of an event type referenced by an event", async () => {
|
it("blocks deletion of an event type referenced by an event", async () => {
|
||||||
|
|||||||
@@ -632,7 +632,7 @@ async function pollChange(
|
|||||||
})
|
})
|
||||||
.from(WebsitePoll)
|
.from(WebsitePoll)
|
||||||
.where(eq(WebsitePoll.id, id))
|
.where(eq(WebsitePoll.id, id))
|
||||||
.limit(1);
|
.for("update");
|
||||||
if (!existing) throw notFound();
|
if (!existing) throw notFound();
|
||||||
if (action === "delete") {
|
if (action === "delete") {
|
||||||
await connection
|
await connection
|
||||||
@@ -735,7 +735,7 @@ async function pollQuestionChange(
|
|||||||
})
|
})
|
||||||
.from(WebsitePollQuestion)
|
.from(WebsitePollQuestion)
|
||||||
.where(eq(WebsitePollQuestion.id, id))
|
.where(eq(WebsitePollQuestion.id, id))
|
||||||
.limit(1);
|
.for("update");
|
||||||
if (!existing) throw notFound();
|
if (!existing) throw notFound();
|
||||||
if (action === "delete") {
|
if (action === "delete") {
|
||||||
await connection
|
await connection
|
||||||
|
|||||||
Reference in new issue
Block a user