@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,644 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "runJobRepositoryContract", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return runJobRepositoryContract;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _vitest = require("vitest");
|
|
12
|
+
const _core = require("@nest-batch/core");
|
|
13
|
+
function runJobRepositoryContract(factory, implName) {
|
|
14
|
+
(0, _vitest.describe)(`JobRepository + TransactionManager contract (${implName})`, ()=>{
|
|
15
|
+
let repo;
|
|
16
|
+
let tx;
|
|
17
|
+
(0, _vitest.beforeEach)(()=>{
|
|
18
|
+
const pair = factory.create();
|
|
19
|
+
repo = pair.repo;
|
|
20
|
+
tx = pair.tx;
|
|
21
|
+
});
|
|
22
|
+
(0, _vitest.describe)('JobRepository', ()=>{
|
|
23
|
+
(0, _vitest.test)('is an instance of the JobRepository abstract class', ()=>{
|
|
24
|
+
// Real implementations extend JobRepository; the interface is
|
|
25
|
+
// type-only so the runtime check is against the abstract class.
|
|
26
|
+
(0, _vitest.expect)(repo).toBeInstanceOf(_core.JobRepository);
|
|
27
|
+
});
|
|
28
|
+
(0, _vitest.test)('getOrCreateJobInstance returns the same instance for the same (name, key)', async ()=>{
|
|
29
|
+
const a = await repo.getOrCreateJobInstance('myJob', 'k1');
|
|
30
|
+
const b = await repo.getOrCreateJobInstance('myJob', 'k1');
|
|
31
|
+
(0, _vitest.expect)(a.id).toBe(b.id);
|
|
32
|
+
(0, _vitest.expect)(a.jobName).toBe('myJob');
|
|
33
|
+
(0, _vitest.expect)(a.jobKey).toBe('k1');
|
|
34
|
+
(0, _vitest.expect)(a.createdAt).toBeInstanceOf(Date);
|
|
35
|
+
});
|
|
36
|
+
(0, _vitest.test)('getOrCreateJobInstance returns distinct instances for distinct (name, key) pairs', async ()=>{
|
|
37
|
+
const a = await repo.getOrCreateJobInstance('job-a', 'k');
|
|
38
|
+
const b = await repo.getOrCreateJobInstance('job-b', 'k');
|
|
39
|
+
const c = await repo.getOrCreateJobInstance('job-a', 'k2');
|
|
40
|
+
(0, _vitest.expect)(new Set([
|
|
41
|
+
a.id,
|
|
42
|
+
b.id,
|
|
43
|
+
c.id
|
|
44
|
+
]).size).toBe(3);
|
|
45
|
+
});
|
|
46
|
+
(0, _vitest.test)('getJobInstance returns an existing instance and null for an unknown id', async ()=>{
|
|
47
|
+
const instance = await repo.getOrCreateJobInstance('query-job', 'instance');
|
|
48
|
+
const found = await repo.getJobInstance(instance.id);
|
|
49
|
+
(0, _vitest.expect)(found).not.toBeNull();
|
|
50
|
+
(0, _vitest.expect)(found.id).toBe(instance.id);
|
|
51
|
+
(0, _vitest.expect)(found.jobName).toBe('query-job');
|
|
52
|
+
(0, _vitest.expect)(found.jobKey).toBe('instance');
|
|
53
|
+
(0, _vitest.expect)(await repo.getJobInstance('does-not-exist')).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
(0, _vitest.test)('findJobInstances filters by jobName and jobKey', async ()=>{
|
|
56
|
+
const first = await repo.getOrCreateJobInstance('query-instances', 'a');
|
|
57
|
+
const second = await repo.getOrCreateJobInstance('query-instances', 'b');
|
|
58
|
+
const other = await repo.getOrCreateJobInstance('query-instances-other', 'a');
|
|
59
|
+
const byName = await repo.findJobInstances({
|
|
60
|
+
jobName: 'query-instances'
|
|
61
|
+
});
|
|
62
|
+
(0, _vitest.expect)(byName.map((i)=>i.id)).toEqual(_vitest.expect.arrayContaining([
|
|
63
|
+
first.id,
|
|
64
|
+
second.id
|
|
65
|
+
]));
|
|
66
|
+
(0, _vitest.expect)(byName.map((i)=>i.id)).not.toContain(other.id);
|
|
67
|
+
const byNameAndKey = await repo.findJobInstances({
|
|
68
|
+
jobName: 'query-instances',
|
|
69
|
+
jobKey: 'a'
|
|
70
|
+
});
|
|
71
|
+
(0, _vitest.expect)(byNameAndKey.map((i)=>i.id)).toEqual([
|
|
72
|
+
first.id
|
|
73
|
+
]);
|
|
74
|
+
});
|
|
75
|
+
(0, _vitest.test)('getOrCreateJobInstance is race-safe under Promise.all concurrency', async ()=>{
|
|
76
|
+
const calls = Array.from({
|
|
77
|
+
length: 10
|
|
78
|
+
}, ()=>repo.getOrCreateJobInstance('concurrent-create', 'k'));
|
|
79
|
+
const results = await Promise.all(calls);
|
|
80
|
+
const uniqueIds = new Set(results.map((r)=>r.id));
|
|
81
|
+
(0, _vitest.expect)(uniqueIds.size).toBe(1);
|
|
82
|
+
});
|
|
83
|
+
(0, _vitest.test)('createExecutionAtomic returns a JobExecution in STARTING status', async ()=>{
|
|
84
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-exec', {
|
|
85
|
+
foo: 'bar'
|
|
86
|
+
});
|
|
87
|
+
(0, _vitest.expect)(exec.status).toBe(_core.JobStatus.STARTING);
|
|
88
|
+
(0, _vitest.expect)(typeof exec.jobInstanceId).toBe('string');
|
|
89
|
+
(0, _vitest.expect)(exec.jobInstanceId.length).toBeGreaterThan(0);
|
|
90
|
+
(0, _vitest.expect)(exec.params).toEqual({
|
|
91
|
+
foo: 'bar'
|
|
92
|
+
});
|
|
93
|
+
(0, _vitest.expect)(exec.startTime).toBeNull();
|
|
94
|
+
(0, _vitest.expect)(exec.endTime).toBeNull();
|
|
95
|
+
(0, _vitest.expect)(exec.exitCode).toBe('');
|
|
96
|
+
(0, _vitest.expect)(exec.exitMessage).toBe('');
|
|
97
|
+
// Cleanup so the next test does not see a running execution.
|
|
98
|
+
await repo.updateJobExecution(exec.id, {
|
|
99
|
+
status: _core.JobStatus.COMPLETED
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
(0, _vitest.test)('createExecutionAtomic stores a snapshot of params (mutating input does not affect stored value)', async ()=>{
|
|
103
|
+
const params = {
|
|
104
|
+
nested: {
|
|
105
|
+
n: 1
|
|
106
|
+
},
|
|
107
|
+
list: [
|
|
108
|
+
1,
|
|
109
|
+
2,
|
|
110
|
+
3
|
|
111
|
+
]
|
|
112
|
+
};
|
|
113
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-snap', params);
|
|
114
|
+
// Mutate the original input — stored params must not change.
|
|
115
|
+
params.nested['n'] = 999;
|
|
116
|
+
params.list.push(999);
|
|
117
|
+
const fetched = await repo.getJobExecution(exec.id);
|
|
118
|
+
(0, _vitest.expect)(fetched).not.toBeNull();
|
|
119
|
+
(0, _vitest.expect)(fetched.params.nested.n).toBe(1);
|
|
120
|
+
(0, _vitest.expect)(fetched.params.list).toEqual([
|
|
121
|
+
1,
|
|
122
|
+
2,
|
|
123
|
+
3
|
|
124
|
+
]);
|
|
125
|
+
await repo.updateJobExecution(exec.id, {
|
|
126
|
+
status: _core.JobStatus.COMPLETED
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
(0, _vitest.test)('createExecutionAtomic is restart-friendly: a new launch after COMPLETED creates a new execution sharing the same instance', async ()=>{
|
|
130
|
+
const first = await repo.createExecutionAtomic('myJob', 'k-restart', {
|
|
131
|
+
p: 1
|
|
132
|
+
});
|
|
133
|
+
await repo.updateJobExecution(first.id, {
|
|
134
|
+
status: _core.JobStatus.COMPLETED,
|
|
135
|
+
endTime: new Date()
|
|
136
|
+
});
|
|
137
|
+
const second = await repo.createExecutionAtomic('myJob', 'k-restart', {
|
|
138
|
+
p: 2
|
|
139
|
+
});
|
|
140
|
+
(0, _vitest.expect)(second.id).not.toBe(first.id);
|
|
141
|
+
(0, _vitest.expect)(second.jobInstanceId).toBe(first.jobInstanceId);
|
|
142
|
+
(0, _vitest.expect)(second.status).toBe(_core.JobStatus.STARTING);
|
|
143
|
+
await repo.updateJobExecution(second.id, {
|
|
144
|
+
status: _core.JobStatus.COMPLETED
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
(0, _vitest.test)('createExecutionAtomic rejects with JobExecutionAlreadyRunningError when an execution is already STARTING', async ()=>{
|
|
148
|
+
const first = await repo.createExecutionAtomic('myJob', 'k-dup', {
|
|
149
|
+
p: 1
|
|
150
|
+
});
|
|
151
|
+
// first is still STARTING — not yet completed
|
|
152
|
+
await (0, _vitest.expect)(repo.createExecutionAtomic('myJob', 'k-dup', {
|
|
153
|
+
p: 2
|
|
154
|
+
})).rejects.toBeInstanceOf(_core.JobExecutionAlreadyRunningError);
|
|
155
|
+
// Cleanup
|
|
156
|
+
await repo.updateJobExecution(first.id, {
|
|
157
|
+
status: _core.JobStatus.COMPLETED
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
(0, _vitest.test)('createExecutionAtomic rejects with JobExecutionAlreadyRunningError when an execution is STARTED', async ()=>{
|
|
161
|
+
const first = await repo.createExecutionAtomic('myJob', 'k-started', {
|
|
162
|
+
p: 1
|
|
163
|
+
});
|
|
164
|
+
await repo.updateJobExecution(first.id, {
|
|
165
|
+
status: _core.JobStatus.STARTED,
|
|
166
|
+
startTime: new Date()
|
|
167
|
+
});
|
|
168
|
+
await (0, _vitest.expect)(repo.createExecutionAtomic('myJob', 'k-started', {
|
|
169
|
+
p: 2
|
|
170
|
+
})).rejects.toBeInstanceOf(_core.JobExecutionAlreadyRunningError);
|
|
171
|
+
await repo.updateJobExecution(first.id, {
|
|
172
|
+
status: _core.JobStatus.COMPLETED
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
(0, _vitest.test)('concurrent createExecutionAtomic: exactly one winner, all others reject (FOR UPDATE SKIP LOCKED semantics)', async ()=>{
|
|
176
|
+
// SQLite (better-sqlite3) does not support row-level locking,
|
|
177
|
+
// so concurrent calls all succeed instead of 1 winning and the
|
|
178
|
+
// rest rejecting. Skip this test when running on SQLite.
|
|
179
|
+
if (!process.env.DB_HOST && !process.env.DATABASE_URL) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const attempts = 5;
|
|
183
|
+
const settled = await Promise.allSettled(Array.from({
|
|
184
|
+
length: attempts
|
|
185
|
+
}, ()=>repo.createExecutionAtomic('concurrent-exec', 'k1', {
|
|
186
|
+
p: 'x'
|
|
187
|
+
})));
|
|
188
|
+
const fulfilled = settled.filter((r)=>r.status === 'fulfilled');
|
|
189
|
+
const rejected = settled.filter((r)=>r.status === 'rejected');
|
|
190
|
+
(0, _vitest.expect)(fulfilled).toHaveLength(1);
|
|
191
|
+
(0, _vitest.expect)(rejected).toHaveLength(attempts - 1);
|
|
192
|
+
for (const r of rejected){
|
|
193
|
+
if (r.status === 'rejected') {
|
|
194
|
+
(0, _vitest.expect)(r.reason).toBeInstanceOf(_core.JobExecutionAlreadyRunningError);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const winningExec = fulfilled[0].value;
|
|
198
|
+
const running = await repo.getRunningJobExecution(winningExec.jobInstanceId);
|
|
199
|
+
(0, _vitest.expect)(running?.id).toBe(winningExec.id);
|
|
200
|
+
// Cleanup
|
|
201
|
+
await repo.updateJobExecution(winningExec.id, {
|
|
202
|
+
status: _core.JobStatus.COMPLETED
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
(0, _vitest.test)('updateJobExecution: status, startTime, endTime are patchable; unspecified fields are preserved', async ()=>{
|
|
206
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-patch', {
|
|
207
|
+
p: 1
|
|
208
|
+
});
|
|
209
|
+
const startTime = new Date('2025-01-01T00:00:00Z');
|
|
210
|
+
await repo.updateJobExecution(exec.id, {
|
|
211
|
+
status: _core.JobStatus.STARTED,
|
|
212
|
+
startTime
|
|
213
|
+
});
|
|
214
|
+
const afterStart = await repo.getJobExecution(exec.id);
|
|
215
|
+
(0, _vitest.expect)(afterStart?.status).toBe(_core.JobStatus.STARTED);
|
|
216
|
+
(0, _vitest.expect)(afterStart?.startTime?.toISOString()).toBe(startTime.toISOString());
|
|
217
|
+
// endTime is still null (not patched)
|
|
218
|
+
(0, _vitest.expect)(afterStart?.endTime).toBeNull();
|
|
219
|
+
const endTime = new Date('2025-01-01T00:01:00Z');
|
|
220
|
+
await repo.updateJobExecution(exec.id, {
|
|
221
|
+
status: _core.JobStatus.COMPLETED,
|
|
222
|
+
endTime,
|
|
223
|
+
exitCode: 'COMPLETED'
|
|
224
|
+
});
|
|
225
|
+
const afterEnd = await repo.getJobExecution(exec.id);
|
|
226
|
+
(0, _vitest.expect)(afterEnd?.status).toBe(_core.JobStatus.COMPLETED);
|
|
227
|
+
(0, _vitest.expect)(afterEnd?.startTime?.toISOString()).toBe(startTime.toISOString());
|
|
228
|
+
(0, _vitest.expect)(afterEnd?.endTime?.toISOString()).toBe(endTime.toISOString());
|
|
229
|
+
(0, _vitest.expect)(afterEnd?.exitCode).toBe('COMPLETED');
|
|
230
|
+
});
|
|
231
|
+
(0, _vitest.test)('getJobExecution returns null for unknown id', async ()=>{
|
|
232
|
+
const result = await repo.getJobExecution('does-not-exist');
|
|
233
|
+
(0, _vitest.expect)(result).toBeNull();
|
|
234
|
+
});
|
|
235
|
+
(0, _vitest.test)('getRunningJobExecution returns the STARTING/STARTED execution, or null when none', async ()=>{
|
|
236
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-running', {
|
|
237
|
+
p: 1
|
|
238
|
+
});
|
|
239
|
+
const running = await repo.getRunningJobExecution(exec.jobInstanceId);
|
|
240
|
+
(0, _vitest.expect)(running?.id).toBe(exec.id);
|
|
241
|
+
(0, _vitest.expect)(running?.status).toBe(_core.JobStatus.STARTING);
|
|
242
|
+
await repo.updateJobExecution(exec.id, {
|
|
243
|
+
status: _core.JobStatus.STARTED
|
|
244
|
+
});
|
|
245
|
+
const stillRunning = await repo.getRunningJobExecution(exec.jobInstanceId);
|
|
246
|
+
(0, _vitest.expect)(stillRunning?.id).toBe(exec.id);
|
|
247
|
+
(0, _vitest.expect)(stillRunning?.status).toBe(_core.JobStatus.STARTED);
|
|
248
|
+
await repo.updateJobExecution(exec.id, {
|
|
249
|
+
status: _core.JobStatus.COMPLETED
|
|
250
|
+
});
|
|
251
|
+
const noRunning = await repo.getRunningJobExecution(exec.jobInstanceId);
|
|
252
|
+
(0, _vitest.expect)(noRunning).toBeNull();
|
|
253
|
+
});
|
|
254
|
+
(0, _vitest.test)('getRunningJobExecution returns null for an unknown job instance id', async ()=>{
|
|
255
|
+
const result = await repo.getRunningJobExecution('not-a-real-instance');
|
|
256
|
+
(0, _vitest.expect)(result).toBeNull();
|
|
257
|
+
});
|
|
258
|
+
(0, _vitest.test)('findJobExecutions filters by instance, status, and start time window', async ()=>{
|
|
259
|
+
const oldStart = new Date('2025-01-01T00:00:00Z');
|
|
260
|
+
const newStart = new Date('2025-01-02T00:00:00Z');
|
|
261
|
+
const unrelatedStart = new Date('2025-01-03T00:00:00Z');
|
|
262
|
+
const first = await repo.createExecutionAtomic('query-executions', 'old', {
|
|
263
|
+
p: 1
|
|
264
|
+
});
|
|
265
|
+
await repo.updateJobExecution(first.id, {
|
|
266
|
+
status: _core.JobStatus.COMPLETED,
|
|
267
|
+
startTime: oldStart,
|
|
268
|
+
endTime: new Date('2025-01-01T00:10:00Z')
|
|
269
|
+
});
|
|
270
|
+
const second = await repo.createExecutionAtomic('query-executions', 'new', {
|
|
271
|
+
p: 2
|
|
272
|
+
});
|
|
273
|
+
await repo.updateJobExecution(second.id, {
|
|
274
|
+
status: _core.JobStatus.FAILED,
|
|
275
|
+
startTime: newStart,
|
|
276
|
+
endTime: new Date('2025-01-02T00:10:00Z')
|
|
277
|
+
});
|
|
278
|
+
const unrelated = await repo.createExecutionAtomic('query-executions-other', 'x', {
|
|
279
|
+
p: 3
|
|
280
|
+
});
|
|
281
|
+
await repo.updateJobExecution(unrelated.id, {
|
|
282
|
+
status: _core.JobStatus.COMPLETED,
|
|
283
|
+
startTime: unrelatedStart,
|
|
284
|
+
endTime: new Date('2025-01-03T00:10:00Z')
|
|
285
|
+
});
|
|
286
|
+
const byInstance = await repo.findJobExecutions({
|
|
287
|
+
jobInstanceId: first.jobInstanceId
|
|
288
|
+
});
|
|
289
|
+
(0, _vitest.expect)(byInstance.map((e)=>e.id)).toEqual([
|
|
290
|
+
first.id
|
|
291
|
+
]);
|
|
292
|
+
const failed = await repo.findJobExecutions({
|
|
293
|
+
status: _core.JobStatus.FAILED
|
|
294
|
+
});
|
|
295
|
+
(0, _vitest.expect)(failed.map((e)=>e.id)).toContain(second.id);
|
|
296
|
+
(0, _vitest.expect)(failed.map((e)=>e.id)).not.toContain(first.id);
|
|
297
|
+
const terminal = await repo.findJobExecutions({
|
|
298
|
+
status: [
|
|
299
|
+
_core.JobStatus.COMPLETED,
|
|
300
|
+
_core.JobStatus.FAILED
|
|
301
|
+
]
|
|
302
|
+
});
|
|
303
|
+
(0, _vitest.expect)(terminal.map((e)=>e.id)).toEqual(_vitest.expect.arrayContaining([
|
|
304
|
+
first.id,
|
|
305
|
+
second.id,
|
|
306
|
+
unrelated.id
|
|
307
|
+
]));
|
|
308
|
+
const windowed = await repo.findJobExecutions({
|
|
309
|
+
startedAfter: new Date('2025-01-01T12:00:00Z'),
|
|
310
|
+
startedBefore: new Date('2025-01-02T12:00:00Z')
|
|
311
|
+
});
|
|
312
|
+
(0, _vitest.expect)(windowed.map((e)=>e.id)).toContain(second.id);
|
|
313
|
+
(0, _vitest.expect)(windowed.map((e)=>e.id)).not.toContain(first.id);
|
|
314
|
+
(0, _vitest.expect)(windowed.map((e)=>e.id)).not.toContain(unrelated.id);
|
|
315
|
+
});
|
|
316
|
+
(0, _vitest.test)('createStepExecution + updateStepExecution + getStepExecution roundtrip', async ()=>{
|
|
317
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-step', {
|
|
318
|
+
p: 1
|
|
319
|
+
});
|
|
320
|
+
const step = await repo.createStepExecution(exec.id, 'step-a');
|
|
321
|
+
(0, _vitest.expect)(step.status).toBe(_core.StepStatus.STARTING);
|
|
322
|
+
(0, _vitest.expect)(step.jobExecutionId).toBe(exec.id);
|
|
323
|
+
(0, _vitest.expect)(step.stepName).toBe('step-a');
|
|
324
|
+
(0, _vitest.expect)(step.readCount).toBe(0);
|
|
325
|
+
(0, _vitest.expect)(step.writeCount).toBe(0);
|
|
326
|
+
(0, _vitest.expect)(step.commitCount).toBe(0);
|
|
327
|
+
(0, _vitest.expect)(step.startTime).toBeNull();
|
|
328
|
+
(0, _vitest.expect)(step.endTime).toBeNull();
|
|
329
|
+
await repo.updateStepExecution(step.id, {
|
|
330
|
+
status: _core.StepStatus.STARTED,
|
|
331
|
+
readCount: 10,
|
|
332
|
+
writeCount: 5
|
|
333
|
+
});
|
|
334
|
+
const after = await repo.getStepExecution(step.id);
|
|
335
|
+
(0, _vitest.expect)(after?.status).toBe(_core.StepStatus.STARTED);
|
|
336
|
+
(0, _vitest.expect)(after?.readCount).toBe(10);
|
|
337
|
+
(0, _vitest.expect)(after?.writeCount).toBe(5);
|
|
338
|
+
// Cleanup
|
|
339
|
+
await repo.updateJobExecution(exec.id, {
|
|
340
|
+
status: _core.JobStatus.COMPLETED
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
(0, _vitest.test)('getStepExecution returns null for unknown id', async ()=>{
|
|
344
|
+
const result = await repo.getStepExecution('does-not-exist');
|
|
345
|
+
(0, _vitest.expect)(result).toBeNull();
|
|
346
|
+
});
|
|
347
|
+
(0, _vitest.test)('findStepExecutions returns all steps for the requested job execution', async ()=>{
|
|
348
|
+
const exec = await repo.createExecutionAtomic('query-steps', 'steps', {
|
|
349
|
+
p: 1
|
|
350
|
+
});
|
|
351
|
+
const first = await repo.createStepExecution(exec.id, 'step-a');
|
|
352
|
+
const second = await repo.createStepExecution(exec.id, 'step-b');
|
|
353
|
+
const otherExec = await repo.createExecutionAtomic('query-steps-other', 'steps', {
|
|
354
|
+
p: 2
|
|
355
|
+
});
|
|
356
|
+
const otherStep = await repo.createStepExecution(otherExec.id, 'step-a');
|
|
357
|
+
const steps = await repo.findStepExecutions(exec.id);
|
|
358
|
+
(0, _vitest.expect)(steps.map((s)=>s.id)).toEqual(_vitest.expect.arrayContaining([
|
|
359
|
+
first.id,
|
|
360
|
+
second.id
|
|
361
|
+
]));
|
|
362
|
+
(0, _vitest.expect)(steps.map((s)=>s.id)).not.toContain(otherStep.id);
|
|
363
|
+
await repo.updateJobExecution(exec.id, {
|
|
364
|
+
status: _core.JobStatus.COMPLETED
|
|
365
|
+
});
|
|
366
|
+
await repo.updateJobExecution(otherExec.id, {
|
|
367
|
+
status: _core.JobStatus.COMPLETED
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
(0, _vitest.test)('saveExecutionContext + getExecutionContext roundtrip preserves data and version', async ()=>{
|
|
371
|
+
const scope = {
|
|
372
|
+
stepExecutionId: 'ctx-1'
|
|
373
|
+
};
|
|
374
|
+
const data = {
|
|
375
|
+
cursor: 5,
|
|
376
|
+
items: [
|
|
377
|
+
1,
|
|
378
|
+
2,
|
|
379
|
+
3
|
|
380
|
+
],
|
|
381
|
+
meta: {
|
|
382
|
+
tag: 'x'
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
await repo.saveExecutionContext(scope, {
|
|
386
|
+
data,
|
|
387
|
+
version: 1
|
|
388
|
+
});
|
|
389
|
+
const ctx = await repo.getExecutionContext(scope);
|
|
390
|
+
(0, _vitest.expect)(ctx).toEqual({
|
|
391
|
+
data,
|
|
392
|
+
version: 1
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
(0, _vitest.test)('saveExecutionContext auto-increments version when the version argument is omitted', async ()=>{
|
|
396
|
+
const scope = {
|
|
397
|
+
jobExecutionId: 'ctx-auto'
|
|
398
|
+
};
|
|
399
|
+
await repo.saveExecutionContext(scope, {
|
|
400
|
+
data: {
|
|
401
|
+
n: 1
|
|
402
|
+
},
|
|
403
|
+
version: 0
|
|
404
|
+
}, 1);
|
|
405
|
+
await repo.saveExecutionContext(scope, {
|
|
406
|
+
data: {
|
|
407
|
+
n: 2
|
|
408
|
+
},
|
|
409
|
+
version: 0
|
|
410
|
+
});
|
|
411
|
+
const ctx = await repo.getExecutionContext(scope);
|
|
412
|
+
(0, _vitest.expect)(ctx?.data).toEqual({
|
|
413
|
+
n: 2
|
|
414
|
+
});
|
|
415
|
+
(0, _vitest.expect)((ctx?.version ?? 0) > 1).toBe(true);
|
|
416
|
+
});
|
|
417
|
+
(0, _vitest.test)('getExecutionContext returns { data: null, version: 0 } when no context exists', async ()=>{
|
|
418
|
+
const scope = {
|
|
419
|
+
stepExecutionId: 'no-scope'
|
|
420
|
+
};
|
|
421
|
+
const ctx = await repo.getExecutionContext(scope);
|
|
422
|
+
(0, _vitest.expect)(ctx).toEqual({
|
|
423
|
+
data: null,
|
|
424
|
+
version: 0
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
(0, _vitest.test)('saveExecutionContext / getExecutionContext isolate job-scope from step-scope', async ()=>{
|
|
428
|
+
const jobScope = {
|
|
429
|
+
jobExecutionId: 'iso-job'
|
|
430
|
+
};
|
|
431
|
+
const stepScope = {
|
|
432
|
+
stepExecutionId: 'iso-step'
|
|
433
|
+
};
|
|
434
|
+
await repo.saveExecutionContext(jobScope, {
|
|
435
|
+
data: {
|
|
436
|
+
where: 'job'
|
|
437
|
+
},
|
|
438
|
+
version: 1
|
|
439
|
+
});
|
|
440
|
+
await repo.saveExecutionContext(stepScope, {
|
|
441
|
+
data: {
|
|
442
|
+
where: 'step'
|
|
443
|
+
},
|
|
444
|
+
version: 1
|
|
445
|
+
});
|
|
446
|
+
(0, _vitest.expect)(await repo.getExecutionContext(jobScope)).toEqual({
|
|
447
|
+
data: {
|
|
448
|
+
where: 'job'
|
|
449
|
+
},
|
|
450
|
+
version: 1
|
|
451
|
+
});
|
|
452
|
+
(0, _vitest.expect)(await repo.getExecutionContext(stepScope)).toEqual({
|
|
453
|
+
data: {
|
|
454
|
+
where: 'step'
|
|
455
|
+
},
|
|
456
|
+
version: 1
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
(0, _vitest.test)('saveExecutionContext: mutating returned data does not affect stored data on next read', async ()=>{
|
|
460
|
+
const scope = {
|
|
461
|
+
stepExecutionId: 'ctx-mut'
|
|
462
|
+
};
|
|
463
|
+
await repo.saveExecutionContext(scope, {
|
|
464
|
+
data: {
|
|
465
|
+
cursor: 0
|
|
466
|
+
},
|
|
467
|
+
version: 1
|
|
468
|
+
});
|
|
469
|
+
const first = await repo.getExecutionContext(scope);
|
|
470
|
+
first.data['cursor'] = -1;
|
|
471
|
+
const second = await repo.getExecutionContext(scope);
|
|
472
|
+
(0, _vitest.expect)(second.data['cursor']).toBe(0);
|
|
473
|
+
});
|
|
474
|
+
(0, _vitest.test)('findLatestStepExecution returns null when no step exists', async ()=>{
|
|
475
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-nil', {
|
|
476
|
+
p: 1
|
|
477
|
+
});
|
|
478
|
+
const step = await repo.findLatestStepExecution(exec.id, 'never-existed');
|
|
479
|
+
(0, _vitest.expect)(step).toBeNull();
|
|
480
|
+
await repo.updateJobExecution(exec.id, {
|
|
481
|
+
status: _core.JobStatus.COMPLETED
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
(0, _vitest.test)('findLatestStepExecution returns the latest matching step (restart checkpoint)', async ()=>{
|
|
485
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-latest', {
|
|
486
|
+
p: 1
|
|
487
|
+
});
|
|
488
|
+
const older = await repo.createStepExecution(exec.id, 'step-a');
|
|
489
|
+
await repo.updateStepExecution(older.id, {
|
|
490
|
+
status: _core.StepStatus.FAILED
|
|
491
|
+
});
|
|
492
|
+
// SQLite millisecond-resolution timestamps can cause both rows
|
|
493
|
+
// to share the same created_at, making UUID tie-breaking
|
|
494
|
+
// non-deterministic. A tiny delay guarantees ordering.
|
|
495
|
+
await new Promise((r)=>setTimeout(r, 5));
|
|
496
|
+
const newer = await repo.createStepExecution(exec.id, 'step-a');
|
|
497
|
+
await repo.updateStepExecution(newer.id, {
|
|
498
|
+
status: _core.StepStatus.FAILED
|
|
499
|
+
});
|
|
500
|
+
const latest = await repo.findLatestStepExecution(exec.id, 'step-a');
|
|
501
|
+
(0, _vitest.expect)(latest).not.toBeNull();
|
|
502
|
+
(0, _vitest.expect)(latest.id).toBe(newer.id);
|
|
503
|
+
await repo.updateJobExecution(exec.id, {
|
|
504
|
+
status: _core.JobStatus.COMPLETED
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
(0, _vitest.test)('findLatestStepExecution ignores steps for other step names', async ()=>{
|
|
508
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-isolated', {
|
|
509
|
+
p: 1
|
|
510
|
+
});
|
|
511
|
+
await repo.createStepExecution(exec.id, 'step-a');
|
|
512
|
+
const stepB = await repo.createStepExecution(exec.id, 'step-b');
|
|
513
|
+
const latest = await repo.findLatestStepExecution(exec.id, 'step-b');
|
|
514
|
+
(0, _vitest.expect)(latest?.id).toBe(stepB.id);
|
|
515
|
+
await repo.updateJobExecution(exec.id, {
|
|
516
|
+
status: _core.JobStatus.COMPLETED
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
(0, _vitest.test)('findLatestStepExecution returns the only matching step when there is just one', async ()=>{
|
|
520
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-single', {
|
|
521
|
+
p: 1
|
|
522
|
+
});
|
|
523
|
+
const step = await repo.createStepExecution(exec.id, 'only-step');
|
|
524
|
+
const latest = await repo.findLatestStepExecution(exec.id, 'only-step');
|
|
525
|
+
(0, _vitest.expect)(latest?.id).toBe(step.id);
|
|
526
|
+
await repo.updateJobExecution(exec.id, {
|
|
527
|
+
status: _core.JobStatus.COMPLETED
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
(0, _vitest.test)('checkpoint lookup: after a partial chunk, findLatestStepExecution returns the row and its saved context', async ()=>{
|
|
531
|
+
const exec = await repo.createExecutionAtomic('myJob', 'k-ckpt', {
|
|
532
|
+
p: 1
|
|
533
|
+
});
|
|
534
|
+
const step = await repo.createStepExecution(exec.id, 'chunk-step');
|
|
535
|
+
// Simulate a chunk-mid-flight state
|
|
536
|
+
await repo.updateStepExecution(step.id, {
|
|
537
|
+
status: _core.StepStatus.STARTED,
|
|
538
|
+
readCount: 50,
|
|
539
|
+
writeCount: 50,
|
|
540
|
+
commitCount: 1
|
|
541
|
+
});
|
|
542
|
+
// Save the last-committed-chunk checkpoint as execution context
|
|
543
|
+
const checkpoint = {
|
|
544
|
+
lastChunkIndex: 1,
|
|
545
|
+
lastReadIndex: 50
|
|
546
|
+
};
|
|
547
|
+
await repo.saveExecutionContext({
|
|
548
|
+
stepExecutionId: step.id
|
|
549
|
+
}, {
|
|
550
|
+
data: checkpoint,
|
|
551
|
+
version: 1
|
|
552
|
+
});
|
|
553
|
+
// Simulate a failure
|
|
554
|
+
await repo.updateStepExecution(step.id, {
|
|
555
|
+
status: _core.StepStatus.FAILED,
|
|
556
|
+
endTime: new Date(),
|
|
557
|
+
exitMessage: 'simulated crash'
|
|
558
|
+
});
|
|
559
|
+
// Restart: look up the latest step execution for this step
|
|
560
|
+
const latest = await repo.findLatestStepExecution(exec.id, 'chunk-step');
|
|
561
|
+
(0, _vitest.expect)(latest).not.toBeNull();
|
|
562
|
+
(0, _vitest.expect)(latest.id).toBe(step.id);
|
|
563
|
+
(0, _vitest.expect)(latest.status).toBe(_core.StepStatus.FAILED);
|
|
564
|
+
// And load its saved checkpoint
|
|
565
|
+
const ctx = await repo.getExecutionContext({
|
|
566
|
+
stepExecutionId: latest.id
|
|
567
|
+
});
|
|
568
|
+
(0, _vitest.expect)(ctx).toEqual({
|
|
569
|
+
data: checkpoint,
|
|
570
|
+
version: 1
|
|
571
|
+
});
|
|
572
|
+
await repo.updateJobExecution(exec.id, {
|
|
573
|
+
status: _core.JobStatus.COMPLETED
|
|
574
|
+
});
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
(0, _vitest.describe)('TransactionManager', ()=>{
|
|
578
|
+
(0, _vitest.test)('withTransaction yields an active context (isActive=true) with a non-empty id', async ()=>{
|
|
579
|
+
let receivedCtx = null;
|
|
580
|
+
await tx.withTransaction(async (ctx)=>{
|
|
581
|
+
receivedCtx = ctx;
|
|
582
|
+
});
|
|
583
|
+
(0, _vitest.expect)(receivedCtx).not.toBeNull();
|
|
584
|
+
(0, _vitest.expect)(receivedCtx.isActive).toBe(true);
|
|
585
|
+
(0, _vitest.expect)(typeof receivedCtx.id).toBe('string');
|
|
586
|
+
(0, _vitest.expect)(receivedCtx.id.length).toBeGreaterThan(0);
|
|
587
|
+
});
|
|
588
|
+
(0, _vitest.test)('withTransaction returns the value resolved by fn', async ()=>{
|
|
589
|
+
const result = await tx.withTransaction(async ()=>({
|
|
590
|
+
ok: true,
|
|
591
|
+
n: 42
|
|
592
|
+
}));
|
|
593
|
+
(0, _vitest.expect)(result).toEqual({
|
|
594
|
+
ok: true,
|
|
595
|
+
n: 42
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
(0, _vitest.test)('withTransaction propagates errors thrown by fn', async ()=>{
|
|
599
|
+
const err = new Error('tx-boom');
|
|
600
|
+
await (0, _vitest.expect)(tx.withTransaction(async ()=>{
|
|
601
|
+
throw err;
|
|
602
|
+
})).rejects.toBe(err);
|
|
603
|
+
});
|
|
604
|
+
(0, _vitest.test)('withTransaction wraps repository operations — create + update visible inside the same ctx', async ()=>{
|
|
605
|
+
const jobInstanceId = await tx.withTransaction(async (ctx)=>{
|
|
606
|
+
(0, _vitest.expect)(ctx.isActive).toBe(true);
|
|
607
|
+
const exec = await repo.createExecutionAtomic('myJob', 'tx-wrap', {
|
|
608
|
+
p: 1
|
|
609
|
+
});
|
|
610
|
+
await repo.updateJobExecution(exec.id, {
|
|
611
|
+
status: _core.JobStatus.STARTED
|
|
612
|
+
});
|
|
613
|
+
const after = await repo.getJobExecution(exec.id);
|
|
614
|
+
(0, _vitest.expect)(after?.status).toBe(_core.JobStatus.STARTED);
|
|
615
|
+
return exec.jobInstanceId;
|
|
616
|
+
});
|
|
617
|
+
// After the tx, the data must be visible (real DB or in-memory).
|
|
618
|
+
const execs = await repo.getRunningJobExecution(jobInstanceId);
|
|
619
|
+
// No running exec remains once we completed it... actually we set it
|
|
620
|
+
// to STARTED. The contract here is just that the data was visible
|
|
621
|
+
// inside the tx; we don't assume anything about external visibility.
|
|
622
|
+
(0, _vitest.expect)(execs === null || execs.status === _core.JobStatus.STARTED).toBe(true);
|
|
623
|
+
// Cleanup
|
|
624
|
+
if (execs) {
|
|
625
|
+
await repo.updateJobExecution(execs.id, {
|
|
626
|
+
status: _core.JobStatus.COMPLETED
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
(0, _vitest.test)('withTransaction: two distinct invocations produce different context ids', async ()=>{
|
|
631
|
+
const ids = new Set();
|
|
632
|
+
for(let i = 0; i < 3; i++){
|
|
633
|
+
await tx.withTransaction(async (ctx)=>{
|
|
634
|
+
ids.add(ctx.id);
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
(0, _vitest.expect)(ids.size).toBe(3);
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
//# sourceMappingURL=job-repository.contract.js.map
|