@nest-batch/core 0.2.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/LICENSE +21 -0
- package/README.md +368 -0
- package/dist/src/adapters/in-process.adapter.d.ts +140 -0
- package/dist/src/adapters/in-process.adapter.d.ts.map +1 -0
- package/dist/src/adapters/in-process.adapter.js +86 -0
- package/dist/src/adapters/in-process.adapter.js.map +1 -0
- package/dist/src/adapters/index.d.ts +18 -0
- package/dist/src/adapters/index.d.ts.map +1 -0
- package/dist/src/adapters/index.js +35 -0
- package/dist/src/adapters/index.js.map +1 -0
- package/dist/src/builder/batch-builder.d.ts +26 -0
- package/dist/src/builder/batch-builder.d.ts.map +1 -0
- package/dist/src/builder/batch-builder.js +25 -0
- package/dist/src/builder/batch-builder.js.map +1 -0
- package/dist/src/builder/flow-builder.d.ts +59 -0
- package/dist/src/builder/flow-builder.d.ts.map +1 -0
- package/dist/src/builder/flow-builder.js +115 -0
- package/dist/src/builder/flow-builder.js.map +1 -0
- package/dist/src/builder/index.d.ts +5 -0
- package/dist/src/builder/index.d.ts.map +1 -0
- package/dist/src/builder/index.js +23 -0
- package/dist/src/builder/index.js.map +1 -0
- package/dist/src/builder/job-builder.d.ts +76 -0
- package/dist/src/builder/job-builder.d.ts.map +1 -0
- package/dist/src/builder/job-builder.js +166 -0
- package/dist/src/builder/job-builder.js.map +1 -0
- package/dist/src/builder/step-builder.d.ts +74 -0
- package/dist/src/builder/step-builder.d.ts.map +1 -0
- package/dist/src/builder/step-builder.js +144 -0
- package/dist/src/builder/step-builder.js.map +1 -0
- package/dist/src/compiler/builder-types.d.ts +20 -0
- package/dist/src/compiler/builder-types.d.ts.map +1 -0
- package/dist/src/compiler/builder-types.js +6 -0
- package/dist/src/compiler/builder-types.js.map +1 -0
- package/dist/src/compiler/definition-compiler.d.ts +99 -0
- package/dist/src/compiler/definition-compiler.d.ts.map +1 -0
- package/dist/src/compiler/definition-compiler.js +257 -0
- package/dist/src/compiler/definition-compiler.js.map +1 -0
- package/dist/src/compiler/index.d.ts +3 -0
- package/dist/src/compiler/index.d.ts.map +1 -0
- package/dist/src/compiler/index.js +21 -0
- package/dist/src/compiler/index.js.map +1 -0
- package/dist/src/core/errors.d.ts +77 -0
- package/dist/src/core/errors.d.ts.map +1 -0
- package/dist/src/core/errors.js +170 -0
- package/dist/src/core/errors.js.map +1 -0
- package/dist/src/core/execution-context/index.d.ts +4 -0
- package/dist/src/core/execution-context/index.d.ts.map +1 -0
- package/dist/src/core/execution-context/index.js +22 -0
- package/dist/src/core/execution-context/index.js.map +1 -0
- package/dist/src/core/execution-context/json-value.d.ts +5 -0
- package/dist/src/core/execution-context/json-value.d.ts.map +1 -0
- package/dist/src/core/execution-context/json-value.js +6 -0
- package/dist/src/core/execution-context/json-value.js.map +1 -0
- package/dist/src/core/execution-context/serializer.d.ts +4 -0
- package/dist/src/core/execution-context/serializer.d.ts.map +1 -0
- package/dist/src/core/execution-context/serializer.js +34 -0
- package/dist/src/core/execution-context/serializer.js.map +1 -0
- package/dist/src/core/execution-context/validator.d.ts +18 -0
- package/dist/src/core/execution-context/validator.d.ts.map +1 -0
- package/dist/src/core/execution-context/validator.js +90 -0
- package/dist/src/core/execution-context/validator.js.map +1 -0
- package/dist/src/core/index.d.ts +8 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +26 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/core/ir/decider-definition.d.ts +20 -0
- package/dist/src/core/ir/decider-definition.d.ts.map +1 -0
- package/dist/src/core/ir/decider-definition.js +6 -0
- package/dist/src/core/ir/decider-definition.js.map +1 -0
- package/dist/src/core/ir/index.d.ts +8 -0
- package/dist/src/core/ir/index.d.ts.map +1 -0
- package/dist/src/core/ir/index.js +26 -0
- package/dist/src/core/ir/index.js.map +1 -0
- package/dist/src/core/ir/job-definition.d.ts +15 -0
- package/dist/src/core/ir/job-definition.d.ts.map +1 -0
- package/dist/src/core/ir/job-definition.js +6 -0
- package/dist/src/core/ir/job-definition.js.map +1 -0
- package/dist/src/core/ir/listener-definition.d.ts +10 -0
- package/dist/src/core/ir/listener-definition.d.ts.map +1 -0
- package/dist/src/core/ir/listener-definition.js +6 -0
- package/dist/src/core/ir/listener-definition.js.map +1 -0
- package/dist/src/core/ir/policy-config.d.ts +24 -0
- package/dist/src/core/ir/policy-config.d.ts.map +1 -0
- package/dist/src/core/ir/policy-config.js +6 -0
- package/dist/src/core/ir/policy-config.js.map +1 -0
- package/dist/src/core/ir/refs.d.ts +42 -0
- package/dist/src/core/ir/refs.d.ts.map +1 -0
- package/dist/src/core/ir/refs.js +18 -0
- package/dist/src/core/ir/refs.js.map +1 -0
- package/dist/src/core/ir/step-definition.d.ts +59 -0
- package/dist/src/core/ir/step-definition.d.ts.map +1 -0
- package/dist/src/core/ir/step-definition.js +6 -0
- package/dist/src/core/ir/step-definition.js.map +1 -0
- package/dist/src/core/ir/transition-definition.d.ts +8 -0
- package/dist/src/core/ir/transition-definition.d.ts.map +1 -0
- package/dist/src/core/ir/transition-definition.js +6 -0
- package/dist/src/core/ir/transition-definition.js.map +1 -0
- package/dist/src/core/item/index.d.ts +2 -0
- package/dist/src/core/item/index.d.ts.map +1 -0
- package/dist/src/core/item/index.js +20 -0
- package/dist/src/core/item/index.js.map +1 -0
- package/dist/src/core/item/interfaces.d.ts +64 -0
- package/dist/src/core/item/interfaces.d.ts.map +1 -0
- package/dist/src/core/item/interfaces.js +6 -0
- package/dist/src/core/item/interfaces.js.map +1 -0
- package/dist/src/core/repository/index.d.ts +3 -0
- package/dist/src/core/repository/index.d.ts.map +1 -0
- package/dist/src/core/repository/index.js +21 -0
- package/dist/src/core/repository/index.js.map +1 -0
- package/dist/src/core/repository/job-repository.d.ts +60 -0
- package/dist/src/core/repository/job-repository.d.ts.map +1 -0
- package/dist/src/core/repository/job-repository.js +27 -0
- package/dist/src/core/repository/job-repository.js.map +1 -0
- package/dist/src/core/repository/types.d.ts +84 -0
- package/dist/src/core/repository/types.d.ts.map +1 -0
- package/dist/src/core/repository/types.js +6 -0
- package/dist/src/core/repository/types.js.map +1 -0
- package/dist/src/core/status.d.ts +29 -0
- package/dist/src/core/status.d.ts.map +1 -0
- package/dist/src/core/status.js +58 -0
- package/dist/src/core/status.js.map +1 -0
- package/dist/src/core/transaction/index.d.ts +2 -0
- package/dist/src/core/transaction/index.d.ts.map +1 -0
- package/dist/src/core/transaction/index.js +20 -0
- package/dist/src/core/transaction/index.js.map +1 -0
- package/dist/src/core/transaction/transaction-manager.d.ts +8 -0
- package/dist/src/core/transaction/transaction-manager.d.ts.map +1 -0
- package/dist/src/core/transaction/transaction-manager.js +14 -0
- package/dist/src/core/transaction/transaction-manager.js.map +1 -0
- package/dist/src/core/validation/definition-validator.d.ts +46 -0
- package/dist/src/core/validation/definition-validator.d.ts.map +1 -0
- package/dist/src/core/validation/definition-validator.js +177 -0
- package/dist/src/core/validation/definition-validator.js.map +1 -0
- package/dist/src/core/validation/index.d.ts +2 -0
- package/dist/src/core/validation/index.d.ts.map +1 -0
- package/dist/src/core/validation/index.js +20 -0
- package/dist/src/core/validation/index.js.map +1 -0
- package/dist/src/decorators/constants.d.ts +10 -0
- package/dist/src/decorators/constants.d.ts.map +1 -0
- package/dist/src/decorators/constants.js +50 -0
- package/dist/src/decorators/constants.js.map +1 -0
- package/dist/src/decorators/flow.decorator.d.ts +25 -0
- package/dist/src/decorators/flow.decorator.d.ts.map +1 -0
- package/dist/src/decorators/flow.decorator.js +19 -0
- package/dist/src/decorators/flow.decorator.js.map +1 -0
- package/dist/src/decorators/index.d.ts +8 -0
- package/dist/src/decorators/index.d.ts.map +1 -0
- package/dist/src/decorators/index.js +26 -0
- package/dist/src/decorators/index.js.map +1 -0
- package/dist/src/decorators/item.decorators.d.ts +32 -0
- package/dist/src/decorators/item.decorators.d.ts.map +1 -0
- package/dist/src/decorators/item.decorators.js +40 -0
- package/dist/src/decorators/item.decorators.js.map +1 -0
- package/dist/src/decorators/job.decorator.d.ts +11 -0
- package/dist/src/decorators/job.decorator.d.ts.map +1 -0
- package/dist/src/decorators/job.decorator.js +17 -0
- package/dist/src/decorators/job.decorator.js.map +1 -0
- package/dist/src/decorators/listener.decorators.d.ts +56 -0
- package/dist/src/decorators/listener.decorators.d.ts.map +1 -0
- package/dist/src/decorators/listener.decorators.js +157 -0
- package/dist/src/decorators/listener.decorators.js.map +1 -0
- package/dist/src/decorators/step.decorator.d.ts +25 -0
- package/dist/src/decorators/step.decorator.d.ts.map +1 -0
- package/dist/src/decorators/step.decorator.js +21 -0
- package/dist/src/decorators/step.decorator.js.map +1 -0
- package/dist/src/decorators/tasklet.decorator.d.ts +7 -0
- package/dist/src/decorators/tasklet.decorator.d.ts.map +1 -0
- package/dist/src/decorators/tasklet.decorator.js +21 -0
- package/dist/src/decorators/tasklet.decorator.js.map +1 -0
- package/dist/src/execution/batch-worker-runner.d.ts +27 -0
- package/dist/src/execution/batch-worker-runner.d.ts.map +1 -0
- package/dist/src/execution/batch-worker-runner.js +147 -0
- package/dist/src/execution/batch-worker-runner.js.map +1 -0
- package/dist/src/execution/chunk-step-executor.d.ts +86 -0
- package/dist/src/execution/chunk-step-executor.d.ts.map +1 -0
- package/dist/src/execution/chunk-step-executor.js +482 -0
- package/dist/src/execution/chunk-step-executor.js.map +1 -0
- package/dist/src/execution/execution-strategy.d.ts +110 -0
- package/dist/src/execution/execution-strategy.d.ts.map +1 -0
- package/dist/src/execution/execution-strategy.js +13 -0
- package/dist/src/execution/execution-strategy.js.map +1 -0
- package/dist/src/execution/external-task-execution-strategy.d.ts +36 -0
- package/dist/src/execution/external-task-execution-strategy.d.ts.map +1 -0
- package/dist/src/execution/external-task-execution-strategy.js +97 -0
- package/dist/src/execution/external-task-execution-strategy.js.map +1 -0
- package/dist/src/execution/in-process-execution-strategy.d.ts +129 -0
- package/dist/src/execution/in-process-execution-strategy.d.ts.map +1 -0
- package/dist/src/execution/in-process-execution-strategy.js +141 -0
- package/dist/src/execution/in-process-execution-strategy.js.map +1 -0
- package/dist/src/execution/index.d.ts +14 -0
- package/dist/src/execution/index.d.ts.map +1 -0
- package/dist/src/execution/index.js +32 -0
- package/dist/src/execution/index.js.map +1 -0
- package/dist/src/execution/job-executor.d.ts +145 -0
- package/dist/src/execution/job-executor.d.ts.map +1 -0
- package/dist/src/execution/job-executor.js +475 -0
- package/dist/src/execution/job-executor.js.map +1 -0
- package/dist/src/execution/job-explorer.d.ts +15 -0
- package/dist/src/execution/job-explorer.d.ts.map +1 -0
- package/dist/src/execution/job-explorer.js +84 -0
- package/dist/src/execution/job-explorer.js.map +1 -0
- package/dist/src/execution/job-key.d.ts +3 -0
- package/dist/src/execution/job-key.d.ts.map +1 -0
- package/dist/src/execution/job-key.js +43 -0
- package/dist/src/execution/job-key.js.map +1 -0
- package/dist/src/execution/job-launcher.d.ts +75 -0
- package/dist/src/execution/job-launcher.d.ts.map +1 -0
- package/dist/src/execution/job-launcher.js +112 -0
- package/dist/src/execution/job-launcher.js.map +1 -0
- package/dist/src/execution/job-operator.d.ts +22 -0
- package/dist/src/execution/job-operator.d.ts.map +1 -0
- package/dist/src/execution/job-operator.js +125 -0
- package/dist/src/execution/job-operator.js.map +1 -0
- package/dist/src/execution/listener-invoker.d.ts +164 -0
- package/dist/src/execution/listener-invoker.d.ts.map +1 -0
- package/dist/src/execution/listener-invoker.js +246 -0
- package/dist/src/execution/listener-invoker.js.map +1 -0
- package/dist/src/execution/ref-resolver.d.ts +40 -0
- package/dist/src/execution/ref-resolver.d.ts.map +1 -0
- package/dist/src/execution/ref-resolver.js +41 -0
- package/dist/src/execution/ref-resolver.js.map +1 -0
- package/dist/src/execution/tasklet-step-executor.d.ts +79 -0
- package/dist/src/execution/tasklet-step-executor.d.ts.map +1 -0
- package/dist/src/execution/tasklet-step-executor.js +138 -0
- package/dist/src/execution/tasklet-step-executor.js.map +1 -0
- package/dist/src/explorer/batch-explorer.d.ts +138 -0
- package/dist/src/explorer/batch-explorer.d.ts.map +1 -0
- package/dist/src/explorer/batch-explorer.js +167 -0
- package/dist/src/explorer/batch-explorer.js.map +1 -0
- package/dist/src/explorer/index.d.ts +2 -0
- package/dist/src/explorer/index.d.ts.map +1 -0
- package/dist/src/explorer/index.js +20 -0
- package/dist/src/explorer/index.js.map +1 -0
- package/dist/src/flow/flow-evaluator.d.ts +30 -0
- package/dist/src/flow/flow-evaluator.d.ts.map +1 -0
- package/dist/src/flow/flow-evaluator.js +80 -0
- package/dist/src/flow/flow-evaluator.js.map +1 -0
- package/dist/src/flow/index.d.ts +2 -0
- package/dist/src/flow/index.d.ts.map +1 -0
- package/dist/src/flow/index.js +20 -0
- package/dist/src/flow/index.js.map +1 -0
- package/dist/src/index.d.ts +18 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +90 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/io/checkpoint.d.ts +7 -0
- package/dist/src/io/checkpoint.d.ts.map +1 -0
- package/dist/src/io/checkpoint.js +56 -0
- package/dist/src/io/checkpoint.js.map +1 -0
- package/dist/src/io/database.d.ts +50 -0
- package/dist/src/io/database.d.ts.map +1 -0
- package/dist/src/io/database.js +108 -0
- package/dist/src/io/database.js.map +1 -0
- package/dist/src/io/file-readers.d.ts +54 -0
- package/dist/src/io/file-readers.d.ts.map +1 -0
- package/dist/src/io/file-readers.js +167 -0
- package/dist/src/io/file-readers.js.map +1 -0
- package/dist/src/io/file-writers.d.ts +31 -0
- package/dist/src/io/file-writers.d.ts.map +1 -0
- package/dist/src/io/file-writers.js +80 -0
- package/dist/src/io/file-writers.js.map +1 -0
- package/dist/src/io/index.d.ts +6 -0
- package/dist/src/io/index.d.ts.map +1 -0
- package/dist/src/io/index.js +24 -0
- package/dist/src/io/index.js.map +1 -0
- package/dist/src/io/s3.d.ts +50 -0
- package/dist/src/io/s3.d.ts.map +1 -0
- package/dist/src/io/s3.js +96 -0
- package/dist/src/io/s3.js.map +1 -0
- package/dist/src/listeners/builtin-listeners.d.ts +77 -0
- package/dist/src/listeners/builtin-listeners.d.ts.map +1 -0
- package/dist/src/listeners/builtin-listeners.js +108 -0
- package/dist/src/listeners/builtin-listeners.js.map +1 -0
- package/dist/src/listeners/index.d.ts +8 -0
- package/dist/src/listeners/index.d.ts.map +1 -0
- package/dist/src/listeners/index.js +25 -0
- package/dist/src/listeners/index.js.map +1 -0
- package/dist/src/module/adapter-options.d.ts +39 -0
- package/dist/src/module/adapter-options.d.ts.map +1 -0
- package/dist/src/module/adapter-options.js +34 -0
- package/dist/src/module/adapter-options.js.map +1 -0
- package/dist/src/module/adapter.d.ts +157 -0
- package/dist/src/module/adapter.d.ts.map +1 -0
- package/dist/src/module/adapter.js +80 -0
- package/dist/src/module/adapter.js.map +1 -0
- package/dist/src/module/batch-schedule-registry.d.ts +110 -0
- package/dist/src/module/batch-schedule-registry.d.ts.map +1 -0
- package/dist/src/module/batch-schedule-registry.js +0 -0
- package/dist/src/module/batch-schedule-registry.js.map +1 -0
- package/dist/src/module/index.d.ts +14 -0
- package/dist/src/module/index.d.ts.map +1 -0
- package/dist/src/module/index.js +31 -0
- package/dist/src/module/index.js.map +1 -0
- package/dist/src/module/nest-batch.module.d.ts +236 -0
- package/dist/src/module/nest-batch.module.d.ts.map +1 -0
- package/dist/src/module/nest-batch.module.js +475 -0
- package/dist/src/module/nest-batch.module.js.map +1 -0
- package/dist/src/module/tokens.d.ts +83 -0
- package/dist/src/module/tokens.d.ts.map +1 -0
- package/dist/src/module/tokens.js +58 -0
- package/dist/src/module/tokens.js.map +1 -0
- package/dist/src/observability/event-types.d.ts +55 -0
- package/dist/src/observability/event-types.d.ts.map +1 -0
- package/dist/src/observability/event-types.js +36 -0
- package/dist/src/observability/event-types.js.map +1 -0
- package/dist/src/observability/exporters.d.ts +35 -0
- package/dist/src/observability/exporters.d.ts.map +1 -0
- package/dist/src/observability/exporters.js +93 -0
- package/dist/src/observability/exporters.js.map +1 -0
- package/dist/src/observability/index.d.ts +3 -0
- package/dist/src/observability/index.d.ts.map +1 -0
- package/dist/src/observability/index.js +21 -0
- package/dist/src/observability/index.js.map +1 -0
- package/dist/src/partition-helpers.d.ts +127 -0
- package/dist/src/partition-helpers.d.ts.map +1 -0
- package/dist/src/partition-helpers.js +136 -0
- package/dist/src/partition-helpers.js.map +1 -0
- package/dist/src/policies/backoff.d.ts +3 -0
- package/dist/src/policies/backoff.d.ts.map +1 -0
- package/dist/src/policies/backoff.js +34 -0
- package/dist/src/policies/backoff.js.map +1 -0
- package/dist/src/policies/index.d.ts +4 -0
- package/dist/src/policies/index.d.ts.map +1 -0
- package/dist/src/policies/index.js +22 -0
- package/dist/src/policies/index.js.map +1 -0
- package/dist/src/policies/retry-policy.d.ts +13 -0
- package/dist/src/policies/retry-policy.d.ts.map +1 -0
- package/dist/src/policies/retry-policy.js +55 -0
- package/dist/src/policies/retry-policy.js.map +1 -0
- package/dist/src/policies/skip-policy.d.ts +12 -0
- package/dist/src/policies/skip-policy.d.ts.map +1 -0
- package/dist/src/policies/skip-policy.js +44 -0
- package/dist/src/policies/skip-policy.js.map +1 -0
- package/dist/src/registry/index.d.ts +2 -0
- package/dist/src/registry/index.d.ts.map +1 -0
- package/dist/src/registry/index.js +20 -0
- package/dist/src/registry/index.js.map +1 -0
- package/dist/src/registry/job-registry.d.ts +16 -0
- package/dist/src/registry/job-registry.d.ts.map +1 -0
- package/dist/src/registry/job-registry.js +50 -0
- package/dist/src/registry/job-registry.js.map +1 -0
- package/dist/src/repository/id-generator.d.ts +18 -0
- package/dist/src/repository/id-generator.d.ts.map +1 -0
- package/dist/src/repository/id-generator.js +37 -0
- package/dist/src/repository/id-generator.js.map +1 -0
- package/dist/src/repository/in-memory/in-memory-job-repository.d.ts +49 -0
- package/dist/src/repository/in-memory/in-memory-job-repository.d.ts.map +1 -0
- package/dist/src/repository/in-memory/in-memory-job-repository.js +291 -0
- package/dist/src/repository/in-memory/in-memory-job-repository.js.map +1 -0
- package/dist/src/repository/in-memory/index.d.ts +2 -0
- package/dist/src/repository/in-memory/index.d.ts.map +1 -0
- package/dist/src/repository/in-memory/index.js +20 -0
- package/dist/src/repository/in-memory/index.js.map +1 -0
- package/dist/src/repository/index.d.ts +4 -0
- package/dist/src/repository/index.d.ts.map +1 -0
- package/dist/src/repository/index.js +22 -0
- package/dist/src/repository/index.js.map +1 -0
- package/dist/src/repository/uuid-v7.d.ts +20 -0
- package/dist/src/repository/uuid-v7.d.ts.map +1 -0
- package/dist/src/repository/uuid-v7.js +31 -0
- package/dist/src/repository/uuid-v7.js.map +1 -0
- package/dist/src/scheduling/batch-scheduled.d.ts +87 -0
- package/dist/src/scheduling/batch-scheduled.d.ts.map +1 -0
- package/dist/src/scheduling/batch-scheduled.js +170 -0
- package/dist/src/scheduling/batch-scheduled.js.map +1 -0
- package/dist/src/transaction/in-memory-transaction-manager.d.ts +16 -0
- package/dist/src/transaction/in-memory-transaction-manager.d.ts.map +1 -0
- package/dist/src/transaction/in-memory-transaction-manager.js +33 -0
- package/dist/src/transaction/in-memory-transaction-manager.js.map +1 -0
- package/dist/src/transaction/index.d.ts +2 -0
- package/dist/src/transaction/index.d.ts.map +1 -0
- package/dist/src/transaction/index.js +20 -0
- package/dist/src/transaction/index.js.map +1 -0
- package/dist/tests/contracts/index.d.ts +26 -0
- package/dist/tests/contracts/index.d.ts.map +1 -0
- package/dist/tests/contracts/index.js +37 -0
- package/dist/tests/contracts/index.js.map +1 -0
- package/dist/tests/contracts/job-repository.contract.d.ts +46 -0
- package/dist/tests/contracts/job-repository.contract.d.ts.map +1 -0
- package/dist/tests/contracts/job-repository.contract.js +644 -0
- package/dist/tests/contracts/job-repository.contract.js.map +1 -0
- package/package.json +80 -0
- package/src/adapters/in-process.adapter.ts +182 -0
- package/src/adapters/index.ts +17 -0
- package/src/builder/batch-builder.ts +32 -0
- package/src/builder/flow-builder.ts +141 -0
- package/src/builder/index.ts +4 -0
- package/src/builder/job-builder.ts +206 -0
- package/src/builder/step-builder.ts +190 -0
- package/src/compiler/builder-types.ts +27 -0
- package/src/compiler/definition-compiler.ts +325 -0
- package/src/compiler/index.ts +2 -0
- package/src/core/errors.ts +125 -0
- package/src/core/execution-context/index.ts +3 -0
- package/src/core/execution-context/json-value.ts +3 -0
- package/src/core/execution-context/serializer.ts +21 -0
- package/src/core/execution-context/validator.ts +103 -0
- package/src/core/index.ts +7 -0
- package/src/core/ir/decider-definition.ts +25 -0
- package/src/core/ir/index.ts +7 -0
- package/src/core/ir/job-definition.ts +15 -0
- package/src/core/ir/listener-definition.ts +19 -0
- package/src/core/ir/policy-config.ts +19 -0
- package/src/core/ir/refs.ts +42 -0
- package/src/core/ir/step-definition.ts +62 -0
- package/src/core/ir/transition-definition.ts +9 -0
- package/src/core/item/index.ts +1 -0
- package/src/core/item/interfaces.ts +70 -0
- package/src/core/repository/index.ts +2 -0
- package/src/core/repository/job-repository.ts +100 -0
- package/src/core/repository/types.ts +91 -0
- package/src/core/status.ts +31 -0
- package/src/core/transaction/index.ts +1 -0
- package/src/core/transaction/transaction-manager.ts +8 -0
- package/src/core/validation/definition-validator.ts +215 -0
- package/src/core/validation/index.ts +1 -0
- package/src/decorators/constants.ts +9 -0
- package/src/decorators/flow.decorator.ts +31 -0
- package/src/decorators/index.ts +7 -0
- package/src/decorators/item.decorators.ts +51 -0
- package/src/decorators/job.decorator.ts +16 -0
- package/src/decorators/listener.decorators.ts +142 -0
- package/src/decorators/step.decorator.ts +33 -0
- package/src/decorators/tasklet.decorator.ts +14 -0
- package/src/execution/batch-worker-runner.ts +142 -0
- package/src/execution/chunk-step-executor.ts +594 -0
- package/src/execution/execution-strategy.ts +115 -0
- package/src/execution/external-task-execution-strategy.ts +104 -0
- package/src/execution/in-process-execution-strategy.ts +207 -0
- package/src/execution/index.ts +13 -0
- package/src/execution/job-executor.ts +553 -0
- package/src/execution/job-explorer.ts +73 -0
- package/src/execution/job-key.ts +35 -0
- package/src/execution/job-launcher.ts +132 -0
- package/src/execution/job-operator.ts +127 -0
- package/src/execution/listener-invoker.ts +389 -0
- package/src/execution/ref-resolver.ts +64 -0
- package/src/execution/tasklet-step-executor.ts +182 -0
- package/src/explorer/batch-explorer.ts +251 -0
- package/src/explorer/index.ts +1 -0
- package/src/flow/flow-evaluator.ts +89 -0
- package/src/flow/index.ts +1 -0
- package/src/index.ts +24 -0
- package/src/io/checkpoint.ts +47 -0
- package/src/io/database.ts +114 -0
- package/src/io/file-readers.ts +191 -0
- package/src/io/file-writers.ts +99 -0
- package/src/io/index.ts +5 -0
- package/src/io/s3.ts +117 -0
- package/src/listeners/builtin-listeners.ts +151 -0
- package/src/listeners/index.ts +7 -0
- package/src/module/adapter-options.ts +38 -0
- package/src/module/adapter.ts +160 -0
- package/src/module/batch-schedule-registry.ts +0 -0
- package/src/module/index.ts +13 -0
- package/src/module/nest-batch.module.ts +674 -0
- package/src/module/tokens.ts +95 -0
- package/src/observability/event-types.ts +61 -0
- package/src/observability/exporters.ts +96 -0
- package/src/observability/index.ts +2 -0
- package/src/partition-helpers.ts +204 -0
- package/src/policies/backoff.ts +22 -0
- package/src/policies/index.ts +3 -0
- package/src/policies/retry-policy.ts +57 -0
- package/src/policies/skip-policy.ts +51 -0
- package/src/registry/index.ts +1 -0
- package/src/registry/job-registry.ts +42 -0
- package/src/repository/id-generator.ts +25 -0
- package/src/repository/in-memory/in-memory-job-repository.ts +334 -0
- package/src/repository/in-memory/index.ts +1 -0
- package/src/repository/index.ts +3 -0
- package/src/repository/uuid-v7.ts +40 -0
- package/src/scheduling/batch-scheduled.ts +257 -0
- package/src/transaction/in-memory-transaction-manager.ts +23 -0
- package/src/transaction/index.ts +1 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export enum RefKind {
|
|
2
|
+
ProviderToken = 'provider-token',
|
|
3
|
+
BuilderLambda = 'builder-lambda',
|
|
4
|
+
Method = 'method',
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface ReaderRef {
|
|
8
|
+
kind: RefKind;
|
|
9
|
+
token?: string;
|
|
10
|
+
fn?: (...args: any[]) => unknown;
|
|
11
|
+
classToken?: string;
|
|
12
|
+
methodName?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ProcessorRef {
|
|
15
|
+
kind: RefKind;
|
|
16
|
+
token?: string;
|
|
17
|
+
fn?: (...args: any[]) => unknown;
|
|
18
|
+
classToken?: string;
|
|
19
|
+
methodName?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface WriterRef {
|
|
22
|
+
kind: RefKind;
|
|
23
|
+
token?: string;
|
|
24
|
+
fn?: (...args: any[]) => unknown;
|
|
25
|
+
classToken?: string;
|
|
26
|
+
methodName?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface TaskletRef {
|
|
29
|
+
kind: RefKind;
|
|
30
|
+
token?: string;
|
|
31
|
+
fn?: (...args: any[]) => unknown;
|
|
32
|
+
classToken?: string;
|
|
33
|
+
methodName?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ListenerRef {
|
|
36
|
+
kind: RefKind;
|
|
37
|
+
token?: string;
|
|
38
|
+
fn?: (...args: any[]) => unknown;
|
|
39
|
+
classToken?: string;
|
|
40
|
+
methodName?: string;
|
|
41
|
+
}
|
|
42
|
+
export type ItemListenerRef = ListenerRef;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ReaderRef, ProcessorRef, WriterRef, TaskletRef, ItemListenerRef } from './refs';
|
|
2
|
+
import type { SkipPolicyConfig, RetryPolicyConfig } from './policy-config';
|
|
3
|
+
|
|
4
|
+
export type StepDefinition = ChunkStepDefinition | TaskletStepDefinition;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* v1 partition configuration for a chunk step. Pinned by
|
|
8
|
+
* `docs/RELEASE-0.2.0.md §6.1` and the T-AC-3 acceptance test.
|
|
9
|
+
*
|
|
10
|
+
* - `count` is the number of partitions. `count === 1` (or the
|
|
11
|
+
* field being absent) preserves the 0.1.0 "one job per step"
|
|
12
|
+
* behaviour. `count >= 2` activates the partition-aware runtime:
|
|
13
|
+
* the transport enqueues `count` jobs, each with a distinct
|
|
14
|
+
* `partitionIndex`, and the worker body offsets the chunk loop
|
|
15
|
+
* by the partition's range.
|
|
16
|
+
* - `range` is an optional half-open `[from, to]` resolver. When
|
|
17
|
+
* omitted, the runtime treats each partition as "reads from the
|
|
18
|
+
* start" (the host's reader is responsible for not
|
|
19
|
+
* double-processing). When provided, the chunk executor bounds
|
|
20
|
+
* its read loop to `to - from` items.
|
|
21
|
+
*/
|
|
22
|
+
export interface ChunkPartitionConfig {
|
|
23
|
+
/** Number of partitions; must be a positive integer. */
|
|
24
|
+
readonly count: number;
|
|
25
|
+
/**
|
|
26
|
+
* Optional partition-range resolver. Given the partition index
|
|
27
|
+
* `i` and the total `n`, return a half-open `[from, to]` range
|
|
28
|
+
* that the partition consumes. The default behaviour (when
|
|
29
|
+
* omitted) is to read until EOF on every partition; hosts that
|
|
30
|
+
* want an even split should provide a closure that captures the
|
|
31
|
+
* total item count (the runtime has no generic "even split"
|
|
32
|
+
* because the total is host-known).
|
|
33
|
+
*/
|
|
34
|
+
readonly range?: (i: number, n: number) => readonly [from: number, to: number];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ChunkStepDefinition {
|
|
38
|
+
kind: 'chunk';
|
|
39
|
+
id: string;
|
|
40
|
+
chunkSize: number;
|
|
41
|
+
reader: ReaderRef;
|
|
42
|
+
processor?: ProcessorRef;
|
|
43
|
+
writer: WriterRef;
|
|
44
|
+
skipPolicy?: SkipPolicyConfig;
|
|
45
|
+
retryPolicy?: RetryPolicyConfig;
|
|
46
|
+
listeners: ItemListenerRef[];
|
|
47
|
+
/**
|
|
48
|
+
* Optional partition configuration. When absent, the step
|
|
49
|
+
* runs as a single non-partitioned unit (the 0.1.0 behaviour).
|
|
50
|
+
* When present with `count >= 2`, the transport activates
|
|
51
|
+
* partition orchestration — see `docs/RELEASE-0.2.0.md §6` and
|
|
52
|
+
* `packages/core/src/partition-helpers.ts` for the contract.
|
|
53
|
+
*/
|
|
54
|
+
readonly partitions?: ChunkPartitionConfig;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface TaskletStepDefinition {
|
|
58
|
+
kind: 'tasklet';
|
|
59
|
+
id: string;
|
|
60
|
+
tasklet: TaskletRef;
|
|
61
|
+
listeners: ItemListenerRef[];
|
|
62
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FlowExecutionStatus } from '../status';
|
|
2
|
+
|
|
3
|
+
export type FlowTransitionPattern = FlowExecutionStatus | string;
|
|
4
|
+
|
|
5
|
+
export interface TransitionDefinition {
|
|
6
|
+
fromStepId: string;
|
|
7
|
+
onStatus: FlowTransitionPattern;
|
|
8
|
+
toStepId: string | null; // null = END
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './interfaces';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { ExecutionContext, ExecutionScope } from '../repository/types';
|
|
2
|
+
|
|
3
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reads one item at a time. Returns `null` to signal EOF.
|
|
7
|
+
* For async iteration, use `AsyncIterable.read()` (not yet supported in MVP).
|
|
8
|
+
*/
|
|
9
|
+
export interface ItemReader<T = unknown> {
|
|
10
|
+
read(): Promise<T | null>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Processes one item. Returns `null`/`undefined` to filter the item out of the chunk.
|
|
15
|
+
* Throws to indicate the item should be skipped (via SkipPolicy) or retried (via RetryPolicy).
|
|
16
|
+
*/
|
|
17
|
+
export interface ItemProcessor<I = unknown, O = unknown> {
|
|
18
|
+
process(item: I): Promise<O | null | undefined>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Writes a batch of items. Called once per chunk (after processing).
|
|
23
|
+
*
|
|
24
|
+
* May return a `WriterResult` to report partial success — e.g. a
|
|
25
|
+
* `ProductWriter` that drops duplicate-SKU rows internally. Returning
|
|
26
|
+
* `void` (or `undefined`) means the writer assumed all `items` were
|
|
27
|
+
* persisted; the chunk executor then uses `items.length` as the write
|
|
28
|
+
* count and assumes no per-item skips.
|
|
29
|
+
*/
|
|
30
|
+
export interface ItemWriter<T = unknown> {
|
|
31
|
+
write(items: T[]): Promise<WriterResult | void>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface WriterResult {
|
|
35
|
+
written: number;
|
|
36
|
+
skipped: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Optional lifecycle contract for stateful chunk components.
|
|
41
|
+
*
|
|
42
|
+
* The chunk executor passes the step-scoped ExecutionContext to
|
|
43
|
+
* `open()` before the first read, calls `update()` after every committed
|
|
44
|
+
* chunk, persists the returned or mutated context, and calls `close()`
|
|
45
|
+
* before the step returns. Errors from any hook fail the step.
|
|
46
|
+
*/
|
|
47
|
+
export interface ItemStream {
|
|
48
|
+
open(context: ExecutionContext): MaybePromise<void>;
|
|
49
|
+
update(context: ExecutionContext): MaybePromise<ExecutionContext | void>;
|
|
50
|
+
close(): MaybePromise<void>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Tasklet context: lets the tasklet access the execution context for
|
|
55
|
+
* cross-chunk state.
|
|
56
|
+
*/
|
|
57
|
+
export interface TaskletContext {
|
|
58
|
+
readonly jobExecutionId: string;
|
|
59
|
+
readonly stepExecutionId: string;
|
|
60
|
+
getExecutionContext(): Promise<ExecutionContext>;
|
|
61
|
+
saveExecutionContext(ctx: ExecutionContext): Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Tasklet: a single-execution step (no chunk loop).
|
|
66
|
+
* Return value is informational; throws signal failure.
|
|
67
|
+
*/
|
|
68
|
+
export interface Tasklet {
|
|
69
|
+
execute(ctx: TaskletContext): Promise<unknown>;
|
|
70
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
JobInstance,
|
|
3
|
+
JobExecution,
|
|
4
|
+
JobExecutionPatch,
|
|
5
|
+
JobParameters,
|
|
6
|
+
StepExecution,
|
|
7
|
+
StepExecutionPatch,
|
|
8
|
+
ExecutionContext,
|
|
9
|
+
ExecutionScope,
|
|
10
|
+
JobInstanceFilter,
|
|
11
|
+
JobExecutionFilter,
|
|
12
|
+
} from './types';
|
|
13
|
+
import { UnsupportedJobRepositoryOperationError } from '../errors';
|
|
14
|
+
|
|
15
|
+
export interface IJobRepository {
|
|
16
|
+
getOrCreateJobInstance(name: string, jobKey: string): Promise<JobInstance>;
|
|
17
|
+
createJobExecution(jobInstanceId: string, params: JobParameters): Promise<JobExecution>;
|
|
18
|
+
/**
|
|
19
|
+
* Atomically: ensure a `JobInstance` for `(name, jobKey)` exists, lock
|
|
20
|
+
* the instance row (skipping if another concurrent launch already
|
|
21
|
+
* holds the lock), verify no running execution, and create a new
|
|
22
|
+
* execution in STARTING state. The PostgreSQL implementation uses
|
|
23
|
+
* `INSERT ... ON CONFLICT DO NOTHING` + `SELECT ... FOR UPDATE SKIP
|
|
24
|
+
* LOCKED` inside a single transaction. The in-memory implementation
|
|
25
|
+
* uses an in-process mutex (Node is single-threaded so the lock is
|
|
26
|
+
* effectively a serialization point rather than a true blocker).
|
|
27
|
+
*
|
|
28
|
+
* Throws `JobExecutionAlreadyRunningError` if another launch is in
|
|
29
|
+
* progress (FOR UPDATE returned no row) or if an execution is already
|
|
30
|
+
* STARTING/STARTED for this instance.
|
|
31
|
+
*/
|
|
32
|
+
createExecutionAtomic(
|
|
33
|
+
name: string,
|
|
34
|
+
jobKey: string,
|
|
35
|
+
params: JobParameters,
|
|
36
|
+
): Promise<JobExecution>;
|
|
37
|
+
updateJobExecution(executionId: string, patch: JobExecutionPatch): Promise<void>;
|
|
38
|
+
getJobExecution(executionId: string): Promise<JobExecution | null>;
|
|
39
|
+
getJobInstance(jobInstanceId: string): Promise<JobInstance | null>;
|
|
40
|
+
findJobInstances(filter?: JobInstanceFilter): Promise<JobInstance[]>;
|
|
41
|
+
findJobExecutions(filter?: JobExecutionFilter): Promise<JobExecution[]>;
|
|
42
|
+
getRunningJobExecution(jobInstanceId: string): Promise<JobExecution | null>;
|
|
43
|
+
createStepExecution(jobExecutionId: string, stepName: string): Promise<StepExecution>;
|
|
44
|
+
updateStepExecution(stepExecutionId: string, patch: StepExecutionPatch): Promise<void>;
|
|
45
|
+
getStepExecution(stepExecutionId: string): Promise<StepExecution | null>;
|
|
46
|
+
findStepExecutions(jobExecutionId: string): Promise<StepExecution[]>;
|
|
47
|
+
getExecutionContext(scope: ExecutionScope): Promise<ExecutionContext>;
|
|
48
|
+
saveExecutionContext(
|
|
49
|
+
scope: ExecutionScope,
|
|
50
|
+
ctx: ExecutionContext,
|
|
51
|
+
version?: number,
|
|
52
|
+
): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Find the most recently created StepExecution for a given
|
|
55
|
+
* (jobExecutionId, stepName) pair regardless of status. Returns `null`
|
|
56
|
+
* if no matching step execution exists. Used by the restart path to
|
|
57
|
+
* locate the prior (typically FAILED) step execution so its execution
|
|
58
|
+
* context — which holds the last-committed-chunk checkpoint — can be
|
|
59
|
+
* loaded.
|
|
60
|
+
*/
|
|
61
|
+
findLatestStepExecution(jobExecutionId: string, stepName: string): Promise<StepExecution | null>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export abstract class JobRepository implements IJobRepository {
|
|
65
|
+
abstract getOrCreateJobInstance(name: string, jobKey: string): Promise<JobInstance>;
|
|
66
|
+
abstract createJobExecution(jobInstanceId: string, params: JobParameters): Promise<JobExecution>;
|
|
67
|
+
abstract createExecutionAtomic(
|
|
68
|
+
name: string,
|
|
69
|
+
jobKey: string,
|
|
70
|
+
params: JobParameters,
|
|
71
|
+
): Promise<JobExecution>;
|
|
72
|
+
abstract updateJobExecution(executionId: string, patch: JobExecutionPatch): Promise<void>;
|
|
73
|
+
abstract getJobExecution(executionId: string): Promise<JobExecution | null>;
|
|
74
|
+
getJobInstance(_jobInstanceId: string): Promise<JobInstance | null> {
|
|
75
|
+
throw new UnsupportedJobRepositoryOperationError('getJobInstance');
|
|
76
|
+
}
|
|
77
|
+
findJobInstances(_filter: JobInstanceFilter = {}): Promise<JobInstance[]> {
|
|
78
|
+
throw new UnsupportedJobRepositoryOperationError('findJobInstances');
|
|
79
|
+
}
|
|
80
|
+
findJobExecutions(_filter: JobExecutionFilter = {}): Promise<JobExecution[]> {
|
|
81
|
+
throw new UnsupportedJobRepositoryOperationError('findJobExecutions');
|
|
82
|
+
}
|
|
83
|
+
abstract getRunningJobExecution(jobInstanceId: string): Promise<JobExecution | null>;
|
|
84
|
+
abstract createStepExecution(jobExecutionId: string, stepName: string): Promise<StepExecution>;
|
|
85
|
+
abstract updateStepExecution(stepExecutionId: string, patch: StepExecutionPatch): Promise<void>;
|
|
86
|
+
abstract getStepExecution(stepExecutionId: string): Promise<StepExecution | null>;
|
|
87
|
+
findStepExecutions(_jobExecutionId: string): Promise<StepExecution[]> {
|
|
88
|
+
throw new UnsupportedJobRepositoryOperationError('findStepExecutions');
|
|
89
|
+
}
|
|
90
|
+
abstract getExecutionContext(scope: ExecutionScope): Promise<ExecutionContext>;
|
|
91
|
+
abstract saveExecutionContext(
|
|
92
|
+
scope: ExecutionScope,
|
|
93
|
+
ctx: ExecutionContext,
|
|
94
|
+
version?: number,
|
|
95
|
+
): Promise<void>;
|
|
96
|
+
abstract findLatestStepExecution(
|
|
97
|
+
jobExecutionId: string,
|
|
98
|
+
stepName: string,
|
|
99
|
+
): Promise<StepExecution | null>;
|
|
100
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { JobStatus, StepStatus } from '../status';
|
|
2
|
+
import type { JsonValue } from '../execution-context/json-value';
|
|
3
|
+
|
|
4
|
+
export interface JobInstance {
|
|
5
|
+
id: string;
|
|
6
|
+
jobName: string;
|
|
7
|
+
jobKey: string;
|
|
8
|
+
createdAt: Date;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface JobExecutionPatch {
|
|
12
|
+
status?: JobStatus;
|
|
13
|
+
startTime?: Date | null;
|
|
14
|
+
endTime?: Date | null;
|
|
15
|
+
exitCode?: string;
|
|
16
|
+
exitMessage?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface JobExecution {
|
|
20
|
+
id: string;
|
|
21
|
+
jobInstanceId: string;
|
|
22
|
+
status: JobStatus;
|
|
23
|
+
startTime: Date | null;
|
|
24
|
+
endTime: Date | null;
|
|
25
|
+
exitCode: string;
|
|
26
|
+
exitMessage: string;
|
|
27
|
+
params: JobParameters;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface StepExecutionPatch {
|
|
31
|
+
status?: StepStatus;
|
|
32
|
+
readCount?: number;
|
|
33
|
+
writeCount?: number;
|
|
34
|
+
skipCount?: number;
|
|
35
|
+
rollbackCount?: number;
|
|
36
|
+
commitCount?: number;
|
|
37
|
+
startTime?: Date | null;
|
|
38
|
+
endTime?: Date | null;
|
|
39
|
+
exitCode?: string;
|
|
40
|
+
exitMessage?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface StepExecution {
|
|
44
|
+
id: string;
|
|
45
|
+
jobExecutionId: string;
|
|
46
|
+
stepName: string;
|
|
47
|
+
status: StepStatus;
|
|
48
|
+
readCount: number;
|
|
49
|
+
writeCount: number;
|
|
50
|
+
skipCount: number;
|
|
51
|
+
rollbackCount: number;
|
|
52
|
+
commitCount: number;
|
|
53
|
+
startTime: Date | null;
|
|
54
|
+
endTime: Date | null;
|
|
55
|
+
exitCode: string;
|
|
56
|
+
exitMessage: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ExecutionContext {
|
|
60
|
+
data: JsonValue;
|
|
61
|
+
version: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type ExecutionScope = { jobExecutionId: string } | { stepExecutionId: string };
|
|
65
|
+
|
|
66
|
+
export type JobParameters = Record<string, JsonValue>;
|
|
67
|
+
|
|
68
|
+
export interface JobInstanceFilter {
|
|
69
|
+
jobName?: string;
|
|
70
|
+
jobKey?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface JobExecutionFilter {
|
|
74
|
+
jobInstanceId?: string;
|
|
75
|
+
status?: JobStatus | readonly JobStatus[];
|
|
76
|
+
startedAfter?: Date;
|
|
77
|
+
startedBefore?: Date;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface StepExecutionContextEntry {
|
|
81
|
+
stepExecutionId: string;
|
|
82
|
+
context: ExecutionContext;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface JobExecutionDetails {
|
|
86
|
+
jobInstance: JobInstance;
|
|
87
|
+
jobExecution: JobExecution;
|
|
88
|
+
stepExecutions: StepExecution[];
|
|
89
|
+
jobContext: ExecutionContext;
|
|
90
|
+
stepContexts: StepExecutionContextEntry[];
|
|
91
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export enum FlowExecutionStatus {
|
|
2
|
+
COMPLETED = 'COMPLETED',
|
|
3
|
+
FAILED = 'FAILED',
|
|
4
|
+
STOPPED = 'STOPPED',
|
|
5
|
+
UNKNOWN = 'UNKNOWN',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export enum JobStatus {
|
|
9
|
+
STARTING = 'STARTING',
|
|
10
|
+
STARTED = 'STARTED',
|
|
11
|
+
COMPLETED = 'COMPLETED',
|
|
12
|
+
FAILED = 'FAILED',
|
|
13
|
+
STOPPING = 'STOPPING',
|
|
14
|
+
STOPPED = 'STOPPED',
|
|
15
|
+
ABANDONED = 'ABANDONED',
|
|
16
|
+
UNKNOWN = 'UNKNOWN',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export enum StepStatus {
|
|
20
|
+
STARTING = 'STARTING',
|
|
21
|
+
STARTED = 'STARTED',
|
|
22
|
+
COMPLETED = 'COMPLETED',
|
|
23
|
+
FAILED = 'FAILED',
|
|
24
|
+
STOPPED = 'STOPPED',
|
|
25
|
+
UNKNOWN = 'UNKNOWN',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export enum ChunkStatus {
|
|
29
|
+
PROCESSING = 'PROCESSING',
|
|
30
|
+
COMPLETED = 'COMPLETED',
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './transaction-manager';
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import {
|
|
2
|
+
JobDefinition,
|
|
3
|
+
TransitionDefinition,
|
|
4
|
+
StepDefinition,
|
|
5
|
+
} from '../ir';
|
|
6
|
+
import { InvalidFlowGraphError } from '../errors';
|
|
7
|
+
import { validatePartitions } from '../../partition-helpers';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Pure validation for a fully-built `JobDefinition` IR.
|
|
11
|
+
*
|
|
12
|
+
* Does not perform any execution, scheduling, or Nest wiring. After the
|
|
13
|
+
* Builder/Compiler/Decorator API has assembled a `JobDefinition`, the
|
|
14
|
+
* `DefinitionValidator` answers one question: "is this graph structurally
|
|
15
|
+
* sound?" — by enforcing the invariants that the runtime executor relies on.
|
|
16
|
+
*
|
|
17
|
+
* Invariants enforced (in order):
|
|
18
|
+
*
|
|
19
|
+
* 1. EMPTY_JOB — the job has at least one step.
|
|
20
|
+
* 2. NO_START_STEP — `startStepId` references an existing step.
|
|
21
|
+
* 3. INVALID_CHUNK_SIZE — every `chunk` step has `chunkSize > 0`.
|
|
22
|
+
* 4. MISSING_TARGET — every transition's `from`/`to` references a
|
|
23
|
+
* step that exists (or `toStepId === null` for END).
|
|
24
|
+
* 5. UNREACHABLE_STEP — every step is reachable from `startStepId`
|
|
25
|
+
* via transitions (BFS).
|
|
26
|
+
* 6. CYCLE_DETECTED — the transition graph has no cycles (DFS with
|
|
27
|
+
* recursion stack tracking).
|
|
28
|
+
*
|
|
29
|
+
* The order matters: cheap, local checks run first so a malformed job
|
|
30
|
+
* fails fast before we walk the whole graph.
|
|
31
|
+
*
|
|
32
|
+
* Per ORACLE verdict 1b: "all transitions target existing steps, one start
|
|
33
|
+
* step, no accidental cycles, terminal statuses are handled".
|
|
34
|
+
*/
|
|
35
|
+
export class DefinitionValidator {
|
|
36
|
+
/**
|
|
37
|
+
* Validates a complete `JobDefinition`. Throws `InvalidFlowGraphError`
|
|
38
|
+
* on the first violation found, with a stable `code` (see class doc).
|
|
39
|
+
*/
|
|
40
|
+
validate(job: JobDefinition): void {
|
|
41
|
+
const stepIds = Object.keys(job.steps);
|
|
42
|
+
|
|
43
|
+
// 1. At least one step.
|
|
44
|
+
if (stepIds.length === 0) {
|
|
45
|
+
throw new InvalidFlowGraphError(
|
|
46
|
+
'EMPTY_JOB',
|
|
47
|
+
`Job "${job.id}" has no steps`,
|
|
48
|
+
{ jobId: job.id },
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 2. startStepId must reference an existing step.
|
|
53
|
+
if (!(job.startStepId in job.steps)) {
|
|
54
|
+
throw new InvalidFlowGraphError(
|
|
55
|
+
'NO_START_STEP',
|
|
56
|
+
`Job "${job.id}" startStepId "${job.startStepId}" is not in steps`,
|
|
57
|
+
{ jobId: job.id, startStepId: job.startStepId },
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 3. Per-step invariants.
|
|
62
|
+
for (const stepId of stepIds) {
|
|
63
|
+
const step: StepDefinition = job.steps[stepId]!;
|
|
64
|
+
if (step.kind === 'chunk' && step.chunkSize <= 0) {
|
|
65
|
+
throw new InvalidFlowGraphError(
|
|
66
|
+
'INVALID_CHUNK_SIZE',
|
|
67
|
+
`Step "${stepId}" has invalid chunkSize ${step.chunkSize}`,
|
|
68
|
+
{ jobId: job.id, stepId, chunkSize: step.chunkSize },
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (step.kind === 'chunk' && step.partitions !== undefined) {
|
|
72
|
+
// Delegate the partition-config validation to the pure helper
|
|
73
|
+
// so the rule lives in exactly one place (the
|
|
74
|
+
// `partition-helpers` module). The validator's job is to
|
|
75
|
+
// surface the failure with the IR-shaped context; the
|
|
76
|
+
// helper's job is to decide whether the config is valid.
|
|
77
|
+
try {
|
|
78
|
+
validatePartitions(step.partitions);
|
|
79
|
+
} catch (err) {
|
|
80
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
81
|
+
throw new InvalidFlowGraphError(
|
|
82
|
+
'INVALID_PARTITIONS',
|
|
83
|
+
`Step "${stepId}" has invalid partitions: ${message}`,
|
|
84
|
+
{ jobId: job.id, stepId, partitions: step.partitions },
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 4. Every transition's endpoints must exist.
|
|
91
|
+
for (const t of job.transitions) {
|
|
92
|
+
if (!(t.fromStepId in job.steps)) {
|
|
93
|
+
throw new InvalidFlowGraphError(
|
|
94
|
+
'MISSING_TARGET',
|
|
95
|
+
`Transition fromStepId "${t.fromStepId}" not found in steps`,
|
|
96
|
+
{ jobId: job.id, fromStepId: t.fromStepId },
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (t.toStepId !== null && !(t.toStepId in job.steps)) {
|
|
100
|
+
throw new InvalidFlowGraphError(
|
|
101
|
+
'MISSING_TARGET',
|
|
102
|
+
`Transition toStepId "${t.toStepId}" not found in steps`,
|
|
103
|
+
{ jobId: job.id, toStepId: t.toStepId },
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const deciderStepIds = new Set<string>();
|
|
109
|
+
for (const d of job.deciders ?? []) {
|
|
110
|
+
if (!(d.afterStepId in job.steps)) {
|
|
111
|
+
throw new InvalidFlowGraphError(
|
|
112
|
+
'MISSING_TARGET',
|
|
113
|
+
`Decider afterStepId "${d.afterStepId}" not found in steps`,
|
|
114
|
+
{ jobId: job.id, afterStepId: d.afterStepId },
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
if (deciderStepIds.has(d.afterStepId)) {
|
|
118
|
+
throw new InvalidFlowGraphError(
|
|
119
|
+
'DUPLICATE_DECIDER',
|
|
120
|
+
`Step "${d.afterStepId}" has multiple deciders`,
|
|
121
|
+
{ jobId: job.id, afterStepId: d.afterStepId },
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
deciderStepIds.add(d.afterStepId);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 5. No unreachable steps (BFS from startStepId).
|
|
128
|
+
const reachable = this.collectReachable(job);
|
|
129
|
+
|
|
130
|
+
for (const stepId of stepIds) {
|
|
131
|
+
if (!reachable.has(stepId)) {
|
|
132
|
+
throw new InvalidFlowGraphError(
|
|
133
|
+
'UNREACHABLE_STEP',
|
|
134
|
+
`Step "${stepId}" is unreachable from startStepId "${job.startStepId}"`,
|
|
135
|
+
{ jobId: job.id, stepId, startStepId: job.startStepId },
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 6. No cycles (DFS with stack tracking).
|
|
141
|
+
this.assertAcyclic(job);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Lightweight, partial validation used by `FlowEvaluator` and the
|
|
146
|
+
* `Builder` API when only a subset of steps/transitions is in scope.
|
|
147
|
+
*
|
|
148
|
+
* Mirrors rule 4 of `validate()` (transition endpoints must exist) but
|
|
149
|
+
* does NOT enforce reachability, cycles, or the start step — those
|
|
150
|
+
* require the full `JobDefinition` graph.
|
|
151
|
+
*/
|
|
152
|
+
validateTransition(
|
|
153
|
+
transitions: TransitionDefinition[],
|
|
154
|
+
availableSteps: Record<string, StepDefinition>,
|
|
155
|
+
): void {
|
|
156
|
+
for (const t of transitions) {
|
|
157
|
+
if (!(t.fromStepId in availableSteps)) {
|
|
158
|
+
throw new InvalidFlowGraphError(
|
|
159
|
+
'MISSING_TARGET',
|
|
160
|
+
`Transition fromStepId "${t.fromStepId}" not in steps`,
|
|
161
|
+
{ fromStepId: t.fromStepId },
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
if (t.toStepId !== null && !(t.toStepId in availableSteps)) {
|
|
165
|
+
throw new InvalidFlowGraphError(
|
|
166
|
+
'MISSING_TARGET',
|
|
167
|
+
`Transition toStepId "${t.toStepId}" not in steps`,
|
|
168
|
+
{ toStepId: t.toStepId },
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// --- private helpers --------------------------------------------------
|
|
175
|
+
|
|
176
|
+
private collectReachable(job: JobDefinition): Set<string> {
|
|
177
|
+
const reachable = new Set<string>();
|
|
178
|
+
const queue: string[] = [job.startStepId];
|
|
179
|
+
while (queue.length > 0) {
|
|
180
|
+
const cur = queue.shift()!;
|
|
181
|
+
if (reachable.has(cur)) continue;
|
|
182
|
+
reachable.add(cur);
|
|
183
|
+
for (const t of job.transitions) {
|
|
184
|
+
if (t.fromStepId === cur && t.toStepId !== null && !reachable.has(t.toStepId)) {
|
|
185
|
+
queue.push(t.toStepId);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return reachable;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private assertAcyclic(job: JobDefinition): void {
|
|
193
|
+
const visited = new Set<string>();
|
|
194
|
+
const inStack = new Set<string>();
|
|
195
|
+
const detectCycle = (stepId: string, path: readonly string[]): void => {
|
|
196
|
+
if (inStack.has(stepId)) {
|
|
197
|
+
throw new InvalidFlowGraphError(
|
|
198
|
+
'CYCLE_DETECTED',
|
|
199
|
+
`Cycle detected in job "${job.id}": ${[...path, stepId].join(' -> ')}`,
|
|
200
|
+
{ jobId: job.id, path: [...path, stepId] },
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
if (visited.has(stepId)) return;
|
|
204
|
+
visited.add(stepId);
|
|
205
|
+
inStack.add(stepId);
|
|
206
|
+
for (const t of job.transitions) {
|
|
207
|
+
if (t.fromStepId === stepId && t.toStepId !== null) {
|
|
208
|
+
detectCycle(t.toStepId, [...path, stepId]);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
inStack.delete(stepId);
|
|
212
|
+
};
|
|
213
|
+
detectCycle(job.startStepId, []);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './definition-validator';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const BATCH_JOB_METADATA = 'nest-batch:job';
|
|
2
|
+
export const BATCH_STEP_METADATA = 'nest-batch:step';
|
|
3
|
+
export const BATCH_TASKLET_METADATA = 'nest-batch:tasklet';
|
|
4
|
+
export const BATCH_ITEM_READER_METADATA = 'nest-batch:item-reader';
|
|
5
|
+
export const BATCH_ITEM_PROCESSOR_METADATA = 'nest-batch:item-processor';
|
|
6
|
+
export const BATCH_ITEM_WRITER_METADATA = 'nest-batch:item-writer';
|
|
7
|
+
export const BATCH_LISTENER_METADATA = 'nest-batch:listener';
|
|
8
|
+
export const BATCH_TRANSITION_METADATA = 'nest-batch:transition';
|
|
9
|
+
export const BATCH_SCHEDULED_OPTIONS = 'nest-batch:scheduled';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { BATCH_TRANSITION_METADATA } from './constants';
|
|
3
|
+
import type { FlowExecutionStatus } from '../core/status';
|
|
4
|
+
|
|
5
|
+
export interface OnTransitionOptions {
|
|
6
|
+
fromStep: string;
|
|
7
|
+
onStatus: FlowExecutionStatus | string; // string allowed for enum name lookup
|
|
8
|
+
toStep: string | null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Declarative flow transition. The decorated method is a marker; the
|
|
13
|
+
* compiler reads its metadata to build a `TransitionDefinition`.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```typescript
|
|
17
|
+
* @Jobable({ id: 'my-job' })
|
|
18
|
+
* class MyJob {
|
|
19
|
+
* @Stepable({ id: 'step1' }) @Tasklet() async step1() {}
|
|
20
|
+
* @Stepable({ id: 'recovery' }) @Tasklet() async recovery() {}
|
|
21
|
+
*
|
|
22
|
+
* @OnTransition({ fromStep: 'step1', onStatus: 'FAILED', toStep: 'recovery' })
|
|
23
|
+
* onFail() {}
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function OnTransition(options: OnTransitionOptions): MethodDecorator {
|
|
28
|
+
return (target: object, propertyKey: string | symbol, _descriptor: PropertyDescriptor) => {
|
|
29
|
+
Reflect.defineMetadata(BATCH_TRANSITION_METADATA, options, target, propertyKey);
|
|
30
|
+
};
|
|
31
|
+
}
|