@aikirun/task 0.8.0 → 0.9.0

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.
Files changed (2) hide show
  1. package/dist/index.js +32 -33
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -182,19 +182,7 @@ var TaskImpl = class _TaskImpl {
182
182
  const handle = run[INTERNAL].handle;
183
183
  handle[INTERNAL].assertExecutionAllowed();
184
184
  const inputRaw = isNonEmptyArray(args) ? args[0] : void 0;
185
- let input = inputRaw;
186
- if (this.params.schema?.input) {
187
- try {
188
- input = this.params.schema.input.parse(inputRaw);
189
- } catch (error) {
190
- await handle[INTERNAL].transitionState({
191
- status: "failed",
192
- cause: "self",
193
- error: createSerializableError(error)
194
- });
195
- throw new WorkflowRunFailedError(run.id, handle.run.attempts);
196
- }
197
- }
185
+ const input = await this.parse(handle, this.params.schema?.input, inputRaw);
198
186
  const inputHash = await hashInput(input);
199
187
  const reference = this.params.opts?.reference;
200
188
  const path = getTaskPath(this.name, reference?.id ?? inputHash);
@@ -203,7 +191,7 @@ var TaskImpl = class _TaskImpl {
203
191
  await this.assertUniqueTaskReferenceId(handle, existingTaskInfo, inputHash, reference, run.logger);
204
192
  }
205
193
  if (existingTaskInfo?.state.status === "completed") {
206
- return existingTaskInfo.state.output;
194
+ return this.parse(handle, this.params.schema?.output, existingTaskInfo.state.output);
207
195
  }
208
196
  if (existingTaskInfo?.state.status === "failed") {
209
197
  const { state } = existingTaskInfo;
@@ -245,7 +233,15 @@ var TaskImpl = class _TaskImpl {
245
233
  "aiki.taskId": taskId
246
234
  });
247
235
  logger.info("Task started", { "aiki.attempts": attempts });
248
- const { output, lastAttempt } = await this.tryExecuteTask(run, input, taskId, retryStrategy, attempts, logger);
236
+ const { output, lastAttempt } = await this.tryExecuteTask(
237
+ handle,
238
+ input,
239
+ taskId,
240
+ retryStrategy,
241
+ attempts,
242
+ run[INTERNAL].options.spinThresholdMs,
243
+ logger
244
+ );
249
245
  await handle[INTERNAL].transitionTaskState({
250
246
  taskId,
251
247
  taskState: { status: "completed", attempts: lastAttempt, output }
@@ -253,24 +249,12 @@ var TaskImpl = class _TaskImpl {
253
249
  logger.info("Task complete", { "aiki.attempts": lastAttempt });
254
250
  return output;
255
251
  }
256
- async tryExecuteTask(run, input, taskId, retryStrategy, currentAttempt, logger) {
252
+ async tryExecuteTask(handle, input, taskId, retryStrategy, currentAttempt, spinThresholdMs, logger) {
257
253
  let attempts = currentAttempt;
258
254
  while (true) {
259
255
  try {
260
256
  const outputRaw = await this.params.handler(input);
261
- let output = outputRaw;
262
- if (this.params.schema?.output) {
263
- try {
264
- output = this.params.schema.output.parse(outputRaw);
265
- } catch (error) {
266
- await run[INTERNAL].handle[INTERNAL].transitionState({
267
- status: "failed",
268
- cause: "self",
269
- error: createSerializableError(error)
270
- });
271
- throw new WorkflowRunFailedError(run.id, run[INTERNAL].handle.run.attempts);
272
- }
273
- }
257
+ const output = await this.parse(handle, this.params.schema?.output, outputRaw);
274
258
  return { output, lastAttempt: attempts };
275
259
  } catch (error) {
276
260
  if (error instanceof WorkflowRunFailedError || error instanceof WorkflowRunSuspendedError || error instanceof WorkflowRunConflictError) {
@@ -283,7 +267,7 @@ var TaskImpl = class _TaskImpl {
283
267
  "aiki.attempts": attempts,
284
268
  "aiki.reason": serializableError.message
285
269
  });
286
- await run[INTERNAL].handle[INTERNAL].transitionTaskState({
270
+ await handle[INTERNAL].transitionTaskState({
287
271
  taskId,
288
272
  taskState: { status: "failed", attempts, error: serializableError }
289
273
  });
@@ -294,12 +278,12 @@ var TaskImpl = class _TaskImpl {
294
278
  "aiki.nextAttemptInMs": retryParams.delayMs,
295
279
  "aiki.reason": serializableError.message
296
280
  });
297
- if (retryParams.delayMs <= run[INTERNAL].options.spinThresholdMs) {
281
+ if (retryParams.delayMs <= spinThresholdMs) {
298
282
  await delay(retryParams.delayMs);
299
283
  attempts++;
300
284
  continue;
301
285
  }
302
- await run[INTERNAL].handle[INTERNAL].transitionTaskState({
286
+ await handle[INTERNAL].transitionTaskState({
303
287
  taskId,
304
288
  taskState: {
305
289
  status: "awaiting_retry",
@@ -308,7 +292,7 @@ var TaskImpl = class _TaskImpl {
308
292
  nextAttemptInMs: retryParams.delayMs
309
293
  }
310
294
  });
311
- throw new WorkflowRunSuspendedError(run.id);
295
+ throw new WorkflowRunSuspendedError(handle.run.id);
312
296
  }
313
297
  }
314
298
  }
@@ -348,6 +332,21 @@ var TaskImpl = class _TaskImpl {
348
332
  throw new TaskFailedError(taskId, attempts, "Task retry not allowed");
349
333
  }
350
334
  }
335
+ async parse(handle, schema, data) {
336
+ if (!schema) {
337
+ return data;
338
+ }
339
+ try {
340
+ return schema.parse(data);
341
+ } catch (error) {
342
+ await handle[INTERNAL].transitionState({
343
+ status: "failed",
344
+ cause: "self",
345
+ error: createSerializableError(error)
346
+ });
347
+ throw new WorkflowRunFailedError(handle.run.id, handle.run.attempts);
348
+ }
349
+ }
351
350
  };
352
351
  export {
353
352
  task
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikirun/task",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Task SDK for Aiki - define reliable tasks with automatic retries, idempotency, and error handling",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,8 +18,8 @@
18
18
  "build": "tsup"
19
19
  },
20
20
  "dependencies": {
21
- "@aikirun/types": "0.8.0",
22
- "@aikirun/workflow": "0.8.0"
21
+ "@aikirun/types": "0.9.0",
22
+ "@aikirun/workflow": "0.9.0"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"