@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,114 @@
1
+ import type { ExecutionContext, ItemReader, ItemStream, ItemWriter, WriterResult } from '../core';
2
+ import type { JsonValue } from '../core/execution-context';
3
+
4
+ import { readCheckpointNumber, readCheckpointValue, writeCheckpoint } from './checkpoint';
5
+
6
+ export interface DatabasePagingItemReaderOptions<T> {
7
+ readonly pageSize: number;
8
+ readonly checkpointKey?: string;
9
+ fetchPage(args: { offset: number; limit: number }): Promise<readonly T[]>;
10
+ }
11
+
12
+ export class DatabasePagingItemReader<T> implements ItemReader<T>, ItemStream {
13
+ private offset = 0;
14
+ private buffer: readonly T[] = [];
15
+ private bufferIndex = 0;
16
+
17
+ constructor(private readonly options: DatabasePagingItemReaderOptions<T>) {}
18
+
19
+ open(context: ExecutionContext): void {
20
+ this.offset = readCheckpointNumber(context, this.checkpointKey, 'offset', 0);
21
+ this.buffer = [];
22
+ this.bufferIndex = 0;
23
+ }
24
+
25
+ async read(): Promise<T | null> {
26
+ if (this.bufferIndex >= this.buffer.length) {
27
+ this.buffer = await this.options.fetchPage({
28
+ offset: this.offset,
29
+ limit: this.options.pageSize,
30
+ });
31
+ this.bufferIndex = 0;
32
+ if (this.buffer.length === 0) return null;
33
+ }
34
+ const item = this.buffer[this.bufferIndex]!;
35
+ this.bufferIndex += 1;
36
+ this.offset += 1;
37
+ return item;
38
+ }
39
+
40
+ update(context: ExecutionContext): ExecutionContext {
41
+ return writeCheckpoint(context, this.checkpointKey, { offset: this.offset });
42
+ }
43
+
44
+ close(): void {
45
+ this.buffer = [];
46
+ }
47
+
48
+ private get checkpointKey(): string {
49
+ return this.options.checkpointKey ?? 'database-paging-reader';
50
+ }
51
+ }
52
+
53
+ export interface DatabaseCursorItemReaderOptions<T> {
54
+ readonly pageSize: number;
55
+ readonly checkpointKey?: string;
56
+ readonly initialCursor?: JsonValue;
57
+ fetchAfter(cursor: JsonValue, limit: number): Promise<readonly T[]>;
58
+ getCursor(item: T): JsonValue;
59
+ }
60
+
61
+ export class DatabaseCursorItemReader<T> implements ItemReader<T>, ItemStream {
62
+ private cursor: JsonValue = null;
63
+ private buffer: readonly T[] = [];
64
+ private bufferIndex = 0;
65
+
66
+ constructor(private readonly options: DatabaseCursorItemReaderOptions<T>) {}
67
+
68
+ open(context: ExecutionContext): void {
69
+ this.cursor = readCheckpointValue(
70
+ context,
71
+ this.checkpointKey,
72
+ 'cursor',
73
+ this.options.initialCursor ?? null,
74
+ );
75
+ this.buffer = [];
76
+ this.bufferIndex = 0;
77
+ }
78
+
79
+ async read(): Promise<T | null> {
80
+ if (this.bufferIndex >= this.buffer.length) {
81
+ this.buffer = await this.options.fetchAfter(this.cursor, this.options.pageSize);
82
+ this.bufferIndex = 0;
83
+ if (this.buffer.length === 0) return null;
84
+ }
85
+ const item = this.buffer[this.bufferIndex]!;
86
+ this.bufferIndex += 1;
87
+ this.cursor = this.options.getCursor(item);
88
+ return item;
89
+ }
90
+
91
+ update(context: ExecutionContext): ExecutionContext {
92
+ return writeCheckpoint(context, this.checkpointKey, { cursor: this.cursor });
93
+ }
94
+
95
+ close(): void {
96
+ this.buffer = [];
97
+ }
98
+
99
+ private get checkpointKey(): string {
100
+ return this.options.checkpointKey ?? 'database-cursor-reader';
101
+ }
102
+ }
103
+
104
+ export interface DatabaseBatchItemWriterOptions<T> {
105
+ writeBatch(items: readonly T[]): Promise<WriterResult | void>;
106
+ }
107
+
108
+ export class DatabaseBatchItemWriter<T> implements ItemWriter<T> {
109
+ constructor(private readonly options: DatabaseBatchItemWriterOptions<T>) {}
110
+
111
+ write(items: T[]): Promise<WriterResult | void> {
112
+ return this.options.writeBatch(items);
113
+ }
114
+ }
@@ -0,0 +1,191 @@
1
+ import { readFile } from 'node:fs/promises';
2
+
3
+ import type { ExecutionContext, ItemReader, ItemStream } from '../core';
4
+
5
+ import { readCheckpointNumber, writeCheckpoint } from './checkpoint';
6
+
7
+ export interface RestartableFileLineReaderOptions<T = string> {
8
+ readonly path: string;
9
+ readonly encoding?: BufferEncoding;
10
+ readonly checkpointKey?: string;
11
+ readonly skipLines?: number;
12
+ readonly skipBlankLines?: boolean;
13
+ readonly mapLine?: (line: string, lineIndex: number) => T | null | Promise<T | null>;
14
+ }
15
+
16
+ export class RestartableFileLineReader<T = string>
17
+ implements ItemReader<T>, ItemStream
18
+ {
19
+ private lines: string[] = [];
20
+ private index = 0;
21
+
22
+ constructor(private readonly options: RestartableFileLineReaderOptions<T>) {}
23
+
24
+ async open(context: ExecutionContext): Promise<void> {
25
+ const raw = await readFile(this.options.path, this.options.encoding ?? 'utf8');
26
+ this.lines = splitLines(raw);
27
+ this.index = readCheckpointNumber(
28
+ context,
29
+ this.checkpointKey,
30
+ 'index',
31
+ this.options.skipLines ?? 0,
32
+ );
33
+ }
34
+
35
+ async read(): Promise<T | null> {
36
+ while (this.index < this.lines.length) {
37
+ const lineIndex = this.index;
38
+ const line = this.lines[this.index]!;
39
+ this.index += 1;
40
+ if (this.options.skipBlankLines === true && line.trim().length === 0) continue;
41
+ if (this.options.mapLine !== undefined) {
42
+ const mapped = await this.options.mapLine(line, lineIndex);
43
+ if (mapped === null) continue;
44
+ return mapped;
45
+ }
46
+ return line as T;
47
+ }
48
+ return null;
49
+ }
50
+
51
+ update(context: ExecutionContext): ExecutionContext {
52
+ return writeCheckpoint(context, this.checkpointKey, { index: this.index });
53
+ }
54
+
55
+ close(): void {
56
+ this.lines = [];
57
+ }
58
+
59
+ private get checkpointKey(): string {
60
+ return this.options.checkpointKey ?? `file-line:${this.options.path}`;
61
+ }
62
+ }
63
+
64
+ export interface CsvFileItemReaderOptions<T extends Record<string, unknown>> {
65
+ readonly path: string;
66
+ readonly encoding?: BufferEncoding;
67
+ readonly checkpointKey?: string;
68
+ readonly delimiter?: string;
69
+ readonly headers?: readonly string[];
70
+ readonly hasHeader?: boolean;
71
+ readonly skipBlankLines?: boolean;
72
+ readonly mapRow?: (
73
+ row: Record<string, string>,
74
+ lineIndex: number,
75
+ ) => T | null | Promise<T | null>;
76
+ }
77
+
78
+ export class CsvFileItemReader<T extends Record<string, unknown> = Record<string, string>>
79
+ implements ItemReader<T>, ItemStream
80
+ {
81
+ private lines: string[] = [];
82
+ private headers: readonly string[] = [];
83
+ private index = 0;
84
+
85
+ constructor(private readonly options: CsvFileItemReaderOptions<T>) {}
86
+
87
+ async open(context: ExecutionContext): Promise<void> {
88
+ const raw = await readFile(this.options.path, this.options.encoding ?? 'utf8');
89
+ this.lines = splitLines(raw);
90
+ const hasHeader = this.options.hasHeader ?? this.options.headers === undefined;
91
+ this.headers =
92
+ this.options.headers ??
93
+ (this.lines.length > 0
94
+ ? parseDelimitedLine(this.lines[0]!, this.delimiter)
95
+ : []);
96
+ const firstDataLine = hasHeader ? 1 : 0;
97
+ this.index = readCheckpointNumber(context, this.checkpointKey, 'index', firstDataLine);
98
+ }
99
+
100
+ async read(): Promise<T | null> {
101
+ while (this.index < this.lines.length) {
102
+ const lineIndex = this.index;
103
+ const line = this.lines[this.index]!;
104
+ this.index += 1;
105
+ if (this.options.skipBlankLines !== false && line.trim().length === 0) continue;
106
+ const fields = parseDelimitedLine(line, this.delimiter);
107
+ const row: Record<string, string> = {};
108
+ for (let i = 0; i < this.headers.length; i += 1) {
109
+ row[this.headers[i]!] = fields[i] ?? '';
110
+ }
111
+ if (this.options.mapRow !== undefined) {
112
+ const mapped = await this.options.mapRow(row, lineIndex);
113
+ if (mapped === null) continue;
114
+ return mapped;
115
+ }
116
+ return row as T;
117
+ }
118
+ return null;
119
+ }
120
+
121
+ update(context: ExecutionContext): ExecutionContext {
122
+ return writeCheckpoint(context, this.checkpointKey, { index: this.index });
123
+ }
124
+
125
+ close(): void {
126
+ this.lines = [];
127
+ this.headers = [];
128
+ }
129
+
130
+ private get checkpointKey(): string {
131
+ return this.options.checkpointKey ?? `csv:${this.options.path}`;
132
+ }
133
+
134
+ private get delimiter(): string {
135
+ return this.options.delimiter ?? ',';
136
+ }
137
+ }
138
+
139
+ export interface JsonlFileItemReaderOptions<T> {
140
+ readonly path: string;
141
+ readonly encoding?: BufferEncoding;
142
+ readonly checkpointKey?: string;
143
+ }
144
+
145
+ export class JsonlFileItemReader<T = unknown> extends RestartableFileLineReader<T> {
146
+ constructor(options: JsonlFileItemReaderOptions<T>) {
147
+ super({
148
+ ...options,
149
+ skipBlankLines: true,
150
+ mapLine: (line) => JSON.parse(line) as T,
151
+ });
152
+ }
153
+ }
154
+
155
+ export function splitLines(raw: string | Buffer): string[] {
156
+ const text = typeof raw === 'string' ? raw : raw.toString('utf8');
157
+ const withoutBom = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
158
+ return withoutBom.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n');
159
+ }
160
+
161
+ export function parseDelimitedLine(line: string, delimiter = ','): string[] {
162
+ const out: string[] = [];
163
+ let field = '';
164
+ let quoted = false;
165
+ for (let i = 0; i < line.length; i += 1) {
166
+ const ch = line[i]!;
167
+ if (quoted) {
168
+ if (ch === '"' && line[i + 1] === '"') {
169
+ field += '"';
170
+ i += 1;
171
+ } else if (ch === '"') {
172
+ quoted = false;
173
+ } else {
174
+ field += ch;
175
+ }
176
+ continue;
177
+ }
178
+ if (ch === '"') {
179
+ quoted = true;
180
+ continue;
181
+ }
182
+ if (ch === delimiter) {
183
+ out.push(field);
184
+ field = '';
185
+ continue;
186
+ }
187
+ field += ch;
188
+ }
189
+ out.push(field);
190
+ return out;
191
+ }
@@ -0,0 +1,99 @@
1
+ import { appendFile } from 'node:fs/promises';
2
+
3
+ import type { ExecutionContext, ItemStream, ItemWriter, WriterResult } from '../core';
4
+
5
+ import { readCheckpointValue, writeCheckpoint } from './checkpoint';
6
+ import { parseDelimitedLine } from './file-readers';
7
+
8
+ export interface JsonlFileItemWriterOptions {
9
+ readonly path: string;
10
+ readonly encoding?: BufferEncoding;
11
+ }
12
+
13
+ export class JsonlFileItemWriter<T = unknown> implements ItemWriter<T> {
14
+ constructor(private readonly options: JsonlFileItemWriterOptions) {}
15
+
16
+ async write(items: T[]): Promise<void> {
17
+ if (items.length === 0) return;
18
+ const body = `${items.map((item) => JSON.stringify(item)).join('\n')}\n`;
19
+ await appendFile(this.options.path, body, this.options.encoding ?? 'utf8');
20
+ }
21
+ }
22
+
23
+ export interface CsvFileItemWriterOptions<T extends Record<string, unknown>> {
24
+ readonly path: string;
25
+ readonly headers: readonly (keyof T & string)[];
26
+ readonly encoding?: BufferEncoding;
27
+ readonly delimiter?: string;
28
+ readonly checkpointKey?: string;
29
+ readonly writeHeader?: boolean;
30
+ }
31
+
32
+ export class CsvFileItemWriter<T extends Record<string, unknown>>
33
+ implements ItemWriter<T>, ItemStream
34
+ {
35
+ private headerWritten = false;
36
+
37
+ constructor(private readonly options: CsvFileItemWriterOptions<T>) {}
38
+
39
+ open(context: ExecutionContext): void {
40
+ this.headerWritten = readCheckpointValue(
41
+ context,
42
+ this.checkpointKey,
43
+ 'headerWritten',
44
+ false,
45
+ );
46
+ }
47
+
48
+ async write(items: T[]): Promise<WriterResult | void> {
49
+ if (items.length === 0) return;
50
+ const lines: string[] = [];
51
+ if ((this.options.writeHeader ?? true) && !this.headerWritten) {
52
+ lines.push(this.options.headers.map((h) => escapeCsvValue(h, this.delimiter)).join(this.delimiter));
53
+ this.headerWritten = true;
54
+ }
55
+ for (const item of items) {
56
+ lines.push(
57
+ this.options.headers
58
+ .map((h) => escapeCsvValue(item[h], this.delimiter))
59
+ .join(this.delimiter),
60
+ );
61
+ }
62
+ await appendFile(
63
+ this.options.path,
64
+ `${lines.join('\n')}\n`,
65
+ this.options.encoding ?? 'utf8',
66
+ );
67
+ }
68
+
69
+ update(context: ExecutionContext): ExecutionContext {
70
+ return writeCheckpoint(context, this.checkpointKey, {
71
+ headerWritten: this.headerWritten,
72
+ });
73
+ }
74
+
75
+ close(): void {
76
+ return undefined;
77
+ }
78
+
79
+ private get checkpointKey(): string {
80
+ return this.options.checkpointKey ?? `csv-writer:${this.options.path}`;
81
+ }
82
+
83
+ private get delimiter(): string {
84
+ return this.options.delimiter ?? ',';
85
+ }
86
+ }
87
+
88
+ export function escapeCsvValue(value: unknown, delimiter = ','): string {
89
+ const text = value === null || value === undefined ? '' : String(value);
90
+ if (
91
+ text.includes('"') ||
92
+ text.includes('\n') ||
93
+ text.includes('\r') ||
94
+ parseDelimitedLine(text, delimiter).length > 1
95
+ ) {
96
+ return `"${text.replace(/"/g, '""')}"`;
97
+ }
98
+ return text;
99
+ }
@@ -0,0 +1,5 @@
1
+ export * from './checkpoint';
2
+ export * from './file-readers';
3
+ export * from './file-writers';
4
+ export * from './s3';
5
+ export * from './database';
package/src/io/s3.ts ADDED
@@ -0,0 +1,117 @@
1
+ import type { ExecutionContext, ItemReader, ItemStream, ItemWriter } from '../core';
2
+
3
+ import { readCheckpointNumber, writeCheckpoint } from './checkpoint';
4
+ import { splitLines } from './file-readers';
5
+
6
+ export interface S3ObjectLocation {
7
+ readonly bucket: string;
8
+ readonly key: string;
9
+ }
10
+
11
+ export interface S3GetObjectInput extends S3ObjectLocation {}
12
+
13
+ export interface S3PutObjectInput extends S3ObjectLocation {
14
+ readonly body: string | Uint8Array;
15
+ readonly contentType?: string;
16
+ }
17
+
18
+ export interface S3ObjectClient {
19
+ getObject(input: S3GetObjectInput): Promise<{ readonly body: string | Uint8Array }>;
20
+ putObject(input: S3PutObjectInput): Promise<void>;
21
+ }
22
+
23
+ export interface S3JsonlItemReaderOptions<T> extends S3ObjectLocation {
24
+ readonly client: S3ObjectClient;
25
+ readonly checkpointKey?: string;
26
+ readonly mapItem?: (item: unknown, lineIndex: number) => T | Promise<T>;
27
+ }
28
+
29
+ export class S3JsonlItemReader<T = unknown> implements ItemReader<T>, ItemStream {
30
+ private lines: string[] = [];
31
+ private index = 0;
32
+
33
+ constructor(private readonly options: S3JsonlItemReaderOptions<T>) {}
34
+
35
+ async open(context: ExecutionContext): Promise<void> {
36
+ const object = await this.options.client.getObject({
37
+ bucket: this.options.bucket,
38
+ key: this.options.key,
39
+ });
40
+ this.lines = splitLines(bodyToString(object.body));
41
+ this.index = readCheckpointNumber(context, this.checkpointKey, 'index', 0);
42
+ }
43
+
44
+ async read(): Promise<T | null> {
45
+ while (this.index < this.lines.length) {
46
+ const lineIndex = this.index;
47
+ const line = this.lines[this.index]!;
48
+ this.index += 1;
49
+ if (line.trim().length === 0) continue;
50
+ const parsed = JSON.parse(line) as unknown;
51
+ return this.options.mapItem !== undefined
52
+ ? this.options.mapItem(parsed, lineIndex)
53
+ : (parsed as T);
54
+ }
55
+ return null;
56
+ }
57
+
58
+ update(context: ExecutionContext): ExecutionContext {
59
+ return writeCheckpoint(context, this.checkpointKey, { index: this.index });
60
+ }
61
+
62
+ close(): void {
63
+ this.lines = [];
64
+ }
65
+
66
+ private get checkpointKey(): string {
67
+ return this.options.checkpointKey ?? `s3-jsonl:${this.options.bucket}/${this.options.key}`;
68
+ }
69
+ }
70
+
71
+ export interface S3ChunkJsonlItemWriterOptions {
72
+ readonly client: S3ObjectClient;
73
+ readonly bucket: string;
74
+ readonly keyPrefix: string;
75
+ readonly checkpointKey?: string;
76
+ }
77
+
78
+ export class S3ChunkJsonlItemWriter<T = unknown> implements ItemWriter<T>, ItemStream {
79
+ private chunkIndex = 0;
80
+
81
+ constructor(private readonly options: S3ChunkJsonlItemWriterOptions) {}
82
+
83
+ open(context: ExecutionContext): void {
84
+ this.chunkIndex = readCheckpointNumber(context, this.checkpointKey, 'chunkIndex', 0);
85
+ }
86
+
87
+ async write(items: T[]): Promise<void> {
88
+ if (items.length === 0) return;
89
+ const key = `${this.options.keyPrefix.replace(/\/+$/g, '')}/chunk-${String(this.chunkIndex).padStart(6, '0')}.jsonl`;
90
+ const body = `${items.map((item) => JSON.stringify(item)).join('\n')}\n`;
91
+ await this.options.client.putObject({
92
+ bucket: this.options.bucket,
93
+ key,
94
+ body,
95
+ contentType: 'application/x-ndjson',
96
+ });
97
+ this.chunkIndex += 1;
98
+ }
99
+
100
+ update(context: ExecutionContext): ExecutionContext {
101
+ return writeCheckpoint(context, this.checkpointKey, {
102
+ chunkIndex: this.chunkIndex,
103
+ });
104
+ }
105
+
106
+ close(): void {
107
+ return undefined;
108
+ }
109
+
110
+ private get checkpointKey(): string {
111
+ return this.options.checkpointKey ?? `s3-jsonl-writer:${this.options.bucket}/${this.options.keyPrefix}`;
112
+ }
113
+ }
114
+
115
+ function bodyToString(body: string | Uint8Array): string {
116
+ return typeof body === 'string' ? body : Buffer.from(body).toString('utf8');
117
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Reference built-in listeners — drop-in `Injectable` classes that mirror common
3
+ * batch lifecycle conventions (logging, metrics, timing). Each listener exposes
4
+ * the lifecycle methods consumed by `ListenerInvoker` and uses the canonical
5
+ * `ResolverMap` key format (`${phase}:${kind}:${name}`), so a user can simply
6
+ * instantiate one of these classes and register the bound methods under the
7
+ * desired phase/kind pairs.
8
+ *
9
+ * The classes are intentionally framework-agnostic — they do not depend on
10
+ * the execution pipeline, the `ResolverMap` shape, or any module wiring. They
11
+ * only depend on `@nestjs/common` for `Logger` / `Injectable`.
12
+ */
13
+ import { Injectable, Logger } from '@nestjs/common';
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // LoggingListener
17
+ // ---------------------------------------------------------------------------
18
+
19
+ /**
20
+ * Emits a one-line `log` / `warn` entry for every lifecycle event. The method
21
+ * names match the 7 `LifecyclePhaseKind` values plus the 3 `SkipSubKind`
22
+ * variants, so callers can register any of them under a `ResolverMap` key
23
+ * like `before:step:LoggingListener` and the invoker will dispatch correctly.
24
+ */
25
+ @Injectable()
26
+ export class LoggingListener {
27
+ private readonly logger = new Logger(LoggingListener.name);
28
+
29
+ // -- Job -----------------------------------------------------------------
30
+ async beforeJob(ctx: { jobExecutionId: string }): Promise<void> {
31
+ this.logger.log(`Job ${ctx.jobExecutionId} starting`);
32
+ }
33
+
34
+ async afterJob(
35
+ ctx: { jobExecutionId: string },
36
+ result: { status: string },
37
+ ): Promise<void> {
38
+ this.logger.log(`Job ${ctx.jobExecutionId} ${result.status}`);
39
+ }
40
+
41
+ // -- Step ----------------------------------------------------------------
42
+ async beforeStep(ctx: {
43
+ jobExecutionId: string;
44
+ stepExecutionId: string;
45
+ }): Promise<void> {
46
+ this.logger.log(`Step ${ctx.stepExecutionId} starting`);
47
+ }
48
+
49
+ async afterStep(
50
+ ctx: { jobExecutionId: string; stepExecutionId: string },
51
+ result: { status: string; exitCode: string },
52
+ ): Promise<void> {
53
+ this.logger.log(
54
+ `Step ${ctx.stepExecutionId} ${result.status} (${result.exitCode})`,
55
+ );
56
+ }
57
+
58
+ // -- Skip ----------------------------------------------------------------
59
+ async onSkipInRead(err: unknown, item: unknown): Promise<void> {
60
+ this.logger.warn(
61
+ `Skipped read: ${(err as Error).message} (item=${String(item)})`,
62
+ );
63
+ }
64
+
65
+ async onSkipInProcess(item: unknown, err: unknown): Promise<void> {
66
+ this.logger.warn(
67
+ `Skipped process: ${(err as Error).message} (item=${String(item)})`,
68
+ );
69
+ }
70
+
71
+ async onSkipInWrite(items: unknown[], err: unknown): Promise<void> {
72
+ this.logger.warn(
73
+ `Skipped write of ${items.length} items: ${(err as Error).message}`,
74
+ );
75
+ }
76
+ }
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // MetricsListener
80
+ // ---------------------------------------------------------------------------
81
+
82
+ /**
83
+ * Per-step read / write / skip counters. The counts are keyed by
84
+ * `stepExecutionId`, so multiple step executions within the same job are
85
+ * tracked independently. Callers can read the latest counts via
86
+ * `getCounts(stepExecutionId)`.
87
+ */
88
+ @Injectable()
89
+ export class MetricsListener {
90
+ private readonly stepCounts = new Map<
91
+ string,
92
+ { read: number; write: number; skip: number }
93
+ >();
94
+
95
+ /**
96
+ * Store the counts reported by the step result. Missing fields default to 0
97
+ * so a partial result (e.g. a tasklet step that has no read/write/skip
98
+ * counts) does not pollute the metric with `NaN`/`undefined`.
99
+ */
100
+ async afterStep(
101
+ ctx: { stepExecutionId: string },
102
+ result: {
103
+ readCount?: number;
104
+ writeCount?: number;
105
+ skipCount?: number;
106
+ status: string;
107
+ },
108
+ ): Promise<void> {
109
+ this.stepCounts.set(ctx.stepExecutionId, {
110
+ read: result.readCount ?? 0,
111
+ write: result.writeCount ?? 0,
112
+ skip: result.skipCount ?? 0,
113
+ });
114
+ }
115
+
116
+ /** Returns the latest recorded counts for the given step, or `undefined` if
117
+ * the step has not been observed yet. */
118
+ getCounts(
119
+ stepExecutionId: string,
120
+ ): { read: number; write: number; skip: number } | undefined {
121
+ return this.stepCounts.get(stepExecutionId);
122
+ }
123
+ }
124
+
125
+ // ---------------------------------------------------------------------------
126
+ // TimingListener
127
+ // ---------------------------------------------------------------------------
128
+
129
+ /**
130
+ * Records the wall-clock duration of each step. `beforeStep` captures
131
+ * `Date.now()`; `afterStep` returns the elapsed milliseconds (or 0 if no
132
+ * matching `beforeStep` was observed — this keeps the listener idempotent
133
+ * even when invoked out of order, e.g. after a process restart that replayed
134
+ * a partial log).
135
+ */
136
+ @Injectable()
137
+ export class TimingListener {
138
+ private readonly startTimes = new Map<string, number>();
139
+
140
+ async beforeStep(ctx: { stepExecutionId: string }): Promise<void> {
141
+ this.startTimes.set(ctx.stepExecutionId, Date.now());
142
+ }
143
+
144
+ async afterStep(ctx: { stepExecutionId: string }): Promise<number> {
145
+ const start = this.startTimes.get(ctx.stepExecutionId);
146
+ if (start !== undefined) {
147
+ return Date.now() - start;
148
+ }
149
+ return 0;
150
+ }
151
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Public surface for the reference built-in listeners.
3
+ *
4
+ * Re-exports `LoggingListener`, `MetricsListener`, and `TimingListener` so
5
+ * consumers can do `import { LoggingListener } from '@nest-batch/core'`.
6
+ */
7
+ export * from './builtin-listeners';