duron 0.3.0-beta.9 → 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.
- package/dist/action-job.d.ts +33 -2
- package/dist/action-job.d.ts.map +1 -1
- package/dist/action-job.js +88 -23
- package/dist/action-manager.d.ts +44 -2
- package/dist/action-manager.d.ts.map +1 -1
- package/dist/action-manager.js +64 -3
- package/dist/action.d.ts +388 -7
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +44 -23
- package/dist/adapters/adapter.d.ts +365 -8
- package/dist/adapters/adapter.d.ts.map +1 -1
- package/dist/adapters/adapter.js +221 -15
- package/dist/adapters/postgres/base.d.ts +184 -6
- package/dist/adapters/postgres/base.d.ts.map +1 -1
- package/dist/adapters/postgres/base.js +436 -75
- package/dist/adapters/postgres/pglite.d.ts +37 -0
- package/dist/adapters/postgres/pglite.d.ts.map +1 -1
- package/dist/adapters/postgres/pglite.js +38 -0
- package/dist/adapters/postgres/postgres.d.ts +35 -0
- package/dist/adapters/postgres/postgres.d.ts.map +1 -1
- package/dist/adapters/postgres/postgres.js +42 -0
- package/dist/adapters/postgres/schema.d.ts +150 -37
- package/dist/adapters/postgres/schema.d.ts.map +1 -1
- package/dist/adapters/postgres/schema.default.d.ts +151 -38
- package/dist/adapters/postgres/schema.default.d.ts.map +1 -1
- package/dist/adapters/postgres/schema.default.js +2 -2
- package/dist/adapters/postgres/schema.js +60 -23
- package/dist/adapters/schemas.d.ts +124 -80
- package/dist/adapters/schemas.d.ts.map +1 -1
- package/dist/adapters/schemas.js +139 -26
- package/dist/client.d.ts +426 -22
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +370 -20
- package/dist/constants.js +6 -0
- package/dist/errors.d.ts +140 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +152 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/server.d.ts +99 -37
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +84 -25
- package/dist/step-manager.d.ts +111 -4
- package/dist/step-manager.d.ts.map +1 -1
- package/dist/step-manager.js +403 -75
- package/dist/telemetry/index.d.ts +1 -4
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +2 -4
- package/dist/telemetry/local-span-exporter.d.ts +56 -0
- package/dist/telemetry/local-span-exporter.d.ts.map +1 -0
- package/dist/telemetry/local-span-exporter.js +118 -0
- package/dist/utils/p-retry.d.ts +5 -0
- package/dist/utils/p-retry.d.ts.map +1 -1
- package/dist/utils/p-retry.js +8 -0
- package/dist/utils/wait-for-abort.d.ts +1 -0
- package/dist/utils/wait-for-abort.d.ts.map +1 -1
- package/dist/utils/wait-for-abort.js +1 -0
- package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/migration.sql +32 -20
- package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/snapshot.json +241 -66
- package/package.json +42 -26
- package/src/action-job.ts +33 -29
- package/src/action-manager.ts +5 -5
- package/src/action.ts +317 -149
- package/src/adapters/adapter.ts +54 -54
- package/src/adapters/postgres/base.ts +266 -86
- package/src/adapters/postgres/schema.default.ts +2 -2
- package/src/adapters/postgres/schema.ts +52 -24
- package/src/adapters/schemas.ts +91 -36
- package/src/client.ts +322 -68
- package/src/errors.ts +84 -12
- package/src/index.ts +2 -0
- package/src/server.ts +39 -37
- package/src/step-manager.ts +246 -95
- package/src/telemetry/index.ts +2 -20
- package/src/telemetry/local-span-exporter.ts +148 -0
- package/dist/telemetry/adapter.d.ts +0 -107
- package/dist/telemetry/adapter.d.ts.map +0 -1
- package/dist/telemetry/adapter.js +0 -134
- package/dist/telemetry/local.d.ts +0 -22
- package/dist/telemetry/local.d.ts.map +0 -1
- package/dist/telemetry/local.js +0 -243
- package/dist/telemetry/noop.d.ts +0 -17
- package/dist/telemetry/noop.d.ts.map +0 -1
- package/dist/telemetry/noop.js +0 -66
- package/dist/telemetry/opentelemetry.d.ts +0 -25
- package/dist/telemetry/opentelemetry.d.ts.map +0 -1
- package/dist/telemetry/opentelemetry.js +0 -312
- package/src/telemetry/adapter.ts +0 -642
- package/src/telemetry/local.ts +0 -429
- package/src/telemetry/noop.ts +0 -141
- 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 {
|
|
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
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* Telemetry context for recording metrics and span data.
|
|
20
|
+
* Provides access to OpenTelemetry APIs for recording traces and metrics.
|
|
21
21
|
*/
|
|
22
|
-
|
|
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
|
-
*
|
|
75
|
-
*
|
|
74
|
+
* Telemetry context for recording metrics and span data.
|
|
75
|
+
* Provides access to OpenTelemetry APIs for recording traces and metrics.
|
|
76
76
|
*/
|
|
77
|
-
|
|
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
|
|
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:
|
|
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
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
TVariables
|
|
196
|
-
|
|
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
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
*
|
|
263
|
+
* Configuration options for steps within an action.
|
|
264
|
+
* Controls concurrency, retries, and timeouts for step execution.
|
|
238
265
|
*/
|
|
239
|
-
export
|
|
266
|
+
export interface StepsConfigInput {
|
|
240
267
|
/**
|
|
241
|
-
*
|
|
242
|
-
*
|
|
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
|
-
|
|
273
|
+
concurrency?: number
|
|
245
274
|
|
|
246
275
|
/**
|
|
247
|
-
*
|
|
248
|
-
*
|
|
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
|
|
253
|
-
|
|
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
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
354
|
-
|
|
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
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
-
.
|
|
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(':')
|