@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.
Files changed (476) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +368 -0
  3. package/dist/src/adapters/in-process.adapter.d.ts +140 -0
  4. package/dist/src/adapters/in-process.adapter.d.ts.map +1 -0
  5. package/dist/src/adapters/in-process.adapter.js +86 -0
  6. package/dist/src/adapters/in-process.adapter.js.map +1 -0
  7. package/dist/src/adapters/index.d.ts +18 -0
  8. package/dist/src/adapters/index.d.ts.map +1 -0
  9. package/dist/src/adapters/index.js +35 -0
  10. package/dist/src/adapters/index.js.map +1 -0
  11. package/dist/src/builder/batch-builder.d.ts +26 -0
  12. package/dist/src/builder/batch-builder.d.ts.map +1 -0
  13. package/dist/src/builder/batch-builder.js +25 -0
  14. package/dist/src/builder/batch-builder.js.map +1 -0
  15. package/dist/src/builder/flow-builder.d.ts +59 -0
  16. package/dist/src/builder/flow-builder.d.ts.map +1 -0
  17. package/dist/src/builder/flow-builder.js +115 -0
  18. package/dist/src/builder/flow-builder.js.map +1 -0
  19. package/dist/src/builder/index.d.ts +5 -0
  20. package/dist/src/builder/index.d.ts.map +1 -0
  21. package/dist/src/builder/index.js +23 -0
  22. package/dist/src/builder/index.js.map +1 -0
  23. package/dist/src/builder/job-builder.d.ts +76 -0
  24. package/dist/src/builder/job-builder.d.ts.map +1 -0
  25. package/dist/src/builder/job-builder.js +166 -0
  26. package/dist/src/builder/job-builder.js.map +1 -0
  27. package/dist/src/builder/step-builder.d.ts +74 -0
  28. package/dist/src/builder/step-builder.d.ts.map +1 -0
  29. package/dist/src/builder/step-builder.js +144 -0
  30. package/dist/src/builder/step-builder.js.map +1 -0
  31. package/dist/src/compiler/builder-types.d.ts +20 -0
  32. package/dist/src/compiler/builder-types.d.ts.map +1 -0
  33. package/dist/src/compiler/builder-types.js +6 -0
  34. package/dist/src/compiler/builder-types.js.map +1 -0
  35. package/dist/src/compiler/definition-compiler.d.ts +99 -0
  36. package/dist/src/compiler/definition-compiler.d.ts.map +1 -0
  37. package/dist/src/compiler/definition-compiler.js +257 -0
  38. package/dist/src/compiler/definition-compiler.js.map +1 -0
  39. package/dist/src/compiler/index.d.ts +3 -0
  40. package/dist/src/compiler/index.d.ts.map +1 -0
  41. package/dist/src/compiler/index.js +21 -0
  42. package/dist/src/compiler/index.js.map +1 -0
  43. package/dist/src/core/errors.d.ts +77 -0
  44. package/dist/src/core/errors.d.ts.map +1 -0
  45. package/dist/src/core/errors.js +170 -0
  46. package/dist/src/core/errors.js.map +1 -0
  47. package/dist/src/core/execution-context/index.d.ts +4 -0
  48. package/dist/src/core/execution-context/index.d.ts.map +1 -0
  49. package/dist/src/core/execution-context/index.js +22 -0
  50. package/dist/src/core/execution-context/index.js.map +1 -0
  51. package/dist/src/core/execution-context/json-value.d.ts +5 -0
  52. package/dist/src/core/execution-context/json-value.d.ts.map +1 -0
  53. package/dist/src/core/execution-context/json-value.js +6 -0
  54. package/dist/src/core/execution-context/json-value.js.map +1 -0
  55. package/dist/src/core/execution-context/serializer.d.ts +4 -0
  56. package/dist/src/core/execution-context/serializer.d.ts.map +1 -0
  57. package/dist/src/core/execution-context/serializer.js +34 -0
  58. package/dist/src/core/execution-context/serializer.js.map +1 -0
  59. package/dist/src/core/execution-context/validator.d.ts +18 -0
  60. package/dist/src/core/execution-context/validator.d.ts.map +1 -0
  61. package/dist/src/core/execution-context/validator.js +90 -0
  62. package/dist/src/core/execution-context/validator.js.map +1 -0
  63. package/dist/src/core/index.d.ts +8 -0
  64. package/dist/src/core/index.d.ts.map +1 -0
  65. package/dist/src/core/index.js +26 -0
  66. package/dist/src/core/index.js.map +1 -0
  67. package/dist/src/core/ir/decider-definition.d.ts +20 -0
  68. package/dist/src/core/ir/decider-definition.d.ts.map +1 -0
  69. package/dist/src/core/ir/decider-definition.js +6 -0
  70. package/dist/src/core/ir/decider-definition.js.map +1 -0
  71. package/dist/src/core/ir/index.d.ts +8 -0
  72. package/dist/src/core/ir/index.d.ts.map +1 -0
  73. package/dist/src/core/ir/index.js +26 -0
  74. package/dist/src/core/ir/index.js.map +1 -0
  75. package/dist/src/core/ir/job-definition.d.ts +15 -0
  76. package/dist/src/core/ir/job-definition.d.ts.map +1 -0
  77. package/dist/src/core/ir/job-definition.js +6 -0
  78. package/dist/src/core/ir/job-definition.js.map +1 -0
  79. package/dist/src/core/ir/listener-definition.d.ts +10 -0
  80. package/dist/src/core/ir/listener-definition.d.ts.map +1 -0
  81. package/dist/src/core/ir/listener-definition.js +6 -0
  82. package/dist/src/core/ir/listener-definition.js.map +1 -0
  83. package/dist/src/core/ir/policy-config.d.ts +24 -0
  84. package/dist/src/core/ir/policy-config.d.ts.map +1 -0
  85. package/dist/src/core/ir/policy-config.js +6 -0
  86. package/dist/src/core/ir/policy-config.js.map +1 -0
  87. package/dist/src/core/ir/refs.d.ts +42 -0
  88. package/dist/src/core/ir/refs.d.ts.map +1 -0
  89. package/dist/src/core/ir/refs.js +18 -0
  90. package/dist/src/core/ir/refs.js.map +1 -0
  91. package/dist/src/core/ir/step-definition.d.ts +59 -0
  92. package/dist/src/core/ir/step-definition.d.ts.map +1 -0
  93. package/dist/src/core/ir/step-definition.js +6 -0
  94. package/dist/src/core/ir/step-definition.js.map +1 -0
  95. package/dist/src/core/ir/transition-definition.d.ts +8 -0
  96. package/dist/src/core/ir/transition-definition.d.ts.map +1 -0
  97. package/dist/src/core/ir/transition-definition.js +6 -0
  98. package/dist/src/core/ir/transition-definition.js.map +1 -0
  99. package/dist/src/core/item/index.d.ts +2 -0
  100. package/dist/src/core/item/index.d.ts.map +1 -0
  101. package/dist/src/core/item/index.js +20 -0
  102. package/dist/src/core/item/index.js.map +1 -0
  103. package/dist/src/core/item/interfaces.d.ts +64 -0
  104. package/dist/src/core/item/interfaces.d.ts.map +1 -0
  105. package/dist/src/core/item/interfaces.js +6 -0
  106. package/dist/src/core/item/interfaces.js.map +1 -0
  107. package/dist/src/core/repository/index.d.ts +3 -0
  108. package/dist/src/core/repository/index.d.ts.map +1 -0
  109. package/dist/src/core/repository/index.js +21 -0
  110. package/dist/src/core/repository/index.js.map +1 -0
  111. package/dist/src/core/repository/job-repository.d.ts +60 -0
  112. package/dist/src/core/repository/job-repository.d.ts.map +1 -0
  113. package/dist/src/core/repository/job-repository.js +27 -0
  114. package/dist/src/core/repository/job-repository.js.map +1 -0
  115. package/dist/src/core/repository/types.d.ts +84 -0
  116. package/dist/src/core/repository/types.d.ts.map +1 -0
  117. package/dist/src/core/repository/types.js +6 -0
  118. package/dist/src/core/repository/types.js.map +1 -0
  119. package/dist/src/core/status.d.ts +29 -0
  120. package/dist/src/core/status.d.ts.map +1 -0
  121. package/dist/src/core/status.js +58 -0
  122. package/dist/src/core/status.js.map +1 -0
  123. package/dist/src/core/transaction/index.d.ts +2 -0
  124. package/dist/src/core/transaction/index.d.ts.map +1 -0
  125. package/dist/src/core/transaction/index.js +20 -0
  126. package/dist/src/core/transaction/index.js.map +1 -0
  127. package/dist/src/core/transaction/transaction-manager.d.ts +8 -0
  128. package/dist/src/core/transaction/transaction-manager.d.ts.map +1 -0
  129. package/dist/src/core/transaction/transaction-manager.js +14 -0
  130. package/dist/src/core/transaction/transaction-manager.js.map +1 -0
  131. package/dist/src/core/validation/definition-validator.d.ts +46 -0
  132. package/dist/src/core/validation/definition-validator.d.ts.map +1 -0
  133. package/dist/src/core/validation/definition-validator.js +177 -0
  134. package/dist/src/core/validation/definition-validator.js.map +1 -0
  135. package/dist/src/core/validation/index.d.ts +2 -0
  136. package/dist/src/core/validation/index.d.ts.map +1 -0
  137. package/dist/src/core/validation/index.js +20 -0
  138. package/dist/src/core/validation/index.js.map +1 -0
  139. package/dist/src/decorators/constants.d.ts +10 -0
  140. package/dist/src/decorators/constants.d.ts.map +1 -0
  141. package/dist/src/decorators/constants.js +50 -0
  142. package/dist/src/decorators/constants.js.map +1 -0
  143. package/dist/src/decorators/flow.decorator.d.ts +25 -0
  144. package/dist/src/decorators/flow.decorator.d.ts.map +1 -0
  145. package/dist/src/decorators/flow.decorator.js +19 -0
  146. package/dist/src/decorators/flow.decorator.js.map +1 -0
  147. package/dist/src/decorators/index.d.ts +8 -0
  148. package/dist/src/decorators/index.d.ts.map +1 -0
  149. package/dist/src/decorators/index.js +26 -0
  150. package/dist/src/decorators/index.js.map +1 -0
  151. package/dist/src/decorators/item.decorators.d.ts +32 -0
  152. package/dist/src/decorators/item.decorators.d.ts.map +1 -0
  153. package/dist/src/decorators/item.decorators.js +40 -0
  154. package/dist/src/decorators/item.decorators.js.map +1 -0
  155. package/dist/src/decorators/job.decorator.d.ts +11 -0
  156. package/dist/src/decorators/job.decorator.d.ts.map +1 -0
  157. package/dist/src/decorators/job.decorator.js +17 -0
  158. package/dist/src/decorators/job.decorator.js.map +1 -0
  159. package/dist/src/decorators/listener.decorators.d.ts +56 -0
  160. package/dist/src/decorators/listener.decorators.d.ts.map +1 -0
  161. package/dist/src/decorators/listener.decorators.js +157 -0
  162. package/dist/src/decorators/listener.decorators.js.map +1 -0
  163. package/dist/src/decorators/step.decorator.d.ts +25 -0
  164. package/dist/src/decorators/step.decorator.d.ts.map +1 -0
  165. package/dist/src/decorators/step.decorator.js +21 -0
  166. package/dist/src/decorators/step.decorator.js.map +1 -0
  167. package/dist/src/decorators/tasklet.decorator.d.ts +7 -0
  168. package/dist/src/decorators/tasklet.decorator.d.ts.map +1 -0
  169. package/dist/src/decorators/tasklet.decorator.js +21 -0
  170. package/dist/src/decorators/tasklet.decorator.js.map +1 -0
  171. package/dist/src/execution/batch-worker-runner.d.ts +27 -0
  172. package/dist/src/execution/batch-worker-runner.d.ts.map +1 -0
  173. package/dist/src/execution/batch-worker-runner.js +147 -0
  174. package/dist/src/execution/batch-worker-runner.js.map +1 -0
  175. package/dist/src/execution/chunk-step-executor.d.ts +86 -0
  176. package/dist/src/execution/chunk-step-executor.d.ts.map +1 -0
  177. package/dist/src/execution/chunk-step-executor.js +482 -0
  178. package/dist/src/execution/chunk-step-executor.js.map +1 -0
  179. package/dist/src/execution/execution-strategy.d.ts +110 -0
  180. package/dist/src/execution/execution-strategy.d.ts.map +1 -0
  181. package/dist/src/execution/execution-strategy.js +13 -0
  182. package/dist/src/execution/execution-strategy.js.map +1 -0
  183. package/dist/src/execution/external-task-execution-strategy.d.ts +36 -0
  184. package/dist/src/execution/external-task-execution-strategy.d.ts.map +1 -0
  185. package/dist/src/execution/external-task-execution-strategy.js +97 -0
  186. package/dist/src/execution/external-task-execution-strategy.js.map +1 -0
  187. package/dist/src/execution/in-process-execution-strategy.d.ts +129 -0
  188. package/dist/src/execution/in-process-execution-strategy.d.ts.map +1 -0
  189. package/dist/src/execution/in-process-execution-strategy.js +141 -0
  190. package/dist/src/execution/in-process-execution-strategy.js.map +1 -0
  191. package/dist/src/execution/index.d.ts +14 -0
  192. package/dist/src/execution/index.d.ts.map +1 -0
  193. package/dist/src/execution/index.js +32 -0
  194. package/dist/src/execution/index.js.map +1 -0
  195. package/dist/src/execution/job-executor.d.ts +145 -0
  196. package/dist/src/execution/job-executor.d.ts.map +1 -0
  197. package/dist/src/execution/job-executor.js +475 -0
  198. package/dist/src/execution/job-executor.js.map +1 -0
  199. package/dist/src/execution/job-explorer.d.ts +15 -0
  200. package/dist/src/execution/job-explorer.d.ts.map +1 -0
  201. package/dist/src/execution/job-explorer.js +84 -0
  202. package/dist/src/execution/job-explorer.js.map +1 -0
  203. package/dist/src/execution/job-key.d.ts +3 -0
  204. package/dist/src/execution/job-key.d.ts.map +1 -0
  205. package/dist/src/execution/job-key.js +43 -0
  206. package/dist/src/execution/job-key.js.map +1 -0
  207. package/dist/src/execution/job-launcher.d.ts +75 -0
  208. package/dist/src/execution/job-launcher.d.ts.map +1 -0
  209. package/dist/src/execution/job-launcher.js +112 -0
  210. package/dist/src/execution/job-launcher.js.map +1 -0
  211. package/dist/src/execution/job-operator.d.ts +22 -0
  212. package/dist/src/execution/job-operator.d.ts.map +1 -0
  213. package/dist/src/execution/job-operator.js +125 -0
  214. package/dist/src/execution/job-operator.js.map +1 -0
  215. package/dist/src/execution/listener-invoker.d.ts +164 -0
  216. package/dist/src/execution/listener-invoker.d.ts.map +1 -0
  217. package/dist/src/execution/listener-invoker.js +246 -0
  218. package/dist/src/execution/listener-invoker.js.map +1 -0
  219. package/dist/src/execution/ref-resolver.d.ts +40 -0
  220. package/dist/src/execution/ref-resolver.d.ts.map +1 -0
  221. package/dist/src/execution/ref-resolver.js +41 -0
  222. package/dist/src/execution/ref-resolver.js.map +1 -0
  223. package/dist/src/execution/tasklet-step-executor.d.ts +79 -0
  224. package/dist/src/execution/tasklet-step-executor.d.ts.map +1 -0
  225. package/dist/src/execution/tasklet-step-executor.js +138 -0
  226. package/dist/src/execution/tasklet-step-executor.js.map +1 -0
  227. package/dist/src/explorer/batch-explorer.d.ts +138 -0
  228. package/dist/src/explorer/batch-explorer.d.ts.map +1 -0
  229. package/dist/src/explorer/batch-explorer.js +167 -0
  230. package/dist/src/explorer/batch-explorer.js.map +1 -0
  231. package/dist/src/explorer/index.d.ts +2 -0
  232. package/dist/src/explorer/index.d.ts.map +1 -0
  233. package/dist/src/explorer/index.js +20 -0
  234. package/dist/src/explorer/index.js.map +1 -0
  235. package/dist/src/flow/flow-evaluator.d.ts +30 -0
  236. package/dist/src/flow/flow-evaluator.d.ts.map +1 -0
  237. package/dist/src/flow/flow-evaluator.js +80 -0
  238. package/dist/src/flow/flow-evaluator.js.map +1 -0
  239. package/dist/src/flow/index.d.ts +2 -0
  240. package/dist/src/flow/index.d.ts.map +1 -0
  241. package/dist/src/flow/index.js +20 -0
  242. package/dist/src/flow/index.js.map +1 -0
  243. package/dist/src/index.d.ts +18 -0
  244. package/dist/src/index.d.ts.map +1 -0
  245. package/dist/src/index.js +90 -0
  246. package/dist/src/index.js.map +1 -0
  247. package/dist/src/io/checkpoint.d.ts +7 -0
  248. package/dist/src/io/checkpoint.d.ts.map +1 -0
  249. package/dist/src/io/checkpoint.js +56 -0
  250. package/dist/src/io/checkpoint.js.map +1 -0
  251. package/dist/src/io/database.d.ts +50 -0
  252. package/dist/src/io/database.d.ts.map +1 -0
  253. package/dist/src/io/database.js +108 -0
  254. package/dist/src/io/database.js.map +1 -0
  255. package/dist/src/io/file-readers.d.ts +54 -0
  256. package/dist/src/io/file-readers.d.ts.map +1 -0
  257. package/dist/src/io/file-readers.js +167 -0
  258. package/dist/src/io/file-readers.js.map +1 -0
  259. package/dist/src/io/file-writers.d.ts +31 -0
  260. package/dist/src/io/file-writers.d.ts.map +1 -0
  261. package/dist/src/io/file-writers.js +80 -0
  262. package/dist/src/io/file-writers.js.map +1 -0
  263. package/dist/src/io/index.d.ts +6 -0
  264. package/dist/src/io/index.d.ts.map +1 -0
  265. package/dist/src/io/index.js +24 -0
  266. package/dist/src/io/index.js.map +1 -0
  267. package/dist/src/io/s3.d.ts +50 -0
  268. package/dist/src/io/s3.d.ts.map +1 -0
  269. package/dist/src/io/s3.js +96 -0
  270. package/dist/src/io/s3.js.map +1 -0
  271. package/dist/src/listeners/builtin-listeners.d.ts +77 -0
  272. package/dist/src/listeners/builtin-listeners.d.ts.map +1 -0
  273. package/dist/src/listeners/builtin-listeners.js +108 -0
  274. package/dist/src/listeners/builtin-listeners.js.map +1 -0
  275. package/dist/src/listeners/index.d.ts +8 -0
  276. package/dist/src/listeners/index.d.ts.map +1 -0
  277. package/dist/src/listeners/index.js +25 -0
  278. package/dist/src/listeners/index.js.map +1 -0
  279. package/dist/src/module/adapter-options.d.ts +39 -0
  280. package/dist/src/module/adapter-options.d.ts.map +1 -0
  281. package/dist/src/module/adapter-options.js +34 -0
  282. package/dist/src/module/adapter-options.js.map +1 -0
  283. package/dist/src/module/adapter.d.ts +157 -0
  284. package/dist/src/module/adapter.d.ts.map +1 -0
  285. package/dist/src/module/adapter.js +80 -0
  286. package/dist/src/module/adapter.js.map +1 -0
  287. package/dist/src/module/batch-schedule-registry.d.ts +110 -0
  288. package/dist/src/module/batch-schedule-registry.d.ts.map +1 -0
  289. package/dist/src/module/batch-schedule-registry.js +0 -0
  290. package/dist/src/module/batch-schedule-registry.js.map +1 -0
  291. package/dist/src/module/index.d.ts +14 -0
  292. package/dist/src/module/index.d.ts.map +1 -0
  293. package/dist/src/module/index.js +31 -0
  294. package/dist/src/module/index.js.map +1 -0
  295. package/dist/src/module/nest-batch.module.d.ts +236 -0
  296. package/dist/src/module/nest-batch.module.d.ts.map +1 -0
  297. package/dist/src/module/nest-batch.module.js +475 -0
  298. package/dist/src/module/nest-batch.module.js.map +1 -0
  299. package/dist/src/module/tokens.d.ts +83 -0
  300. package/dist/src/module/tokens.d.ts.map +1 -0
  301. package/dist/src/module/tokens.js +58 -0
  302. package/dist/src/module/tokens.js.map +1 -0
  303. package/dist/src/observability/event-types.d.ts +55 -0
  304. package/dist/src/observability/event-types.d.ts.map +1 -0
  305. package/dist/src/observability/event-types.js +36 -0
  306. package/dist/src/observability/event-types.js.map +1 -0
  307. package/dist/src/observability/exporters.d.ts +35 -0
  308. package/dist/src/observability/exporters.d.ts.map +1 -0
  309. package/dist/src/observability/exporters.js +93 -0
  310. package/dist/src/observability/exporters.js.map +1 -0
  311. package/dist/src/observability/index.d.ts +3 -0
  312. package/dist/src/observability/index.d.ts.map +1 -0
  313. package/dist/src/observability/index.js +21 -0
  314. package/dist/src/observability/index.js.map +1 -0
  315. package/dist/src/partition-helpers.d.ts +127 -0
  316. package/dist/src/partition-helpers.d.ts.map +1 -0
  317. package/dist/src/partition-helpers.js +136 -0
  318. package/dist/src/partition-helpers.js.map +1 -0
  319. package/dist/src/policies/backoff.d.ts +3 -0
  320. package/dist/src/policies/backoff.d.ts.map +1 -0
  321. package/dist/src/policies/backoff.js +34 -0
  322. package/dist/src/policies/backoff.js.map +1 -0
  323. package/dist/src/policies/index.d.ts +4 -0
  324. package/dist/src/policies/index.d.ts.map +1 -0
  325. package/dist/src/policies/index.js +22 -0
  326. package/dist/src/policies/index.js.map +1 -0
  327. package/dist/src/policies/retry-policy.d.ts +13 -0
  328. package/dist/src/policies/retry-policy.d.ts.map +1 -0
  329. package/dist/src/policies/retry-policy.js +55 -0
  330. package/dist/src/policies/retry-policy.js.map +1 -0
  331. package/dist/src/policies/skip-policy.d.ts +12 -0
  332. package/dist/src/policies/skip-policy.d.ts.map +1 -0
  333. package/dist/src/policies/skip-policy.js +44 -0
  334. package/dist/src/policies/skip-policy.js.map +1 -0
  335. package/dist/src/registry/index.d.ts +2 -0
  336. package/dist/src/registry/index.d.ts.map +1 -0
  337. package/dist/src/registry/index.js +20 -0
  338. package/dist/src/registry/index.js.map +1 -0
  339. package/dist/src/registry/job-registry.d.ts +16 -0
  340. package/dist/src/registry/job-registry.d.ts.map +1 -0
  341. package/dist/src/registry/job-registry.js +50 -0
  342. package/dist/src/registry/job-registry.js.map +1 -0
  343. package/dist/src/repository/id-generator.d.ts +18 -0
  344. package/dist/src/repository/id-generator.d.ts.map +1 -0
  345. package/dist/src/repository/id-generator.js +37 -0
  346. package/dist/src/repository/id-generator.js.map +1 -0
  347. package/dist/src/repository/in-memory/in-memory-job-repository.d.ts +49 -0
  348. package/dist/src/repository/in-memory/in-memory-job-repository.d.ts.map +1 -0
  349. package/dist/src/repository/in-memory/in-memory-job-repository.js +291 -0
  350. package/dist/src/repository/in-memory/in-memory-job-repository.js.map +1 -0
  351. package/dist/src/repository/in-memory/index.d.ts +2 -0
  352. package/dist/src/repository/in-memory/index.d.ts.map +1 -0
  353. package/dist/src/repository/in-memory/index.js +20 -0
  354. package/dist/src/repository/in-memory/index.js.map +1 -0
  355. package/dist/src/repository/index.d.ts +4 -0
  356. package/dist/src/repository/index.d.ts.map +1 -0
  357. package/dist/src/repository/index.js +22 -0
  358. package/dist/src/repository/index.js.map +1 -0
  359. package/dist/src/repository/uuid-v7.d.ts +20 -0
  360. package/dist/src/repository/uuid-v7.d.ts.map +1 -0
  361. package/dist/src/repository/uuid-v7.js +31 -0
  362. package/dist/src/repository/uuid-v7.js.map +1 -0
  363. package/dist/src/scheduling/batch-scheduled.d.ts +87 -0
  364. package/dist/src/scheduling/batch-scheduled.d.ts.map +1 -0
  365. package/dist/src/scheduling/batch-scheduled.js +170 -0
  366. package/dist/src/scheduling/batch-scheduled.js.map +1 -0
  367. package/dist/src/transaction/in-memory-transaction-manager.d.ts +16 -0
  368. package/dist/src/transaction/in-memory-transaction-manager.d.ts.map +1 -0
  369. package/dist/src/transaction/in-memory-transaction-manager.js +33 -0
  370. package/dist/src/transaction/in-memory-transaction-manager.js.map +1 -0
  371. package/dist/src/transaction/index.d.ts +2 -0
  372. package/dist/src/transaction/index.d.ts.map +1 -0
  373. package/dist/src/transaction/index.js +20 -0
  374. package/dist/src/transaction/index.js.map +1 -0
  375. package/dist/tests/contracts/index.d.ts +26 -0
  376. package/dist/tests/contracts/index.d.ts.map +1 -0
  377. package/dist/tests/contracts/index.js +37 -0
  378. package/dist/tests/contracts/index.js.map +1 -0
  379. package/dist/tests/contracts/job-repository.contract.d.ts +46 -0
  380. package/dist/tests/contracts/job-repository.contract.d.ts.map +1 -0
  381. package/dist/tests/contracts/job-repository.contract.js +644 -0
  382. package/dist/tests/contracts/job-repository.contract.js.map +1 -0
  383. package/package.json +80 -0
  384. package/src/adapters/in-process.adapter.ts +182 -0
  385. package/src/adapters/index.ts +17 -0
  386. package/src/builder/batch-builder.ts +32 -0
  387. package/src/builder/flow-builder.ts +141 -0
  388. package/src/builder/index.ts +4 -0
  389. package/src/builder/job-builder.ts +206 -0
  390. package/src/builder/step-builder.ts +190 -0
  391. package/src/compiler/builder-types.ts +27 -0
  392. package/src/compiler/definition-compiler.ts +325 -0
  393. package/src/compiler/index.ts +2 -0
  394. package/src/core/errors.ts +125 -0
  395. package/src/core/execution-context/index.ts +3 -0
  396. package/src/core/execution-context/json-value.ts +3 -0
  397. package/src/core/execution-context/serializer.ts +21 -0
  398. package/src/core/execution-context/validator.ts +103 -0
  399. package/src/core/index.ts +7 -0
  400. package/src/core/ir/decider-definition.ts +25 -0
  401. package/src/core/ir/index.ts +7 -0
  402. package/src/core/ir/job-definition.ts +15 -0
  403. package/src/core/ir/listener-definition.ts +19 -0
  404. package/src/core/ir/policy-config.ts +19 -0
  405. package/src/core/ir/refs.ts +42 -0
  406. package/src/core/ir/step-definition.ts +62 -0
  407. package/src/core/ir/transition-definition.ts +9 -0
  408. package/src/core/item/index.ts +1 -0
  409. package/src/core/item/interfaces.ts +70 -0
  410. package/src/core/repository/index.ts +2 -0
  411. package/src/core/repository/job-repository.ts +100 -0
  412. package/src/core/repository/types.ts +91 -0
  413. package/src/core/status.ts +31 -0
  414. package/src/core/transaction/index.ts +1 -0
  415. package/src/core/transaction/transaction-manager.ts +8 -0
  416. package/src/core/validation/definition-validator.ts +215 -0
  417. package/src/core/validation/index.ts +1 -0
  418. package/src/decorators/constants.ts +9 -0
  419. package/src/decorators/flow.decorator.ts +31 -0
  420. package/src/decorators/index.ts +7 -0
  421. package/src/decorators/item.decorators.ts +51 -0
  422. package/src/decorators/job.decorator.ts +16 -0
  423. package/src/decorators/listener.decorators.ts +142 -0
  424. package/src/decorators/step.decorator.ts +33 -0
  425. package/src/decorators/tasklet.decorator.ts +14 -0
  426. package/src/execution/batch-worker-runner.ts +142 -0
  427. package/src/execution/chunk-step-executor.ts +594 -0
  428. package/src/execution/execution-strategy.ts +115 -0
  429. package/src/execution/external-task-execution-strategy.ts +104 -0
  430. package/src/execution/in-process-execution-strategy.ts +207 -0
  431. package/src/execution/index.ts +13 -0
  432. package/src/execution/job-executor.ts +553 -0
  433. package/src/execution/job-explorer.ts +73 -0
  434. package/src/execution/job-key.ts +35 -0
  435. package/src/execution/job-launcher.ts +132 -0
  436. package/src/execution/job-operator.ts +127 -0
  437. package/src/execution/listener-invoker.ts +389 -0
  438. package/src/execution/ref-resolver.ts +64 -0
  439. package/src/execution/tasklet-step-executor.ts +182 -0
  440. package/src/explorer/batch-explorer.ts +251 -0
  441. package/src/explorer/index.ts +1 -0
  442. package/src/flow/flow-evaluator.ts +89 -0
  443. package/src/flow/index.ts +1 -0
  444. package/src/index.ts +24 -0
  445. package/src/io/checkpoint.ts +47 -0
  446. package/src/io/database.ts +114 -0
  447. package/src/io/file-readers.ts +191 -0
  448. package/src/io/file-writers.ts +99 -0
  449. package/src/io/index.ts +5 -0
  450. package/src/io/s3.ts +117 -0
  451. package/src/listeners/builtin-listeners.ts +151 -0
  452. package/src/listeners/index.ts +7 -0
  453. package/src/module/adapter-options.ts +38 -0
  454. package/src/module/adapter.ts +160 -0
  455. package/src/module/batch-schedule-registry.ts +0 -0
  456. package/src/module/index.ts +13 -0
  457. package/src/module/nest-batch.module.ts +674 -0
  458. package/src/module/tokens.ts +95 -0
  459. package/src/observability/event-types.ts +61 -0
  460. package/src/observability/exporters.ts +96 -0
  461. package/src/observability/index.ts +2 -0
  462. package/src/partition-helpers.ts +204 -0
  463. package/src/policies/backoff.ts +22 -0
  464. package/src/policies/index.ts +3 -0
  465. package/src/policies/retry-policy.ts +57 -0
  466. package/src/policies/skip-policy.ts +51 -0
  467. package/src/registry/index.ts +1 -0
  468. package/src/registry/job-registry.ts +42 -0
  469. package/src/repository/id-generator.ts +25 -0
  470. package/src/repository/in-memory/in-memory-job-repository.ts +334 -0
  471. package/src/repository/in-memory/index.ts +1 -0
  472. package/src/repository/index.ts +3 -0
  473. package/src/repository/uuid-v7.ts +40 -0
  474. package/src/scheduling/batch-scheduled.ts +257 -0
  475. package/src/transaction/in-memory-transaction-manager.ts +23 -0
  476. 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,2 @@
1
+ export * from './types';
2
+ export * from './job-repository';
@@ -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,8 @@
1
+ export interface TransactionContext {
2
+ readonly isActive: true;
3
+ readonly id: string;
4
+ }
5
+
6
+ export abstract class TransactionManager {
7
+ abstract withTransaction<T>(fn: (ctx: TransactionContext) => Promise<T>): Promise<T>;
8
+ }
@@ -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
+ }