refactor: align provider and task contracts
This commit is contained in:
@@ -107,7 +107,7 @@ test("postgres reload retries when a write starts during the database read", asy
|
||||
test("store transaction rolls back in-memory mutations and defers events until commit", async () => {
|
||||
const store = createStore();
|
||||
const taskId = "transaction-task";
|
||||
store.tasks.set(taskId, { id: taskId, ownerId: "transaction-user", taskType: "image", modelProductId: "basic-image-v1", status: "queued", estimatedCost: 1, reservedCost: 0, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), eventSequence: 0, channelGroupId: "image-default", routeSnapshotVersion: 1, attempts: [], outputs: [] });
|
||||
store.tasks.set(taskId, { id: taskId, ownerId: "transaction-user", taskType: "image", modelProductId: "basic-image-v1", status: "queued", estimatedCost: 1, reservedCost: 0, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), eventSequence: 0, routeSnapshot: { groupId: "image-default", groupVersion: 1, publicModelId: "basic-image-v1", routeVersion: 1, orderedCandidates: [], strategy: "strict", totalRetryBudget: 0 }, modelSnapshot: { publicModelId: "basic-image-v1", modelVersion: 1, name: "基础模型", tier: "basic", capabilities: ["image"] }, pricingSnapshot: { ruleId: "price-basic-image", ruleVersion: 1, publicModelId: "basic-image-v1", unitPrice: 1, quantity: 1, billingUnit: "output", multiplier: 1, balanceUnitVersion: 1 }, planSnapshot: { queuePriority: 0, maxConcurrent: 1 }, attempts: [], outputs: [] });
|
||||
let observed = 0;
|
||||
store.taskSubscribers.set(taskId, new Set([() => { observed += 1; }]));
|
||||
await assert.rejects(store.transact(() => { const task = store.tasks.get(taskId)!; task.status = "running"; appendEvent(store, taskId, { taskId, type: "task.running", payload: {} }); throw new Error("rollback"); }), /rollback/);
|
||||
@@ -145,7 +145,7 @@ test("staging objects stay below the private root and expired files are collecte
|
||||
test("expired worker lease moves a running task to unknown without releasing reserve", () => {
|
||||
const store = createStore();
|
||||
const now = new Date(Date.now() - 10_000).toISOString();
|
||||
store.tasks.set("lease-task", { id: "lease-task", ownerId: "lease-user", taskType: "image", modelProductId: "basic-image", status: "running", estimatedCost: 10, reservedCost: 10, createdAt: now, updatedAt: now, eventSequence: 0, channelGroupId: "image-default", routeSnapshotVersion: 1, leaseExpiresAt: now, attempts: [{ id: "attempt-1", channelId: "channel-a", sequence: 1, status: "started", startedAt: now, leaseExpiresAt: now }], outputs: [] });
|
||||
store.tasks.set("lease-task", { id: "lease-task", ownerId: "lease-user", taskType: "image", modelProductId: "basic-image", status: "running", estimatedCost: 10, reservedCost: 10, createdAt: now, updatedAt: now, eventSequence: 0, routeSnapshot: { groupId: "image-default", groupVersion: 1, publicModelId: "basic-image-v1", routeVersion: 1, orderedCandidates: [], strategy: "strict", totalRetryBudget: 0 }, modelSnapshot: { publicModelId: "basic-image-v1", modelVersion: 1, name: "基础模型", tier: "basic", capabilities: ["image"] }, pricingSnapshot: { ruleId: "price-basic-image", ruleVersion: 1, publicModelId: "basic-image-v1", unitPrice: 1, quantity: 1, billingUnit: "output", multiplier: 1, balanceUnitVersion: 1 }, planSnapshot: { queuePriority: 0, maxConcurrent: 1 }, leaseExpiresAt: now, attempts: [{ id: "attempt-1", channelId: "channel-a", sequence: 1, status: "started", startedAt: now, leaseExpiresAt: now }], outputs: [] });
|
||||
store.balances.set("lease-user", { available: 0, reserved: 10 });
|
||||
assert.equal(recoverExpiredTaskLeases(store), 1);
|
||||
const task = store.tasks.get("lease-task")!;
|
||||
@@ -293,7 +293,7 @@ test("expired unknown tasks without a provider request id remain held for reconc
|
||||
store.buckets.set(userId, [{ id: "bucket", userId, source: "recharge", remaining: 10, priority: 0 }]);
|
||||
assert.equal(reserveBalance(store, userId, 10, "unknown-expiry-task"), true);
|
||||
const expired = new Date(Date.now() - 1_000).toISOString();
|
||||
store.tasks.set("unknown-expiry-task", { id: "unknown-expiry-task", ownerId: userId, taskType: "image", modelProductId: "basic-image", status: "unknown", estimatedCost: 10, reservedCost: 10, reserveExpiresAt: expired, createdAt: expired, updatedAt: expired, eventSequence: 0, channelGroupId: "image-default", routeSnapshotVersion: 1, attempts: [{ id: "unknown-attempt", channelId: "channel-a", sequence: 1, status: "unknown", startedAt: expired, finishedAt: expired, reconciliationStatus: "pending" }], outputs: [] });
|
||||
store.tasks.set("unknown-expiry-task", { id: "unknown-expiry-task", ownerId: userId, taskType: "image", modelProductId: "basic-image", status: "unknown", estimatedCost: 10, reservedCost: 10, reserveExpiresAt: expired, createdAt: expired, updatedAt: expired, eventSequence: 0, routeSnapshot: { groupId: "image-default", groupVersion: 1, publicModelId: "basic-image-v1", routeVersion: 1, orderedCandidates: [], strategy: "strict", totalRetryBudget: 0 }, modelSnapshot: { publicModelId: "basic-image-v1", modelVersion: 1, name: "基础模型", tier: "basic", capabilities: ["image"] }, pricingSnapshot: { ruleId: "price-basic-image", ruleVersion: 1, publicModelId: "basic-image-v1", unitPrice: 1, quantity: 1, billingUnit: "output", multiplier: 1, balanceUnitVersion: 1 }, planSnapshot: { queuePriority: 0, maxConcurrent: 1 }, attempts: [{ id: "unknown-attempt", channelId: "channel-a", sequence: 1, status: "unknown", startedAt: expired, finishedAt: expired, reconciliationStatus: "pending" }], outputs: [] });
|
||||
assert.equal(recoverExpiredReservations(store), 0);
|
||||
assert.equal(store.tasks.get("unknown-expiry-task")?.status, "unknown");
|
||||
assert.equal(store.tasks.get("unknown-expiry-task")?.reservedCost, 10);
|
||||
@@ -307,7 +307,7 @@ test("file snapshots use a version marker and reject corrupt state", async () =>
|
||||
const store = createStore(file);
|
||||
store.persist();
|
||||
const persisted = JSON.parse(await readFile(file, "utf8")) as { snapshotVersion?: number };
|
||||
assert.equal(persisted.snapshotVersion, 1);
|
||||
assert.equal(persisted.snapshotVersion, 2);
|
||||
await writeFile(file, "{not-json", "utf8");
|
||||
assert.throws(() => createStore(file), /persistence snapshot rejected/);
|
||||
} finally { await rm(root, { recursive: true, force: true }); }
|
||||
|
||||
Reference in New Issue
Block a user