duron 0.3.0-beta.8 → 0.3.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 (91) hide show
  1. package/dist/action-job.d.ts +33 -2
  2. package/dist/action-job.d.ts.map +1 -1
  3. package/dist/action-job.js +93 -26
  4. package/dist/action-manager.d.ts +44 -2
  5. package/dist/action-manager.d.ts.map +1 -1
  6. package/dist/action-manager.js +64 -3
  7. package/dist/action.d.ts +388 -7
  8. package/dist/action.d.ts.map +1 -1
  9. package/dist/action.js +44 -23
  10. package/dist/adapters/adapter.d.ts +365 -8
  11. package/dist/adapters/adapter.d.ts.map +1 -1
  12. package/dist/adapters/adapter.js +221 -15
  13. package/dist/adapters/postgres/base.d.ts +184 -6
  14. package/dist/adapters/postgres/base.d.ts.map +1 -1
  15. package/dist/adapters/postgres/base.js +436 -75
  16. package/dist/adapters/postgres/pglite.d.ts +37 -0
  17. package/dist/adapters/postgres/pglite.d.ts.map +1 -1
  18. package/dist/adapters/postgres/pglite.js +38 -0
  19. package/dist/adapters/postgres/postgres.d.ts +35 -0
  20. package/dist/adapters/postgres/postgres.d.ts.map +1 -1
  21. package/dist/adapters/postgres/postgres.js +42 -0
  22. package/dist/adapters/postgres/schema.d.ts +150 -37
  23. package/dist/adapters/postgres/schema.d.ts.map +1 -1
  24. package/dist/adapters/postgres/schema.default.d.ts +151 -38
  25. package/dist/adapters/postgres/schema.default.d.ts.map +1 -1
  26. package/dist/adapters/postgres/schema.default.js +2 -2
  27. package/dist/adapters/postgres/schema.js +60 -23
  28. package/dist/adapters/schemas.d.ts +124 -80
  29. package/dist/adapters/schemas.d.ts.map +1 -1
  30. package/dist/adapters/schemas.js +139 -26
  31. package/dist/client.d.ts +426 -22
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +370 -20
  34. package/dist/constants.js +6 -0
  35. package/dist/errors.d.ts +166 -9
  36. package/dist/errors.d.ts.map +1 -1
  37. package/dist/errors.js +189 -19
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/server.d.ts +99 -37
  41. package/dist/server.d.ts.map +1 -1
  42. package/dist/server.js +84 -25
  43. package/dist/step-manager.d.ts +111 -4
  44. package/dist/step-manager.d.ts.map +1 -1
  45. package/dist/step-manager.js +411 -75
  46. package/dist/telemetry/index.d.ts +1 -4
  47. package/dist/telemetry/index.d.ts.map +1 -1
  48. package/dist/telemetry/index.js +2 -4
  49. package/dist/telemetry/local-span-exporter.d.ts +56 -0
  50. package/dist/telemetry/local-span-exporter.d.ts.map +1 -0
  51. package/dist/telemetry/local-span-exporter.js +118 -0
  52. package/dist/utils/p-retry.d.ts +5 -0
  53. package/dist/utils/p-retry.d.ts.map +1 -1
  54. package/dist/utils/p-retry.js +8 -0
  55. package/dist/utils/wait-for-abort.d.ts +1 -0
  56. package/dist/utils/wait-for-abort.d.ts.map +1 -1
  57. package/dist/utils/wait-for-abort.js +1 -0
  58. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/migration.sql +32 -20
  59. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/snapshot.json +241 -66
  60. package/package.json +42 -26
  61. package/src/action-job.ts +43 -32
  62. package/src/action-manager.ts +5 -5
  63. package/src/action.ts +317 -149
  64. package/src/adapters/adapter.ts +54 -54
  65. package/src/adapters/postgres/base.ts +266 -86
  66. package/src/adapters/postgres/schema.default.ts +2 -2
  67. package/src/adapters/postgres/schema.ts +52 -24
  68. package/src/adapters/schemas.ts +91 -36
  69. package/src/client.ts +322 -68
  70. package/src/errors.ts +141 -30
  71. package/src/index.ts +2 -0
  72. package/src/server.ts +39 -37
  73. package/src/step-manager.ts +254 -91
  74. package/src/telemetry/index.ts +2 -20
  75. package/src/telemetry/local-span-exporter.ts +148 -0
  76. package/dist/telemetry/adapter.d.ts +0 -107
  77. package/dist/telemetry/adapter.d.ts.map +0 -1
  78. package/dist/telemetry/adapter.js +0 -134
  79. package/dist/telemetry/local.d.ts +0 -22
  80. package/dist/telemetry/local.d.ts.map +0 -1
  81. package/dist/telemetry/local.js +0 -243
  82. package/dist/telemetry/noop.d.ts +0 -17
  83. package/dist/telemetry/noop.d.ts.map +0 -1
  84. package/dist/telemetry/noop.js +0 -66
  85. package/dist/telemetry/opentelemetry.d.ts +0 -25
  86. package/dist/telemetry/opentelemetry.d.ts.map +0 -1
  87. package/dist/telemetry/opentelemetry.js +0 -312
  88. package/src/telemetry/adapter.ts +0 -642
  89. package/src/telemetry/local.ts +0 -429
  90. package/src/telemetry/noop.ts +0 -141
  91. package/src/telemetry/opentelemetry.ts +0 -453
package/src/action.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Logger } from 'pino'
2
2
  import * as z from 'zod'
3
3
 
4
- import type { ObserveContext } from './telemetry/adapter.js'
4
+ import type { TelemetryContext } from './step-manager.js'
5
5
  import generateChecksum from './utils/checksum.js'
6
6
 
7
7
  export type RetryOptions = z.infer<typeof RetryOptionsSchema>
@@ -16,10 +16,10 @@ export interface ActionHandlerContext<TInput extends z.ZodObject, TVariables = R
16
16
  logger: Logger
17
17
 
18
18
  /**
19
- * Observability context for recording metrics and span data.
20
- * Allows recording custom metrics, span attributes, and events.
19
+ * Telemetry context for recording metrics and span data.
20
+ * Provides access to OpenTelemetry APIs for recording traces and metrics.
21
21
  */
22
- observe: ObserveContext
22
+ telemetry: TelemetryContext
23
23
 
24
24
  /**
25
25
  * Execute an inline step within the action.
@@ -71,10 +71,10 @@ export interface StepHandlerContext {
71
71
  parentStepId: string | null
72
72
 
73
73
  /**
74
- * Observability context for recording metrics and span data.
75
- * Allows recording custom metrics, span attributes, and events.
74
+ * Telemetry context for recording metrics and span data.
75
+ * Provides access to OpenTelemetry APIs for recording traces and metrics.
76
76
  */
77
- observe: ObserveContext
77
+ telemetry: TelemetryContext
78
78
 
79
79
  /**
80
80
  * Create a nested child step.
@@ -142,9 +142,20 @@ export interface StepDefinitionHandlerContext<TInput extends z.ZodObject, TVaria
142
142
  export interface StepDefinition<TInput extends z.ZodObject, TResult, TVariables = Record<string, unknown>> {
143
143
  /**
144
144
  * The name of the step.
145
- * Can be a static string or a function that generates the name from the input.
145
+ * Can be a static string or a function that generates the name from the context.
146
+ * The function receives a context object with input, variables, jobId, and parentStepId.
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * name: (ctx) => `process-user-${ctx.input.userId}`
151
+ * ```
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * name: (ctx) => `step-${ctx.var.environment}-${ctx.jobId.slice(0, 8)}`
156
+ * ```
146
157
  */
147
- name: string | ((ctx: { input: z.infer<TInput> }) => string)
158
+ name: string | ((ctx: StepNameContext<TInput, TVariables>) => string)
148
159
 
149
160
  /**
150
161
  * Zod schema for validating the step input.
@@ -183,95 +194,315 @@ export interface ConcurrencyHandlerContext<TInput extends z.ZodObject, TVariable
183
194
  var: TVariables
184
195
  }
185
196
 
186
- export type ActionDefinition<
187
- TInput extends z.ZodObject,
188
- TOutput extends z.ZodObject,
189
- TVariables = Record<string, unknown>,
190
- > = z.input<ReturnType<typeof createActionDefinitionSchema<TInput, TOutput, TVariables>>>
197
+ /**
198
+ * Context available when generating dynamic step names.
199
+ * Provides access to input, variables, job ID, and parent step ID.
200
+ */
201
+ export interface StepNameContext<TInput extends z.ZodObject, TVariables = Record<string, unknown>> {
202
+ /**
203
+ * The validated input for this step.
204
+ */
205
+ input: z.infer<TInput>
191
206
 
192
- export type Action<
193
- TInput extends z.ZodObject,
194
- TOutput extends z.ZodObject,
195
- TVariables = Record<string, unknown>,
196
- > = z.infer<ReturnType<typeof createActionDefinitionSchema<TInput, TOutput, TVariables>>>
207
+ /**
208
+ * Variables shared across the action.
209
+ */
210
+ var: TVariables
211
+
212
+ /**
213
+ * The job ID this step belongs to.
214
+ */
215
+ jobId: string
216
+
217
+ /**
218
+ * The ID of the parent step, or null if this is a root step.
219
+ */
220
+ parentStepId: string | null
221
+ }
197
222
 
198
223
  /**
199
224
  * Retry configuration options for actions and steps.
225
+ * Controls how failed operations are retried with exponential backoff.
200
226
  */
201
- export const RetryOptionsSchema = z
202
- .object({
203
- /**
204
- * Maximum number of retry attempts.
205
- *
206
- * @default 4
207
- */
208
- limit: z.number().default(4),
227
+ export interface RetryOptionsInput {
228
+ /**
229
+ * Maximum number of retry attempts.
230
+ * Set to 0 to disable retries.
231
+ *
232
+ * @default 4
233
+ */
234
+ limit?: number
209
235
 
210
- /**
211
- * Exponential backoff factor.
212
- * The delay between retries is calculated as: minTimeout * (factor ^ attemptNumber)
213
- *
214
- * @default 2
215
- */
216
- factor: z.number().default(2),
236
+ /**
237
+ * Exponential backoff factor.
238
+ * The delay between retries is calculated as: `minTimeout * (factor ^ attemptNumber)`
239
+ *
240
+ * @default 2
241
+ */
242
+ factor?: number
217
243
 
218
- /**
219
- * Minimum delay in milliseconds before the first retry.
220
- *
221
- * @default 1000
222
- */
223
- minTimeout: z.number().default(1000),
244
+ /**
245
+ * Minimum delay in milliseconds before the first retry.
246
+ * This is the base delay that gets multiplied by the factor.
247
+ *
248
+ * @default 1000
249
+ */
250
+ minTimeout?: number
224
251
 
225
- /**
226
- * Maximum delay in milliseconds between retries.
227
- * The calculated delay will be capped at this value.
228
- *
229
- * @default 30000
230
- */
231
- maxTimeout: z.number().default(30000),
232
- })
233
- .default({ limit: 4, factor: 2, minTimeout: 1000, maxTimeout: 30000 })
234
- .describe('The retry options')
252
+ /**
253
+ * Maximum delay in milliseconds between retries.
254
+ * The calculated delay will be capped at this value to prevent
255
+ * excessively long wait times.
256
+ *
257
+ * @default 30000
258
+ */
259
+ maxTimeout?: number
260
+ }
235
261
 
236
262
  /**
237
- * Options for configuring a step within an action.
263
+ * Configuration options for steps within an action.
264
+ * Controls concurrency, retries, and timeouts for step execution.
238
265
  */
239
- export const StepOptionsSchema = z.object({
266
+ export interface StepsConfigInput {
240
267
  /**
241
- * Retry configuration for this step.
242
- * If not provided, uses the default retry options from the action or Duron instance.
268
+ * Maximum number of steps that can run concurrently within this action.
269
+ * Higher values allow more parallelism but may increase resource usage.
270
+ *
271
+ * @default 100
243
272
  */
244
- retry: RetryOptionsSchema,
273
+ concurrency?: number
245
274
 
246
275
  /**
247
- * Timeout in milliseconds for this step.
248
- * Steps that exceed this timeout will be cancelled.
276
+ * Retry configuration for steps.
277
+ * These settings apply to all steps unless overridden at the step level.
278
+ *
279
+ * @default { limit: 4, factor: 2, minTimeout: 1000, maxTimeout: 30000 }
280
+ */
281
+ retry?: RetryOptionsInput
282
+
283
+ /**
284
+ * Timeout in milliseconds for each step.
285
+ * Steps that exceed this timeout will be cancelled and may be retried.
249
286
  *
250
287
  * @default 300000 (5 minutes)
251
288
  */
252
- expire: z
253
- .number()
254
- .default(5 * 60 * 1000)
255
- .describe('The expire time for the step (milliseconds)'),
289
+ expire?: number
290
+ }
256
291
 
292
+ /**
293
+ * Group configuration for concurrency control.
294
+ * Allows grouping jobs by key and controlling concurrency per group.
295
+ */
296
+ export interface GroupsConfigInput<TInput extends z.ZodObject, TVariables = Record<string, unknown>> {
257
297
  /**
258
- * Whether this step runs in parallel with siblings.
259
- * Parallel steps are independent from siblings during time travel.
260
- * When time traveling to a step, completed parallel siblings are preserved.
298
+ * Function to determine the group key for a job.
299
+ * Jobs with the same group key will respect the group concurrency limit.
300
+ * Use this to limit concurrent processing of related jobs (e.g., per user, per tenant).
301
+ *
302
+ * If not provided, all jobs for this action will use the '@default' group key.
261
303
  *
262
- * @default false
304
+ * @param ctx - Context containing the validated input and variables
305
+ * @returns Promise resolving to the group key string
306
+ *
307
+ * @example
308
+ * ```typescript
309
+ * groupKey: async (ctx) => `user:${ctx.input.userId}`
310
+ * ```
263
311
  */
264
- parallel: z.boolean().default(false).describe('Whether this step runs in parallel (independent from siblings)'),
265
- })
312
+ groupKey?: (ctx: ConcurrencyHandlerContext<TInput, TVariables>) => Promise<string>
313
+
314
+ /**
315
+ * Function to dynamically determine the concurrency limit for a job's group.
316
+ * The concurrency limit is stored with each job and used during fetch operations.
317
+ * This allows different groups to have different concurrency limits.
318
+ *
319
+ * If not provided, uses the global `groupConcurrencyLimit` from the client options.
320
+ *
321
+ * @param ctx - Context containing the validated input and variables
322
+ * @returns Promise resolving to the concurrency limit number
323
+ *
324
+ * @example
325
+ * ```typescript
326
+ * concurrency: async (ctx) => ctx.input.priority === 'high' ? 10 : 2
327
+ * ```
328
+ */
329
+ concurrency?: (ctx: ConcurrencyHandlerContext<TInput, TVariables>) => Promise<number>
330
+ }
266
331
 
267
332
  /**
268
- * Creates a Zod schema for validating action definitions.
333
+ * Definition for creating a Duron action.
334
+ * Actions are type-safe, durable job handlers with built-in retry logic,
335
+ * step-based execution, and concurrency control.
269
336
  *
270
- * @template TInput - Zod schema for the action input
271
- * @template TOutput - Zod schema for the action output
272
- * @template TVariables - Type of variables available to the action
273
- * @returns Zod schema for action definitions
337
+ * @template TInput - Zod schema type for validating the action input
338
+ * @template TOutput - Zod schema type for validating the action output
339
+ * @template TVariables - Type of variables available to the action handler
274
340
  */
341
+ export interface ActionDefinitionInput<
342
+ TInput extends z.ZodObject,
343
+ TOutput extends z.ZodObject,
344
+ TVariables = Record<string, unknown>,
345
+ > {
346
+ /**
347
+ * Unique name for this action.
348
+ * Used as the queue name and must be unique across all actions registered with a client.
349
+ * This name is used for job routing, logging, and dashboard display.
350
+ *
351
+ * @example 'send-email', 'process-payment', 'sync-user-data'
352
+ */
353
+ name: string
354
+
355
+ /**
356
+ * Optional version string for the action.
357
+ * Used to track changes to the action and included in the checksum calculation.
358
+ * Changing the version will cause existing jobs to be treated as having a different checksum.
359
+ *
360
+ * @example '1.0.0', '2024-01-15', 'v2'
361
+ */
362
+ version?: string
363
+
364
+ /**
365
+ * Zod schema for validating the action input.
366
+ * If provided, input will be validated before the handler is called.
367
+ * Invalid input will throw a validation error and the job will fail.
368
+ *
369
+ * @example
370
+ * ```typescript
371
+ * input: z.object({
372
+ * email: z.string().email(),
373
+ * subject: z.string().min(1),
374
+ * })
375
+ * ```
376
+ */
377
+ input?: TInput
378
+
379
+ /**
380
+ * Zod schema for validating the action output.
381
+ * If provided, output will be validated after the handler completes.
382
+ * Invalid output will cause the job to fail.
383
+ *
384
+ * @example
385
+ * ```typescript
386
+ * output: z.object({
387
+ * success: z.boolean(),
388
+ * messageId: z.string().optional(),
389
+ * })
390
+ * ```
391
+ */
392
+ output?: TOutput
393
+
394
+ /**
395
+ * Group configuration for concurrency control.
396
+ * Allows grouping jobs by a dynamic key and controlling concurrency per group.
397
+ * Useful for rate limiting per user, tenant, or resource.
398
+ */
399
+ groups?: GroupsConfigInput<TInput, TVariables>
400
+
401
+ /**
402
+ * Configuration for steps within this action.
403
+ * Steps are retryable units of work that can be executed within the action handler.
404
+ * These settings apply to all steps unless overridden at the step level.
405
+ *
406
+ * @default { concurrency: 100, retry: { limit: 4, factor: 2, minTimeout: 1000, maxTimeout: 30000 }, expire: 300000 }
407
+ */
408
+ steps?: StepsConfigInput
409
+
410
+ /**
411
+ * Maximum number of jobs for this action that can run concurrently across all workers.
412
+ * This limit is enforced per action, regardless of group.
413
+ *
414
+ * @default 100
415
+ */
416
+ concurrency?: number
417
+
418
+ /**
419
+ * Timeout in milliseconds for the entire action.
420
+ * Jobs that exceed this timeout will be cancelled.
421
+ * Make sure this is greater than the expected total execution time including all steps.
422
+ *
423
+ * @default 900000 (15 minutes)
424
+ */
425
+ expire?: number
426
+
427
+ /**
428
+ * Function to generate a dynamic description for the job.
429
+ * The description is calculated at job creation time and stored in the database.
430
+ * Use this to provide context about what the specific job instance is doing.
431
+ *
432
+ * @param ctx - Context containing the validated input and variables
433
+ * @returns Promise resolving to the description string
434
+ *
435
+ * @example
436
+ * ```typescript
437
+ * description: async (ctx) => `Send email to ${ctx.input.email}`
438
+ * ```
439
+ */
440
+ description?: (ctx: ConcurrencyHandlerContext<TInput, TVariables>) => Promise<string>
441
+
442
+ /**
443
+ * The handler function that executes the action logic.
444
+ * Receives a context object with validated input, variables, logger, and step functions.
445
+ * Must return a Promise that resolves to the action output (matching the output schema if provided).
446
+ *
447
+ * @param ctx - Action handler context with input, variables, and step functions
448
+ * @returns Promise resolving to the action output
449
+ *
450
+ * @example
451
+ * ```typescript
452
+ * handler: async (ctx) => {
453
+ * const result = await ctx.step('send', async () => {
454
+ * return await sendEmail(ctx.input.email, ctx.input.subject)
455
+ * })
456
+ * return { success: true, messageId: result.id }
457
+ * }
458
+ * ```
459
+ */
460
+ handler: (ctx: ActionHandlerContext<TInput, TVariables>) => Promise<z.infer<TOutput>>
461
+ }
462
+
463
+ // Type alias for backwards compatibility (inferred from Zod schema)
464
+ export type ActionDefinition<
465
+ TInput extends z.ZodObject,
466
+ TOutput extends z.ZodObject,
467
+ TVariables = Record<string, unknown>,
468
+ > = ActionDefinitionInput<TInput, TOutput, TVariables>
469
+
470
+ // Compile-time check: ensure ActionDefinitionInput is assignable to the Zod schema's input type
471
+ type _EnsureActionDefinitionCompatible<
472
+ TInput extends z.ZodObject,
473
+ TOutput extends z.ZodObject,
474
+ TVariables,
475
+ > = ActionDefinitionInput<TInput, TOutput, TVariables> extends z.input<
476
+ ReturnType<typeof createActionDefinitionSchema<TInput, TOutput, TVariables>>
477
+ >
478
+ ? true
479
+ : 'ERROR: ActionDefinitionInput does not match Zod schema input type'
480
+
481
+ // This will cause a compile error if the types diverge
482
+ declare const _actionDefCheck: _EnsureActionDefinitionCompatible<z.ZodObject<any>, z.ZodObject<any>, any>
483
+ const _checkActionDef: _EnsureActionDefinitionCompatible<z.ZodObject<any>, z.ZodObject<any>, any> = true
484
+
485
+ export type Action<
486
+ TInput extends z.ZodObject,
487
+ TOutput extends z.ZodObject,
488
+ TVariables = Record<string, unknown>,
489
+ > = z.infer<ReturnType<typeof createActionDefinitionSchema<TInput, TOutput, TVariables>>>
490
+
491
+ export const RetryOptionsSchema = z
492
+ .object({
493
+ limit: z.number().default(4),
494
+ factor: z.number().default(2),
495
+ minTimeout: z.number().default(1000),
496
+ maxTimeout: z.number().default(30000),
497
+ })
498
+ .default({ limit: 4, factor: 2, minTimeout: 1000, maxTimeout: 30000 })
499
+
500
+ export const StepOptionsSchema = z.object({
501
+ retry: RetryOptionsSchema,
502
+ expire: z.number().default(5 * 60 * 1000),
503
+ parallel: z.boolean().default(false),
504
+ })
505
+
275
506
  export function createActionDefinitionSchema<
276
507
  TInput extends z.ZodObject,
277
508
  TOutput extends z.ZodObject,
@@ -279,66 +510,25 @@ export function createActionDefinitionSchema<
279
510
  >() {
280
511
  return z
281
512
  .object({
282
- /**
283
- * Unique name for this action.
284
- * Used as the queue name and must be unique across all actions.
285
- * Required.
286
- */
287
- name: z.string().describe('The name of the action'),
288
-
289
- /**
290
- * Version of the action.
291
- * Used to track changes to the action and generate the checksum.
292
- */
293
- version: z.string().describe('The version of the action').optional(),
294
-
295
- /**
296
- * Zod schema for validating the action input.
297
- * If provided, input will be validated before the handler is called.
298
- * If not provided, any input will be accepted.
299
- */
513
+ name: z.string(),
514
+ version: z.string().optional(),
300
515
  input: z
301
516
  .custom<TInput>((val: any) => {
302
517
  return !val || ('_zod' in val && 'type' in val && val.type === 'object')
303
518
  })
304
519
  .optional(),
305
-
306
- /**
307
- * Zod schema for validating the action output.
308
- * If provided, output will be validated after the handler completes.
309
- * If not provided, any output will be accepted.
310
- */
311
520
  output: z
312
521
  .custom<TOutput>((val: any) => {
313
522
  return !val || ('_zod' in val && 'type' in val && val.type === 'object')
314
523
  })
315
524
  .optional(),
316
-
317
525
  groups: z
318
526
  .object({
319
- /**
320
- * Function to determine the group key for a job.
321
- * Jobs with the same group key will respect the group concurrency limit.
322
- * If not provided, all jobs for this action will use the '@default' group key.
323
- *
324
- * @param ctx - Context containing the input and variables
325
- * @returns Promise resolving to the group key string
326
- */
327
527
  groupKey: z
328
528
  .custom<(ctx: ConcurrencyHandlerContext<TInput, TVariables>) => Promise<string>>((val) => {
329
529
  return !val || val instanceof Function
330
530
  })
331
531
  .optional(),
332
-
333
- /**
334
- * Function to determine the concurrency limit for a job.
335
- * The concurrency limit is stored with each job and used during fetch operations.
336
- * When fetching jobs, the latest job's concurrency limit is used for each groupKey.
337
- * If not provided, defaults to 10.
338
- *
339
- * @param ctx - Context containing the input and variables
340
- * @returns Promise resolving to the concurrency limit number
341
- */
342
532
  concurrency: z
343
533
  .custom<(ctx: ConcurrencyHandlerContext<TInput, TVariables>) => Promise<number>>((val) => {
344
534
  return !val || val instanceof Function
@@ -346,49 +536,27 @@ export function createActionDefinitionSchema<
346
536
  .optional(),
347
537
  })
348
538
  .optional(),
349
-
350
539
  steps: z
351
540
  .object({
352
- /**
353
- * Function to determine the concurrency limit for a step.
354
- * The concurrency limit is stored with each step and used during fetch operations.
355
- * When fetching steps, the latest step's concurrency limit is used for each stepKey.
356
- * If not provided, defaults to 100.
357
- */
358
- concurrency: z.number().default(100).describe('How many steps can run concurrently for this action'),
359
- retry: RetryOptionsSchema.describe('How to retry on failure for the steps of this action'),
360
- expire: z
361
- .number()
362
- .default(5 * 60 * 1000)
363
- .describe('How long a step can run for (milliseconds)'),
541
+ concurrency: z.number().default(100),
542
+ retry: RetryOptionsSchema,
543
+ expire: z.number().default(5 * 60 * 1000),
364
544
  })
365
545
  .default({
366
546
  concurrency: 100,
367
547
  retry: { limit: 4, factor: 2, minTimeout: 1000, maxTimeout: 30000 },
368
548
  expire: 5 * 60 * 1000,
369
549
  }),
370
-
371
- concurrency: z.number().default(100).describe('How many jobs can run concurrently for this action'),
372
-
373
- expire: z
374
- .number()
375
- .default(15 * 60 * 1000)
376
- .describe('How long a job can run for (milliseconds)'),
377
-
378
- /**
379
- * The handler function that executes the action logic.
380
- * Receives a context object with input, variables, and a step function.
381
- * Must return a Promise that resolves to the action output.
382
- * Required.
383
- *
384
- * @param ctx - Action handler context
385
- * @returns Promise resolving to the action output
386
- */
387
- handler: z
388
- .custom<(ctx: ActionHandlerContext<TInput, TVariables>) => Promise<z.infer<TOutput>>>((val) => {
389
- return val instanceof Function
550
+ concurrency: z.number().default(100),
551
+ expire: z.number().default(15 * 60 * 1000),
552
+ description: z
553
+ .custom<(ctx: ConcurrencyHandlerContext<TInput, TVariables>) => Promise<string>>((val) => {
554
+ return !val || val instanceof Function
390
555
  })
391
- .describe('The handler for the action'),
556
+ .optional(),
557
+ handler: z.custom<(ctx: ActionHandlerContext<TInput, TVariables>) => Promise<z.infer<TOutput>>>((val) => {
558
+ return val instanceof Function
559
+ }),
392
560
  })
393
561
  .transform((def) => {
394
562
  const checksum = [def.name, def.version, def.handler.toString()].filter(Boolean).join(':')