@tenetkit/pg 0.38.0 → 0.38.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -17,5 +17,5 @@ export declare const postgresOperations: (input: {
|
|
|
17
17
|
readonly requireRun: (runId: string) => Effect.Effect<DecodedRun, RunNotFound | RuntimeUnavailable | SqlError, SqlR>;
|
|
18
18
|
readonly requireClaim: (claim: import("tenetkit/runtime/driver/run-store").ExecutionClaim) => Effect.Effect<void, import("tenetkit/runtime/driver/sql/errors").StaleClaim | RunNotFound | RuntimeUnavailable | SqlError, SqlR>;
|
|
19
19
|
readonly nextId: (prefix: string) => Effect.Effect<string>;
|
|
20
|
-
}) => Pick<RunStoreInterface, "recordOperation" | "startOperation" | "completeOperation" | "commitModelResponse" | "commitInterruptedModelResponse" | "expireRunningOperation" | "getOperation" | "getOperationByKey" | "resolveOperation">;
|
|
20
|
+
}) => Pick<RunStoreInterface, "recordOperation" | "startOperation" | "completeOperation" | "commitModelResponse" | "commitInterruptedModelResponse" | "expireRunningOperation" | "recoverRunningOperations" | "getOperation" | "getOperationByKey" | "resolveOperation">;
|
|
21
21
|
export {};
|
|
@@ -18,6 +18,38 @@ import { lockRunHierarchy } from "./locks.js";
|
|
|
18
18
|
export const postgresOperations = (input) => {
|
|
19
19
|
const { sql, hub, run, runNoTxn, requireRun, requireClaim, nextId } = input;
|
|
20
20
|
const fenced = (claim, effect) => run(sql `SELECT run_id FROM tenetkit_runs WHERE run_id = ${claim.runId} FOR UPDATE`.pipe(Effect.andThen(requireClaim(claim)), Effect.andThen(effect)));
|
|
21
|
+
const expire = (op) => Effect.gen(function* () {
|
|
22
|
+
const loaded = yield* requireRun(op.runId);
|
|
23
|
+
const rows = yield* sql `
|
|
24
|
+
SELECT * FROM tenetkit_run_operations WHERE run_id = ${op.runId} AND operation_id = ${op.operationId}
|
|
25
|
+
`;
|
|
26
|
+
const row = rows[0];
|
|
27
|
+
if (row === undefined)
|
|
28
|
+
return yield* RuntimeUnavailable.make({ message: "operation missing" });
|
|
29
|
+
if (row.status !== "running") {
|
|
30
|
+
return { record: toOperationRecord(row), outcome: row.status };
|
|
31
|
+
}
|
|
32
|
+
if (canBlindRetry(row.replay_policy)) {
|
|
33
|
+
yield* sql `
|
|
34
|
+
UPDATE tenetkit_run_operations
|
|
35
|
+
SET status = 'requested', started_at = NULL, finished_at = NULL, owner_worker_id = NULL, lease_expires_at = NULL
|
|
36
|
+
WHERE run_id = ${op.runId} AND operation_id = ${op.operationId} AND status = 'running'
|
|
37
|
+
`;
|
|
38
|
+
const next = yield* sql `
|
|
39
|
+
SELECT * FROM tenetkit_run_operations WHERE run_id = ${op.runId} AND operation_id = ${op.operationId}
|
|
40
|
+
`;
|
|
41
|
+
return { record: toOperationRecord(next[0]), outcome: "retried" };
|
|
42
|
+
}
|
|
43
|
+
yield* sql `
|
|
44
|
+
UPDATE tenetkit_run_operations SET status = 'unknown', finished_at = NOW()
|
|
45
|
+
WHERE run_id = ${op.runId} AND operation_id = ${op.operationId} AND status = 'running'
|
|
46
|
+
`;
|
|
47
|
+
yield* appendEvent(hub, loaded, { _tag: "OperationUnknown", operationId: op.operationId }, loaded.cancellationRequested ? "cancelling" : "needs-resolution");
|
|
48
|
+
const next = yield* sql `
|
|
49
|
+
SELECT * FROM tenetkit_run_operations WHERE run_id = ${op.runId} AND operation_id = ${op.operationId}
|
|
50
|
+
`;
|
|
51
|
+
return { record: toOperationRecord(next[0]), outcome: "unknown" };
|
|
52
|
+
});
|
|
21
53
|
return {
|
|
22
54
|
recordOperation: (op) => fenced(op, Effect.gen(function* () {
|
|
23
55
|
const loaded = yield* requireRun(op.runId);
|
|
@@ -212,37 +244,18 @@ export const postgresOperations = (input) => {
|
|
|
212
244
|
return toOperationRecord(rows[0]);
|
|
213
245
|
})),
|
|
214
246
|
...postgresModelResponseOperations(input),
|
|
215
|
-
expireRunningOperation: (op) => fenced(op,
|
|
216
|
-
|
|
217
|
-
const
|
|
218
|
-
SELECT
|
|
247
|
+
expireRunningOperation: (op) => fenced(op, expire(op)),
|
|
248
|
+
recoverRunningOperations: (claim) => fenced(claim, Effect.gen(function* () {
|
|
249
|
+
const operations = yield* sql `
|
|
250
|
+
SELECT operation_id FROM tenetkit_run_operations
|
|
251
|
+
WHERE run_id = ${claim.runId} AND status = 'running'
|
|
252
|
+
ORDER BY operation_id
|
|
219
253
|
`;
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
return yield* RuntimeUnavailable.make({ message: "operation missing" });
|
|
223
|
-
if (row.status !== "running") {
|
|
224
|
-
return { record: toOperationRecord(row), outcome: row.status };
|
|
254
|
+
for (const operation of operations) {
|
|
255
|
+
yield* expire({ runId: claim.runId, operationId: operation.operation_id });
|
|
225
256
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
UPDATE tenetkit_run_operations
|
|
229
|
-
SET status = 'requested', started_at = NULL, finished_at = NULL, owner_worker_id = NULL, lease_expires_at = NULL
|
|
230
|
-
WHERE run_id = ${op.runId} AND operation_id = ${op.operationId} AND status = 'running'
|
|
231
|
-
`;
|
|
232
|
-
const next = yield* sql `
|
|
233
|
-
SELECT * FROM tenetkit_run_operations WHERE run_id = ${op.runId} AND operation_id = ${op.operationId}
|
|
234
|
-
`;
|
|
235
|
-
return { record: toOperationRecord(next[0]), outcome: "retried" };
|
|
236
|
-
}
|
|
237
|
-
yield* sql `
|
|
238
|
-
UPDATE tenetkit_run_operations SET status = 'unknown', finished_at = NOW()
|
|
239
|
-
WHERE run_id = ${op.runId} AND operation_id = ${op.operationId} AND status = 'running'
|
|
240
|
-
`;
|
|
241
|
-
yield* appendEvent(hub, loaded, { _tag: "OperationUnknown", operationId: op.operationId }, loaded.cancellationRequested ? "cancelling" : "needs-resolution");
|
|
242
|
-
const next = yield* sql `
|
|
243
|
-
SELECT * FROM tenetkit_run_operations WHERE run_id = ${op.runId} AND operation_id = ${op.operationId}
|
|
244
|
-
`;
|
|
245
|
-
return { record: toOperationRecord(next[0]), outcome: "unknown" };
|
|
257
|
+
const loaded = yield* requireRun(claim.runId);
|
|
258
|
+
return loaded.status === "needs-resolution" ? "blocked" : "ready";
|
|
246
259
|
})),
|
|
247
260
|
getOperation: (op) => runNoTxn(Effect.gen(function* () {
|
|
248
261
|
yield* requireRun(op.runId);
|
|
@@ -318,8 +331,15 @@ export const postgresOperations = (input) => {
|
|
|
318
331
|
WHERE run_id = ${op.runId} AND operation_id = ${op.operationId} AND status = 'unknown'
|
|
319
332
|
`;
|
|
320
333
|
}
|
|
334
|
+
const unresolved = yield* sql `
|
|
335
|
+
SELECT COUNT(*)::int AS unresolved FROM tenetkit_run_operations
|
|
336
|
+
WHERE run_id = ${op.runId} AND status = 'unknown'
|
|
337
|
+
`;
|
|
338
|
+
const runStatus = Number(unresolved[0]?.unresolved ?? 0) > 0
|
|
339
|
+
? sql `'needs-resolution'`
|
|
340
|
+
: sql `CASE WHEN cancellation_requested THEN 'cancelling' ELSE 'queued' END`;
|
|
321
341
|
yield* sql `
|
|
322
|
-
UPDATE tenetkit_runs SET status =
|
|
342
|
+
UPDATE tenetkit_runs SET status = ${runStatus}, owner_worker_id = NULL, lease_expires_at = NULL, updated_at = NOW()
|
|
323
343
|
WHERE run_id = ${op.runId} AND status = 'needs-resolution'
|
|
324
344
|
`;
|
|
325
345
|
yield* settleAdmittedCancellation(hub, op.runId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@effect/sql-pg": "4.0.0-rc.111",
|
|
42
|
-
"tenetkit": "0.38.
|
|
42
|
+
"tenetkit": "0.38.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@effect/vitest": "4.0.0-rc.111",
|