@isomorph.ai/app-sdk 1.36.1 → 1.36.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.
- package/dist/runtime.js +30 -9
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -237,18 +237,31 @@ export class Runs {
|
|
|
237
237
|
const interrupted = expired.filter(run => !active.has(run.id));
|
|
238
238
|
for (const run of interrupted) {
|
|
239
239
|
const exhausted = run.attempt >= run.max_attempts;
|
|
240
|
-
|
|
240
|
+
const status = run.cancel_requested ? 'cancelled' : exhausted ? 'failed' : 'queued';
|
|
241
|
+
const { data } = await this.table().update({ status, error: status === 'failed' ? 'the worker was interrupted and no attempts remain' : run.error, lease_until: null, updated_at: now.toISOString() }).eq('id', run.id).eq('status', 'running').eq('cancel_requested', run.cancel_requested).select('id').maybeSingle();
|
|
242
|
+
// Cancellation may have arrived between reading the expired lease and
|
|
243
|
+
// writing its retry. It wins that race without leaving another attempt.
|
|
244
|
+
if (!data && !run.cancel_requested)
|
|
245
|
+
await this.table().update({ status: 'cancelled', lease_until: null, updated_at: now.toISOString() }).eq('id', run.id).eq('status', 'running').eq('cancel_requested', true);
|
|
241
246
|
}
|
|
242
247
|
return interrupted.length;
|
|
243
248
|
}
|
|
244
249
|
/** Claims the oldest queued run by a conditional update; null when the queue is empty or another worker won. */
|
|
245
250
|
async claim(now) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
while (true) {
|
|
252
|
+
const { data: queued } = await this.table().select('id, attempt, cancel_requested').eq('status', 'queued').order('created_at').limit(1);
|
|
253
|
+
const next = queued[0];
|
|
254
|
+
if (!next)
|
|
255
|
+
return null;
|
|
256
|
+
if (next.cancel_requested) {
|
|
257
|
+
const { data } = await this.table().update({ status: 'cancelled', lease_until: null, updated_at: now.toISOString() }).eq('id', next.id).eq('status', 'queued').eq('cancel_requested', true).select('id').maybeSingle();
|
|
258
|
+
if (!data)
|
|
259
|
+
return null;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
const { data } = await this.table().update({ status: 'running', attempt: next.attempt + 1, lease_until: new Date(now.getTime() + LEASE_MS).toISOString(), updated_at: now.toISOString() }).eq('id', next.id).eq('status', 'queued').eq('cancel_requested', false).select('*').maybeSingle();
|
|
263
|
+
return data;
|
|
264
|
+
}
|
|
252
265
|
}
|
|
253
266
|
async progress(id, percent, note) {
|
|
254
267
|
await this.table().update({ progress: Math.max(0, Math.min(100, Math.round(percent))), ...(note === undefined ? {} : { note }), lease_until: new Date(Date.now() + LEASE_MS).toISOString(), updated_at: new Date().toISOString() }).eq('id', id);
|
|
@@ -261,8 +274,16 @@ export class Runs {
|
|
|
261
274
|
async finish(run, outcome) {
|
|
262
275
|
const retry = outcome.error !== undefined && !outcome.cancelled && run.attempt < run.max_attempts;
|
|
263
276
|
const status = outcome.cancelled ? 'cancelled' : outcome.error === undefined ? 'succeeded' : retry ? 'queued' : 'failed';
|
|
264
|
-
|
|
265
|
-
|
|
277
|
+
const now = new Date().toISOString();
|
|
278
|
+
if (!outcome.cancelled) {
|
|
279
|
+
const { data } = await this.table().update({ status, result: outcome.result ?? null, error: outcome.error ?? null, progress: status === 'succeeded' ? 100 : run.progress, lease_until: null, updated_at: now }).eq('id', run.id).eq('status', 'running').eq('cancel_requested', false).select('id').maybeSingle();
|
|
280
|
+
if (data)
|
|
281
|
+
return status;
|
|
282
|
+
}
|
|
283
|
+
// The handler may throw after the user cancels. A cancelled run is
|
|
284
|
+
// terminal even when that failure would otherwise be retried.
|
|
285
|
+
await this.table().update({ status: 'cancelled', result: null, error: null, lease_until: null, updated_at: now }).eq('id', run.id).eq('status', 'running').eq('cancel_requested', true);
|
|
286
|
+
return 'cancelled';
|
|
266
287
|
}
|
|
267
288
|
}
|
|
268
289
|
export class Runtime {
|