fix(housekeeping): serialize set-rank intents
This commit is contained in:
1 parent
48096833ec
commit
2c5db2168b
2 files changed
+21
-2
No files matched your search
@@ -922,7 +922,7 @@ async function executeRconMutation(
|
||||
.select({ rank: User.rank })
|
||||
.from(User)
|
||||
.where(eq(User.id, userId))
|
||||
.limit(1);
|
||||
.for("update");
|
||||
if (!target) {
|
||||
throw new SystemMutationFailure(
|
||||
"NOT_FOUND",
|
||||
|
||||
+20
-1
@@ -12,6 +12,7 @@ const doubles = vi.hoisted(() => ({
|
||||
createEmulatorRankInTransaction: vi.fn(),
|
||||
dbDelete: vi.fn(),
|
||||
dbExecute: vi.fn(),
|
||||
dbForUpdate: vi.fn(),
|
||||
dbInsert: vi.fn(),
|
||||
dbSelect: vi.fn(),
|
||||
dbTransaction: vi.fn(),
|
||||
@@ -117,10 +118,11 @@ function updateChain(result: Promise<unknown> = Promise.resolve(undefined)) {
|
||||
}
|
||||
|
||||
function limitedSelection(rows: readonly unknown[]) {
|
||||
doubles.dbForUpdate.mockResolvedValueOnce(rows);
|
||||
return {
|
||||
from: () => ({
|
||||
where: () => ({
|
||||
for: () => Promise.resolve(rows),
|
||||
for: doubles.dbForUpdate,
|
||||
limit: () => Promise.resolve(rows),
|
||||
}),
|
||||
}),
|
||||
@@ -310,6 +312,23 @@ describe("durable rank synchronization", () => {
|
||||
expect(doubles.rconSetRank).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("locks the user row before committing a set-rank intent", async () => {
|
||||
doubles.dbSelect.mockImplementationOnce(() =>
|
||||
limitedSelection([{ rank: 3 }]),
|
||||
);
|
||||
doubles.dbExecute.mockResolvedValue([[{ id: 4 }]]);
|
||||
doubles.rconSetRank.mockResolvedValue(true);
|
||||
|
||||
const result = await systemMutationService.execute(
|
||||
serviceContext(PERMS.RCON_EXECUTE),
|
||||
"rcon.set-rank",
|
||||
{ userId: 8, rank: 4 },
|
||||
);
|
||||
|
||||
expect(result).toMatchObject({ ok: true });
|
||||
expect(doubles.dbForUpdate).toHaveBeenCalledWith("update");
|
||||
});
|
||||
|
||||
it("returns the durable recovery key when set-rank RCON fails after commit", async () => {
|
||||
doubles.dbSelect.mockImplementationOnce(() =>
|
||||
limitedSelection([{ rank: 3 }]),
|
||||
|
||||
Reference in new issue
Block a user