fix: 改进候选随机性与并发配额稳定性

This commit is contained in:
root
2026-09-15 15:14:01 +08:00
parent 69fc8d51ce
commit 0c5cbd75d9
5 changed files with 384 additions and 69 deletions
+137
View File
@@ -0,0 +1,137 @@
import { readFile } from "node:fs/promises";
import { randomUUID } from "node:crypto";
import { PrismaClient } from "@prisma/client";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import {
assertSafeTestDatabaseUrl,
resolveTestDatabaseUrl,
} from "../../prisma/database-safety";
const databaseUrl = resolveTestDatabaseUrl();
const prisma = new PrismaClient({ datasources: { db: { url: databaseUrl } } });
async function executeStatements(
tx: Parameters<Parameters<typeof prisma.$transaction>[0]>[0],
sql: string,
) {
for (const statement of sql
.split(";")
.map((part) => part.trim())
.filter(Boolean))
await tx.$executeRawUnsafe(statement);
}
describe("0008 legacy lease upgrade", () => {
beforeAll(async () => {
assertSafeTestDatabaseUrl(databaseUrl);
await prisma.$connect();
});
afterAll(async () => prisma.$disconnect());
it("expires legacy ACTIVE leases, releases their bottles, and preserves terminal rows", async () => {
const schema = `migration_0008_${randomUUID().replaceAll("-", "")}`;
const authorId = randomUUID();
const pickerId = randomUUID();
const activeBottleId = randomUUID();
const returnedBottleId = randomUUID();
const activeLeaseId = randomUUID();
const returnedLeaseId = randomUUID();
const migration = await readFile(
new URL(
"../../prisma/migrations/0008_bottle_pick_leases/migration.sql",
import.meta.url,
),
"utf8",
);
try {
await prisma.$transaction(async (tx) => {
await tx.$executeRawUnsafe(`CREATE SCHEMA "${schema}"`);
await tx.$executeRawUnsafe(`SET LOCAL search_path TO "${schema}"`);
await executeStatements(
tx,
`
CREATE TYPE "BottlePoolStatus" AS ENUM ('IN_POOL', 'LEASED', 'CONSUMED', 'REMOVED', 'CLOSED');
CREATE TYPE "BottlePickLeaseStatus" AS ENUM ('ACTIVE', 'RETURNED', 'EXPIRED', 'CONSUMED');
CREATE TABLE "accounts" ("id" UUID PRIMARY KEY);
CREATE TABLE "bottles" (
"id" UUID PRIMARY KEY,
"pool_status" "BottlePoolStatus" NOT NULL,
"version" INTEGER NOT NULL
);
CREATE TABLE "bottle_pick_leases" (
"id" UUID PRIMARY KEY,
"bottle_id" UUID NOT NULL REFERENCES "bottles"("id"),
"picker_id" UUID NOT NULL REFERENCES "accounts"("id"),
"lease_token_hash" VARCHAR(255) NOT NULL UNIQUE,
"status" "BottlePickLeaseStatus" NOT NULL,
"ended_at" TIMESTAMPTZ(3),
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO "accounts" ("id") VALUES ('${authorId}'), ('${pickerId}');
INSERT INTO "bottles" ("id", "pool_status", "version") VALUES
('${activeBottleId}', 'LEASED', 4),
('${returnedBottleId}', 'CLOSED', 7);
INSERT INTO "bottle_pick_leases"
("id", "bottle_id", "picker_id", "lease_token_hash", "status", "ended_at") VALUES
('${activeLeaseId}', '${activeBottleId}', '${pickerId}', 'active-hash', 'ACTIVE', NULL),
('${returnedLeaseId}', '${returnedBottleId}', '${pickerId}', 'returned-hash', 'RETURNED', CURRENT_TIMESTAMP);
`,
);
await executeStatements(tx, migration);
const leases = await tx.$queryRawUnsafe<
Array<{
id: string;
status: string;
endedAt: Date | null;
ciphertextHex: string;
}>
>(`
SELECT "id", "status", "ended_at" AS "endedAt",
encode("lease_token_ciphertext", 'hex') AS "ciphertextHex"
FROM "bottle_pick_leases" ORDER BY "id"
`);
const bottles = await tx.$queryRawUnsafe<
Array<{ id: string; poolStatus: string; version: number }>
>(`
SELECT "id", "pool_status" AS "poolStatus", "version"
FROM "bottles" ORDER BY "id"
`);
const ciphertextColumn = await tx.$queryRawUnsafe<
Array<{ isNullable: string }>
>(`
SELECT is_nullable AS "isNullable" FROM information_schema.columns
WHERE table_schema = '${schema}' AND table_name = 'bottle_pick_leases'
AND column_name = 'lease_token_ciphertext'
`);
expect(leases.find(({ id }) => id === activeLeaseId)).toMatchObject({
status: "EXPIRED",
endedAt: expect.any(Date) as Date,
ciphertextHex: "00".repeat(48),
});
expect(leases.find(({ id }) => id === returnedLeaseId)).toMatchObject({
status: "RETURNED",
endedAt: expect.any(Date) as Date,
ciphertextHex: "00".repeat(48),
});
expect(bottles.find(({ id }) => id === activeBottleId)).toMatchObject({
poolStatus: "IN_POOL",
version: 5,
});
expect(bottles.find(({ id }) => id === returnedBottleId)).toMatchObject(
{
poolStatus: "CLOSED",
version: 7,
},
);
expect(ciphertextColumn).toEqual([{ isNullable: "NO" }]);
});
} finally {
await prisma.$executeRawUnsafe(
`DROP SCHEMA IF EXISTS "${schema}" CASCADE`,
);
}
});
});