nvent 0.4.4 → 0.5.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 (293) hide show
  1. package/dist/module.d.mts +4 -185
  2. package/dist/module.json +3 -3
  3. package/dist/module.mjs +451 -257
  4. package/dist/runtime/adapters/base/index.d.ts +6 -0
  5. package/dist/runtime/adapters/base/index.js +1 -0
  6. package/dist/runtime/adapters/base/store-validator.d.ts +48 -0
  7. package/dist/runtime/adapters/base/store-validator.js +147 -0
  8. package/dist/runtime/adapters/builtin/file-queue.d.ts +67 -0
  9. package/dist/runtime/adapters/builtin/file-queue.js +499 -0
  10. package/dist/runtime/adapters/builtin/file-store.d.ts +32 -0
  11. package/dist/runtime/adapters/builtin/file-store.js +206 -0
  12. package/dist/runtime/adapters/builtin/file-stream.d.ts +39 -0
  13. package/dist/runtime/adapters/builtin/file-stream.js +56 -0
  14. package/dist/runtime/adapters/builtin/index.d.ts +10 -0
  15. package/dist/runtime/adapters/builtin/index.js +5 -0
  16. package/dist/runtime/adapters/builtin/memory-queue.d.ts +52 -0
  17. package/dist/runtime/adapters/builtin/memory-queue.js +243 -0
  18. package/dist/runtime/adapters/builtin/memory-store.d.ts +68 -0
  19. package/dist/runtime/adapters/builtin/memory-store.js +333 -0
  20. package/dist/runtime/adapters/builtin/memory-stream.d.ts +21 -0
  21. package/dist/runtime/adapters/builtin/memory-stream.js +56 -0
  22. package/dist/runtime/adapters/factory.d.ts +31 -0
  23. package/dist/runtime/adapters/factory.js +134 -0
  24. package/dist/runtime/adapters/index.d.ts +8 -0
  25. package/dist/runtime/adapters/index.js +3 -0
  26. package/dist/runtime/adapters/interfaces/index.d.ts +11 -0
  27. package/dist/runtime/adapters/interfaces/index.js +3 -0
  28. package/dist/runtime/adapters/interfaces/queue.d.ts +150 -0
  29. package/dist/runtime/adapters/interfaces/store.d.ts +297 -0
  30. package/dist/runtime/adapters/interfaces/stream.d.ts +62 -0
  31. package/dist/runtime/adapters/registry.d.ts +85 -0
  32. package/dist/runtime/adapters/registry.js +161 -0
  33. package/dist/runtime/config/index.d.ts +29 -0
  34. package/dist/runtime/config/index.js +175 -0
  35. package/dist/runtime/config/types.d.ts +397 -0
  36. package/dist/runtime/config/types.js +0 -0
  37. package/dist/runtime/{server-utils/events → events}/eventBus.d.ts +1 -1
  38. package/dist/runtime/events/types.d.ts +145 -0
  39. package/dist/runtime/events/types.js +0 -0
  40. package/dist/runtime/events/utils/scheduleTrigger.d.ts +8 -0
  41. package/dist/runtime/events/utils/scheduleTrigger.js +69 -0
  42. package/dist/runtime/events/utils/stallDetector.d.ts +140 -0
  43. package/dist/runtime/events/utils/stallDetector.js +436 -0
  44. package/dist/runtime/events/utils/triggerRuntime.d.ts +58 -0
  45. package/dist/runtime/events/utils/triggerRuntime.js +212 -0
  46. package/dist/runtime/{server-utils/events → events}/wiring/flowWiring.d.ts +12 -11
  47. package/dist/runtime/events/wiring/flowWiring.js +1020 -0
  48. package/dist/runtime/events/wiring/registry.d.ts +19 -0
  49. package/dist/runtime/events/wiring/registry.js +35 -0
  50. package/dist/runtime/events/wiring/stateWiring.d.ts +37 -0
  51. package/dist/runtime/events/wiring/stateWiring.js +92 -0
  52. package/dist/runtime/events/wiring/streamWiring.d.ts +36 -0
  53. package/dist/runtime/events/wiring/streamWiring.js +156 -0
  54. package/dist/runtime/events/wiring/triggerWiring.d.ts +21 -0
  55. package/dist/runtime/events/wiring/triggerWiring.js +412 -0
  56. package/dist/runtime/nitro/plugins/00.adapters.d.ts +14 -0
  57. package/dist/runtime/nitro/plugins/00.adapters.js +73 -0
  58. package/dist/runtime/nitro/plugins/02.workers.js +63 -0
  59. package/dist/runtime/nitro/plugins/03.triggers.d.ts +12 -0
  60. package/dist/runtime/nitro/plugins/03.triggers.js +55 -0
  61. package/dist/runtime/nitro/routes/webhook.await.d.ts +23 -0
  62. package/dist/runtime/nitro/routes/webhook.await.js +90 -0
  63. package/dist/runtime/nitro/routes/webhook.trigger.d.ts +69 -0
  64. package/dist/runtime/nitro/routes/webhook.trigger.js +64 -0
  65. package/dist/runtime/nitro/utils/adapters.d.ts +66 -0
  66. package/dist/runtime/nitro/utils/adapters.js +51 -0
  67. package/dist/runtime/nitro/utils/awaitPatterns/event.d.ts +15 -0
  68. package/dist/runtime/nitro/utils/awaitPatterns/event.js +120 -0
  69. package/dist/runtime/nitro/utils/awaitPatterns/index.d.ts +28 -0
  70. package/dist/runtime/nitro/utils/awaitPatterns/index.js +55 -0
  71. package/dist/runtime/nitro/utils/awaitPatterns/schedule.d.ts +16 -0
  72. package/dist/runtime/nitro/utils/awaitPatterns/schedule.js +78 -0
  73. package/dist/runtime/nitro/utils/awaitPatterns/time.d.ts +15 -0
  74. package/dist/runtime/nitro/utils/awaitPatterns/time.js +67 -0
  75. package/dist/runtime/nitro/utils/awaitPatterns/webhook.d.ts +15 -0
  76. package/dist/runtime/nitro/utils/awaitPatterns/webhook.js +120 -0
  77. package/dist/runtime/nitro/utils/defineFunction.d.ts +10 -0
  78. package/dist/runtime/nitro/utils/defineFunction.js +17 -0
  79. package/dist/runtime/nitro/utils/defineFunctionConfig.d.ts +310 -0
  80. package/dist/runtime/nitro/utils/defineFunctionConfig.js +3 -0
  81. package/dist/runtime/nitro/utils/defineHooks.d.ts +41 -0
  82. package/dist/runtime/nitro/utils/defineHooks.js +6 -0
  83. package/dist/runtime/nitro/utils/registerAdapter.d.ts +59 -0
  84. package/dist/runtime/nitro/utils/registerAdapter.js +13 -0
  85. package/dist/runtime/nitro/utils/useAwait.d.ts +71 -0
  86. package/dist/runtime/nitro/utils/useAwait.js +139 -0
  87. package/dist/runtime/{server-utils → nitro}/utils/useEventManager.d.ts +2 -2
  88. package/dist/runtime/{server-utils → nitro}/utils/useEventManager.js +1 -1
  89. package/dist/runtime/nitro/utils/useFlow.d.ts +68 -0
  90. package/dist/runtime/nitro/utils/useFlow.js +226 -0
  91. package/dist/runtime/nitro/utils/useHookRegistry.d.ts +34 -0
  92. package/dist/runtime/nitro/utils/useHookRegistry.js +25 -0
  93. package/dist/runtime/{server-utils → nitro}/utils/useNventLogger.js +2 -2
  94. package/dist/runtime/nitro/utils/useRunContext.d.ts +6 -0
  95. package/dist/runtime/nitro/utils/useRunContext.js +102 -0
  96. package/dist/runtime/nitro/utils/useStreamTopics.d.ts +83 -0
  97. package/dist/runtime/nitro/utils/useStreamTopics.js +94 -0
  98. package/dist/runtime/nitro/utils/useTrigger.d.ts +150 -0
  99. package/dist/runtime/nitro/utils/useTrigger.js +320 -0
  100. package/dist/runtime/scheduler/index.d.ts +33 -0
  101. package/dist/runtime/scheduler/index.js +38 -0
  102. package/dist/runtime/scheduler/scheduler.d.ts +113 -0
  103. package/dist/runtime/scheduler/scheduler.js +623 -0
  104. package/dist/runtime/scheduler/types.d.ts +116 -0
  105. package/dist/runtime/scheduler/types.js +0 -0
  106. package/dist/runtime/tsconfig.json +8 -0
  107. package/dist/runtime/worker/node/runner.d.ts +53 -0
  108. package/dist/runtime/worker/node/runner.js +327 -0
  109. package/dist/types.d.mts +2 -2
  110. package/package.json +16 -46
  111. package/LICENSE +0 -21
  112. package/README.md +0 -389
  113. package/dist/runtime/app/assets/vueflow.css +0 -1
  114. package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +0 -33
  115. package/dist/runtime/app/components/ConfirmDialog.vue +0 -121
  116. package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +0 -33
  117. package/dist/runtime/app/components/FlowDiagram.d.vue.ts +0 -64
  118. package/dist/runtime/app/components/FlowDiagram.vue +0 -338
  119. package/dist/runtime/app/components/FlowDiagram.vue.d.ts +0 -64
  120. package/dist/runtime/app/components/FlowNodeCard.d.vue.ts +0 -29
  121. package/dist/runtime/app/components/FlowNodeCard.vue +0 -156
  122. package/dist/runtime/app/components/FlowNodeCard.vue.d.ts +0 -29
  123. package/dist/runtime/app/components/FlowRunOverview.d.vue.ts +0 -9
  124. package/dist/runtime/app/components/FlowRunOverview.vue +0 -291
  125. package/dist/runtime/app/components/FlowRunOverview.vue.d.ts +0 -9
  126. package/dist/runtime/app/components/FlowRunStatusBadge.d.vue.ts +0 -14
  127. package/dist/runtime/app/components/FlowRunStatusBadge.vue +0 -60
  128. package/dist/runtime/app/components/FlowRunStatusBadge.vue.d.ts +0 -14
  129. package/dist/runtime/app/components/FlowRunTimeline.d.vue.ts +0 -12
  130. package/dist/runtime/app/components/FlowRunTimeline.vue +0 -127
  131. package/dist/runtime/app/components/FlowRunTimeline.vue.d.ts +0 -12
  132. package/dist/runtime/app/components/FlowScheduleDialog.d.vue.ts +0 -16
  133. package/dist/runtime/app/components/FlowScheduleDialog.vue +0 -226
  134. package/dist/runtime/app/components/FlowScheduleDialog.vue.d.ts +0 -16
  135. package/dist/runtime/app/components/FlowSchedulesList.d.vue.ts +0 -12
  136. package/dist/runtime/app/components/FlowSchedulesList.vue +0 -99
  137. package/dist/runtime/app/components/FlowSchedulesList.vue.d.ts +0 -12
  138. package/dist/runtime/app/components/JobScheduling.d.vue.ts +0 -6
  139. package/dist/runtime/app/components/JobScheduling.vue +0 -203
  140. package/dist/runtime/app/components/JobScheduling.vue.d.ts +0 -6
  141. package/dist/runtime/app/components/ListItem.d.vue.ts +0 -23
  142. package/dist/runtime/app/components/ListItem.vue +0 -70
  143. package/dist/runtime/app/components/ListItem.vue.d.ts +0 -23
  144. package/dist/runtime/app/components/QueueConfigDetails.d.vue.ts +0 -45
  145. package/dist/runtime/app/components/QueueConfigDetails.vue +0 -412
  146. package/dist/runtime/app/components/QueueConfigDetails.vue.d.ts +0 -45
  147. package/dist/runtime/app/components/StatCounter.d.vue.ts +0 -9
  148. package/dist/runtime/app/components/StatCounter.vue +0 -25
  149. package/dist/runtime/app/components/StatCounter.vue.d.ts +0 -9
  150. package/dist/runtime/app/components/TimelineList.d.vue.ts +0 -7
  151. package/dist/runtime/app/components/TimelineList.vue +0 -210
  152. package/dist/runtime/app/components/TimelineList.vue.d.ts +0 -7
  153. package/dist/runtime/app/components/nhealth/component-router.d.vue.ts +0 -46
  154. package/dist/runtime/app/components/nhealth/component-router.vue +0 -26
  155. package/dist/runtime/app/components/nhealth/component-router.vue.d.ts +0 -46
  156. package/dist/runtime/app/components/nhealth/component-shell.d.vue.ts +0 -24
  157. package/dist/runtime/app/components/nhealth/component-shell.vue +0 -89
  158. package/dist/runtime/app/components/nhealth/component-shell.vue.d.ts +0 -24
  159. package/dist/runtime/app/composables/useAnalyzedFlows.d.ts +0 -14
  160. package/dist/runtime/app/composables/useAnalyzedFlows.js +0 -8
  161. package/dist/runtime/app/composables/useComponentRouter.d.ts +0 -38
  162. package/dist/runtime/app/composables/useComponentRouter.js +0 -240
  163. package/dist/runtime/app/composables/useFlowRunTimeline.d.ts +0 -80
  164. package/dist/runtime/app/composables/useFlowRunTimeline.js +0 -68
  165. package/dist/runtime/app/composables/useFlowRuns.d.ts +0 -18
  166. package/dist/runtime/app/composables/useFlowRuns.js +0 -32
  167. package/dist/runtime/app/composables/useFlowRunsInfinite.d.ts +0 -24
  168. package/dist/runtime/app/composables/useFlowRunsInfinite.js +0 -123
  169. package/dist/runtime/app/composables/useFlowRunsPolling.d.ts +0 -9
  170. package/dist/runtime/app/composables/useFlowRunsPolling.js +0 -33
  171. package/dist/runtime/app/composables/useFlowState.d.ts +0 -125
  172. package/dist/runtime/app/composables/useFlowState.js +0 -211
  173. package/dist/runtime/app/composables/useFlowWebSocket.d.ts +0 -27
  174. package/dist/runtime/app/composables/useFlowWebSocket.js +0 -205
  175. package/dist/runtime/app/composables/useFlowsNavigation.d.ts +0 -10
  176. package/dist/runtime/app/composables/useFlowsNavigation.js +0 -58
  177. package/dist/runtime/app/composables/useQueueJobs.d.ts +0 -26
  178. package/dist/runtime/app/composables/useQueueJobs.js +0 -20
  179. package/dist/runtime/app/composables/useQueueUpdates.d.ts +0 -26
  180. package/dist/runtime/app/composables/useQueueUpdates.js +0 -122
  181. package/dist/runtime/app/composables/useQueues.d.ts +0 -45
  182. package/dist/runtime/app/composables/useQueues.js +0 -26
  183. package/dist/runtime/app/composables/useQueuesLive.d.ts +0 -19
  184. package/dist/runtime/app/composables/useQueuesLive.js +0 -143
  185. package/dist/runtime/app/pages/flows/index.d.vue.ts +0 -3
  186. package/dist/runtime/app/pages/flows/index.vue +0 -645
  187. package/dist/runtime/app/pages/flows/index.vue.d.ts +0 -3
  188. package/dist/runtime/app/pages/index.d.vue.ts +0 -3
  189. package/dist/runtime/app/pages/index.vue +0 -34
  190. package/dist/runtime/app/pages/index.vue.d.ts +0 -3
  191. package/dist/runtime/app/pages/queues/index.d.vue.ts +0 -3
  192. package/dist/runtime/app/pages/queues/index.vue +0 -229
  193. package/dist/runtime/app/pages/queues/index.vue.d.ts +0 -3
  194. package/dist/runtime/app/pages/queues/job.d.vue.ts +0 -3
  195. package/dist/runtime/app/pages/queues/job.vue +0 -262
  196. package/dist/runtime/app/pages/queues/job.vue.d.ts +0 -3
  197. package/dist/runtime/app/pages/queues/jobs.d.vue.ts +0 -3
  198. package/dist/runtime/app/pages/queues/jobs.vue +0 -291
  199. package/dist/runtime/app/pages/queues/jobs.vue.d.ts +0 -3
  200. package/dist/runtime/app/plugins/vueflow.client.d.ts +0 -2
  201. package/dist/runtime/app/plugins/vueflow.client.js +0 -11
  202. package/dist/runtime/constants.d.ts +0 -11
  203. package/dist/runtime/constants.js +0 -11
  204. package/dist/runtime/schema.d.ts +0 -37
  205. package/dist/runtime/schema.js +0 -20
  206. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +0 -10
  207. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +0 -44
  208. package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +0 -7
  209. package/dist/runtime/server/api/_flows/[name]/runs.get.js +0 -53
  210. package/dist/runtime/server/api/_flows/[name]/schedule.post.js +0 -57
  211. package/dist/runtime/server/api/_flows/[name]/schedules/[id].delete.d.ts +0 -2
  212. package/dist/runtime/server/api/_flows/[name]/schedules/[id].delete.js +0 -42
  213. package/dist/runtime/server/api/_flows/[name]/schedules.get.d.ts +0 -2
  214. package/dist/runtime/server/api/_flows/[name]/schedules.get.js +0 -48
  215. package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +0 -2
  216. package/dist/runtime/server/api/_flows/[name]/start.post.js +0 -9
  217. package/dist/runtime/server/api/_flows/index.get.d.ts +0 -6
  218. package/dist/runtime/server/api/_flows/index.get.js +0 -5
  219. package/dist/runtime/server/api/_flows/ws.d.ts +0 -60
  220. package/dist/runtime/server/api/_flows/ws.js +0 -188
  221. package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +0 -2
  222. package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +0 -9
  223. package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +0 -2
  224. package/dist/runtime/server/api/_queues/[name]/job/index.get.js +0 -18
  225. package/dist/runtime/server/api/_queues/index.get.d.ts +0 -2
  226. package/dist/runtime/server/api/_queues/index.get.js +0 -63
  227. package/dist/runtime/server/api/_queues/ws.d.ts +0 -48
  228. package/dist/runtime/server/api/_queues/ws.js +0 -205
  229. package/dist/runtime/server/plugins/00.event-store.d.ts +0 -13
  230. package/dist/runtime/server/plugins/00.event-store.js +0 -16
  231. package/dist/runtime/server/plugins/flow-management.d.ts +0 -13
  232. package/dist/runtime/server/plugins/flow-management.js +0 -65
  233. package/dist/runtime/server/plugins/queue-management.d.ts +0 -2
  234. package/dist/runtime/server/plugins/queue-management.js +0 -27
  235. package/dist/runtime/server/plugins/state-cleanup.d.ts +0 -11
  236. package/dist/runtime/server/plugins/state-cleanup.js +0 -93
  237. package/dist/runtime/server/plugins/worker-management.d.ts +0 -2
  238. package/dist/runtime/server/plugins/worker-management.js +0 -33
  239. package/dist/runtime/server/tsconfig.json +0 -3
  240. package/dist/runtime/server-utils/events/adapters/fileAdapter.d.ts +0 -2
  241. package/dist/runtime/server-utils/events/adapters/fileAdapter.js +0 -382
  242. package/dist/runtime/server-utils/events/adapters/memoryAdapter.d.ts +0 -2
  243. package/dist/runtime/server-utils/events/adapters/memoryAdapter.js +0 -171
  244. package/dist/runtime/server-utils/events/adapters/redis/redisAdapter.d.ts +0 -2
  245. package/dist/runtime/server-utils/events/adapters/redis/redisAdapter.js +0 -348
  246. package/dist/runtime/server-utils/events/adapters/redis/redisPubSubGateway.d.ts +0 -30
  247. package/dist/runtime/server-utils/events/adapters/redis/redisPubSubGateway.js +0 -82
  248. package/dist/runtime/server-utils/events/eventStoreFactory.d.ts +0 -19
  249. package/dist/runtime/server-utils/events/eventStoreFactory.js +0 -44
  250. package/dist/runtime/server-utils/events/streamNames.d.ts +0 -17
  251. package/dist/runtime/server-utils/events/streamNames.js +0 -17
  252. package/dist/runtime/server-utils/events/types.d.ts +0 -63
  253. package/dist/runtime/server-utils/events/wiring/flowWiring.js +0 -409
  254. package/dist/runtime/server-utils/events/wiring/registry.d.ts +0 -10
  255. package/dist/runtime/server-utils/events/wiring/registry.js +0 -24
  256. package/dist/runtime/server-utils/queue/adapters/bullmq.d.ts +0 -18
  257. package/dist/runtime/server-utils/queue/adapters/bullmq.js +0 -164
  258. package/dist/runtime/server-utils/queue/queueFactory.d.ts +0 -3
  259. package/dist/runtime/server-utils/queue/queueFactory.js +0 -10
  260. package/dist/runtime/server-utils/queue/types.d.ts +0 -47
  261. package/dist/runtime/server-utils/state/adapters/redis.d.ts +0 -2
  262. package/dist/runtime/server-utils/state/adapters/redis.js +0 -42
  263. package/dist/runtime/server-utils/state/stateFactory.d.ts +0 -3
  264. package/dist/runtime/server-utils/state/stateFactory.js +0 -17
  265. package/dist/runtime/server-utils/state/types.d.ts +0 -23
  266. package/dist/runtime/server-utils/utils/defineQueueConfig.d.ts +0 -154
  267. package/dist/runtime/server-utils/utils/defineQueueConfig.js +0 -2
  268. package/dist/runtime/server-utils/utils/defineQueueWorker.d.ts +0 -10
  269. package/dist/runtime/server-utils/utils/defineQueueWorker.js +0 -17
  270. package/dist/runtime/server-utils/utils/useEventStore.d.ts +0 -20
  271. package/dist/runtime/server-utils/utils/useEventStore.js +0 -119
  272. package/dist/runtime/server-utils/utils/useFlowEngine.d.ts +0 -9
  273. package/dist/runtime/server-utils/utils/useFlowEngine.js +0 -44
  274. package/dist/runtime/server-utils/utils/useLogs.d.ts +0 -41
  275. package/dist/runtime/server-utils/utils/useLogs.js +0 -74
  276. package/dist/runtime/server-utils/utils/useQueue.d.ts +0 -31
  277. package/dist/runtime/server-utils/utils/useQueue.js +0 -24
  278. package/dist/runtime/server-utils/worker/adapter.d.ts +0 -4
  279. package/dist/runtime/server-utils/worker/adapter.js +0 -66
  280. package/dist/runtime/server-utils/worker/runner/node.d.ts +0 -27
  281. package/dist/runtime/server-utils/worker/runner/node.js +0 -196
  282. package/dist/runtime/types.d.ts +0 -132
  283. /package/dist/runtime/{server-utils/events/types.js → adapters/interfaces/queue.js} +0 -0
  284. /package/dist/runtime/{server-utils/queue/types.js → adapters/interfaces/store.js} +0 -0
  285. /package/dist/runtime/{server-utils/state/types.js → adapters/interfaces/stream.js} +0 -0
  286. /package/dist/runtime/{server-utils/events → events}/eventBus.js +0 -0
  287. /package/dist/runtime/{server/plugins/00.ws-lifecycle.d.ts → nitro/plugins/01.ws-lifecycle.d.ts} +0 -0
  288. /package/dist/runtime/{server/plugins/00.ws-lifecycle.js → nitro/plugins/01.ws-lifecycle.js} +0 -0
  289. /package/dist/runtime/{server/api/_flows/[name]/schedule.post.d.ts → nitro/plugins/02.workers.d.ts} +0 -0
  290. /package/dist/runtime/{server-utils → nitro}/utils/useNventLogger.d.ts +0 -0
  291. /package/dist/runtime/{server-utils → nitro}/utils/wsPeerManager.d.ts +0 -0
  292. /package/dist/runtime/{server-utils → nitro}/utils/wsPeerManager.js +0 -0
  293. /package/dist/runtime/{python → worker/python}/get_config.py +0 -0
@@ -0,0 +1,623 @@
1
+ import { CronJob } from "cron";
2
+ import { getEventBus } from "../events/eventBus.js";
3
+ import { resolveTimeAwait } from "../nitro/utils/awaitPatterns/time.js";
4
+ import { resolveScheduleAwait } from "../nitro/utils/awaitPatterns/schedule.js";
5
+ import { useNventLogger } from "#imports";
6
+ export class Scheduler {
7
+ store;
8
+ keyPrefix;
9
+ lockTTL;
10
+ instanceId;
11
+ useIndexLocking;
12
+ jobs = /* @__PURE__ */ new Map();
13
+ jobConfigs = /* @__PURE__ */ new Map();
14
+ lockRenewalTimers = /* @__PURE__ */ new Map();
15
+ started = false;
16
+ logger = useNventLogger("scheduler");
17
+ constructor(options) {
18
+ this.store = options.store;
19
+ this.keyPrefix = options.keyPrefix || "nvent:scheduler";
20
+ this.lockTTL = options.lockTTL || 3e5;
21
+ this.instanceId = options.instanceId || `instance-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
22
+ this.useIndexLocking = options.useIndexLocking !== false;
23
+ }
24
+ async schedule(job) {
25
+ this.jobConfigs.set(job.id, job);
26
+ await this.persistJob(job);
27
+ if (job.type === "cron" && job.cron) {
28
+ const cronJob = new CronJob(
29
+ job.cron,
30
+ async () => {
31
+ await this.executeWithLock(job);
32
+ },
33
+ null,
34
+ job.enabled !== false && this.started,
35
+ job.timezone || "UTC"
36
+ );
37
+ this.jobs.set(job.id, cronJob);
38
+ const nextDate = cronJob.nextDate();
39
+ if (nextDate) {
40
+ job.nextRun = nextDate.toMillis();
41
+ await this.updateJobStats(job.id, { nextRun: job.nextRun });
42
+ }
43
+ return job.id;
44
+ }
45
+ if (job.type === "interval" && job.interval) {
46
+ if (job.enabled !== false && this.started) {
47
+ const intervalId = setInterval(
48
+ async () => {
49
+ await this.executeWithLock(job);
50
+ },
51
+ job.interval
52
+ );
53
+ this.jobs.set(job.id, intervalId);
54
+ }
55
+ job.nextRun = Date.now() + job.interval;
56
+ await this.updateJobStats(job.id, { nextRun: job.nextRun });
57
+ return job.id;
58
+ }
59
+ if (job.type === "one-time" && job.executeAt) {
60
+ const delay = job.executeAt - Date.now();
61
+ if (delay > 0) {
62
+ const timeoutId = setTimeout(
63
+ async () => {
64
+ await this.executeWithLock(job);
65
+ await this.unschedule(job.id);
66
+ },
67
+ delay
68
+ );
69
+ this.jobs.set(job.id, timeoutId);
70
+ job.nextRun = job.executeAt;
71
+ await this.updateJobStats(job.id, { nextRun: job.nextRun });
72
+ } else {
73
+ await this.executeWithLock(job);
74
+ }
75
+ return job.id;
76
+ }
77
+ throw new Error(`Invalid job configuration: ${job.id}`);
78
+ }
79
+ /**
80
+ * Execute job with distributed lock
81
+ * Prevents multiple instances from running the same job
82
+ */
83
+ async executeWithLock(job) {
84
+ const lockAcquired = await this.acquireLock(job.id);
85
+ if (!lockAcquired) {
86
+ return;
87
+ }
88
+ try {
89
+ this.startLockRenewal(job.id);
90
+ await this.executeJob(job);
91
+ } catch (error) {
92
+ this.logger.error("Job failed", { jobId: job.id, error: error.message });
93
+ } finally {
94
+ this.stopLockRenewal(job.id);
95
+ await this.releaseLock(job.id).catch((err) => {
96
+ this.logger.error("Failed to release lock", { jobId: job.id, error: err.message });
97
+ });
98
+ }
99
+ }
100
+ async executeJob(job) {
101
+ const config = this.jobConfigs.get(job.id);
102
+ if (!config) return;
103
+ try {
104
+ const now = Date.now();
105
+ config.lastRun = now;
106
+ config.runCount = (config.runCount || 0) + 1;
107
+ await job.handler();
108
+ if (job.type === "cron" && job.cron) {
109
+ const cronJob = this.jobs.get(job.id);
110
+ if (cronJob instanceof CronJob) {
111
+ const nextDate = cronJob.nextDate();
112
+ if (nextDate) {
113
+ config.nextRun = nextDate.toMillis();
114
+ }
115
+ }
116
+ } else if (job.type === "interval" && job.interval) {
117
+ config.nextRun = Date.now() + job.interval;
118
+ }
119
+ await this.updateJobStats(job.id, {
120
+ lastRun: now,
121
+ nextRun: config.nextRun,
122
+ runCount: config.runCount
123
+ });
124
+ } catch (error) {
125
+ config.failCount = (config.failCount || 0) + 1;
126
+ await this.updateJobStats(job.id, {
127
+ failCount: config.failCount,
128
+ lastError: error instanceof Error ? error.message : String(error)
129
+ });
130
+ throw error;
131
+ }
132
+ }
133
+ /**
134
+ * Acquire distributed lock using store adapter
135
+ */
136
+ async acquireLock(jobId) {
137
+ const lockKey = `${this.keyPrefix}:lock:${jobId}`;
138
+ const now = Date.now();
139
+ const expiresAt = now + this.lockTTL;
140
+ if (this.useIndexLocking && this.store.index.add) {
141
+ try {
142
+ const lockIndex = `${this.keyPrefix}:locks`;
143
+ await this.store.index.add(lockIndex, jobId, expiresAt, {
144
+ instanceId: this.instanceId,
145
+ acquiredAt: now,
146
+ expiresAt
147
+ });
148
+ return true;
149
+ } catch {
150
+ if (this.store.index.get) {
151
+ const existing = await this.store.index.get(`${this.keyPrefix}:locks`, jobId);
152
+ if (existing && existing.score < now) {
153
+ if (this.store.index.delete) {
154
+ await this.store.index.delete(`${this.keyPrefix}:locks`, jobId);
155
+ return this.acquireLock(jobId);
156
+ }
157
+ }
158
+ }
159
+ return false;
160
+ }
161
+ } else {
162
+ try {
163
+ const existingLock = await this.store.kv.get(lockKey);
164
+ if (existingLock) {
165
+ if (existingLock.expiresAt < now) {
166
+ await this.store.kv.delete(lockKey);
167
+ return this.acquireLock(jobId);
168
+ }
169
+ return false;
170
+ }
171
+ const lock = {
172
+ jobId,
173
+ instanceId: this.instanceId,
174
+ acquiredAt: now,
175
+ expiresAt
176
+ };
177
+ await this.store.kv.set(lockKey, lock, Math.ceil(this.lockTTL / 1e3));
178
+ return true;
179
+ } catch (error) {
180
+ this.logger.error("Error acquiring lock", { jobId, error: error.message });
181
+ return false;
182
+ }
183
+ }
184
+ }
185
+ /**
186
+ * Release distributed lock
187
+ */
188
+ async releaseLock(jobId) {
189
+ if (this.useIndexLocking && this.store.index.delete) {
190
+ const lockIndex = `${this.keyPrefix}:locks`;
191
+ await this.store.index.delete(lockIndex, jobId);
192
+ } else {
193
+ const lockKey = `${this.keyPrefix}:lock:${jobId}`;
194
+ await this.store.kv.delete(lockKey);
195
+ }
196
+ }
197
+ /**
198
+ * Start periodic lock renewal (for long-running jobs)
199
+ */
200
+ startLockRenewal(jobId) {
201
+ const renewalInterval = this.lockTTL / 2;
202
+ const timer = setInterval(async () => {
203
+ try {
204
+ if (this.useIndexLocking && this.store.index.update) {
205
+ const lockIndex = `${this.keyPrefix}:locks`;
206
+ const expiresAt = Date.now() + this.lockTTL;
207
+ await this.store.index.update(lockIndex, jobId, {
208
+ expiresAt
209
+ });
210
+ } else {
211
+ const lockKey = `${this.keyPrefix}:lock:${jobId}`;
212
+ const lock = await this.store.kv.get(lockKey);
213
+ if (lock && lock.instanceId === this.instanceId) {
214
+ lock.expiresAt = Date.now() + this.lockTTL;
215
+ await this.store.kv.set(lockKey, lock, Math.ceil(this.lockTTL / 1e3));
216
+ }
217
+ }
218
+ } catch (error) {
219
+ this.logger.error("Error renewing lock", { jobId, error: error.message });
220
+ }
221
+ }, renewalInterval);
222
+ this.lockRenewalTimers.set(jobId, timer);
223
+ }
224
+ /**
225
+ * Stop lock renewal
226
+ */
227
+ stopLockRenewal(jobId) {
228
+ const timer = this.lockRenewalTimers.get(jobId);
229
+ if (timer) {
230
+ clearInterval(timer);
231
+ this.lockRenewalTimers.delete(jobId);
232
+ }
233
+ }
234
+ /**
235
+ * Persist job configuration
236
+ */
237
+ async persistJob(job) {
238
+ const jobKey = `${this.keyPrefix}:jobs:${job.id}`;
239
+ const now = Date.now();
240
+ const jobData = {
241
+ id: job.id,
242
+ name: job.name,
243
+ type: job.type,
244
+ cron: job.cron,
245
+ interval: job.interval,
246
+ executeAt: job.executeAt,
247
+ timezone: job.timezone || "UTC",
248
+ enabled: job.enabled !== false,
249
+ metadata: job.metadata,
250
+ persistedAt: now
251
+ };
252
+ await this.store.kv.set(jobKey, jobData);
253
+ if (this.store.index.add) {
254
+ try {
255
+ const jobIndex = `${this.keyPrefix}:jobs`;
256
+ await this.store.index.add(jobIndex, job.id, now, jobData);
257
+ } catch {
258
+ if (this.store.index.update) {
259
+ try {
260
+ const jobIndex = `${this.keyPrefix}:jobs`;
261
+ await this.store.index.update(jobIndex, job.id, jobData);
262
+ } catch (updateError) {
263
+ this.logger.error("Failed to persist job to index", { jobId: job.id, error: updateError.message });
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ /**
270
+ * Update job statistics
271
+ */
272
+ async updateJobStats(jobId, stats) {
273
+ const statsKey = `${this.keyPrefix}:stats:${jobId}`;
274
+ try {
275
+ const existing = await this.store.kv.get(statsKey) || {};
276
+ await this.store.kv.set(statsKey, {
277
+ ...existing,
278
+ ...stats
279
+ });
280
+ } catch (error) {
281
+ this.logger.error("Error updating stats", {
282
+ jobId,
283
+ error: error.message
284
+ });
285
+ }
286
+ }
287
+ async unschedule(jobId) {
288
+ const job = this.jobs.get(jobId);
289
+ if (job instanceof CronJob) {
290
+ job.stop();
291
+ } else if (job) {
292
+ clearTimeout(job);
293
+ clearInterval(job);
294
+ }
295
+ this.jobs.delete(jobId);
296
+ this.jobConfigs.delete(jobId);
297
+ await this.store.kv.delete(`${this.keyPrefix}:jobs:${jobId}`);
298
+ await this.store.kv.delete(`${this.keyPrefix}:stats:${jobId}`);
299
+ if (this.store.index.delete) {
300
+ try {
301
+ await this.store.index.delete(`${this.keyPrefix}:jobs`, jobId);
302
+ } catch {
303
+ }
304
+ }
305
+ await this.releaseLock(jobId);
306
+ return !!job;
307
+ }
308
+ /**
309
+ * Recover jobs from store on startup
310
+ * Critical for:
311
+ * - Restarts: Re-create in-memory schedulers
312
+ * - Horizontal scaling: New instances pick up existing jobs
313
+ * - Orphaned awaits: Resume flows waiting on schedules
314
+ */
315
+ async recoverJobs() {
316
+ this.logger.info("Recovering jobs from store");
317
+ try {
318
+ if (this.store.index.read) {
319
+ const jobIndex = `${this.keyPrefix}:jobs`;
320
+ const jobEntries = await this.store.index.read(jobIndex, { limit: 1e4 });
321
+ this.logger.info("Found jobs in index", { count: jobEntries.length });
322
+ for (const entry of jobEntries) {
323
+ const jobData = entry.metadata;
324
+ if (jobData) {
325
+ await this.recoverJob(jobData);
326
+ }
327
+ }
328
+ } else {
329
+ this.logger.warn("Store does not support index read. Job recovery limited.");
330
+ this.logger.warn("For full job recovery, use Redis or Postgres store adapter.");
331
+ await this.recoverWellKnownJobs();
332
+ }
333
+ } catch (error) {
334
+ this.logger.error("Error during job recovery", { error: error.message });
335
+ }
336
+ }
337
+ /**
338
+ * Recover a single job from persisted data
339
+ *
340
+ * IMPORTANT: This method reconstructs in-memory schedulers (CronJob/setInterval)
341
+ * WITHOUT calling schedule() to avoid re-persisting handler functions (which
342
+ * cannot be serialized). Handlers are reconstructed from metadata where possible.
343
+ */
344
+ async recoverJob(jobData) {
345
+ try {
346
+ if (this.jobs.has(jobData.id)) {
347
+ return;
348
+ }
349
+ if (jobData.enabled === false) {
350
+ this.logger.debug("Skipping disabled job", { jobId: jobData.id });
351
+ return;
352
+ }
353
+ if (jobData.metadata?.type === "schedule-trigger" && jobData.metadata?.triggerName) {
354
+ jobData.handler = async () => {
355
+ const logger = useNventLogger("scheduler");
356
+ const eventBus = getEventBus();
357
+ const triggerName = jobData.metadata?.triggerName;
358
+ const scheduleConfig = jobData.metadata?.scheduleConfig;
359
+ logger.debug("Schedule trigger fired", { trigger: triggerName });
360
+ await eventBus.publish({
361
+ type: "trigger.fired",
362
+ triggerName,
363
+ data: {
364
+ scheduledAt: Date.now(),
365
+ timezone: scheduleConfig?.timezone || "UTC"
366
+ }
367
+ });
368
+ };
369
+ } else if (jobData.metadata?.component === "await-pattern") {
370
+ const { awaitType, runId, stepName, flowName, position } = jobData.metadata;
371
+ if (awaitType === "time") {
372
+ jobData.handler = async () => {
373
+ await resolveTimeAwait(runId, stepName, flowName, position, { delayCompleted: true });
374
+ };
375
+ } else if (awaitType === "schedule") {
376
+ jobData.handler = async () => {
377
+ await resolveScheduleAwait(runId, stepName, flowName, position, { scheduledAt: Date.now() });
378
+ };
379
+ } else if (awaitType === "webhook") {
380
+ jobData.handler = async () => {
381
+ const eventBus = getEventBus();
382
+ const timeout = jobData.metadata?.timeout;
383
+ const timeoutAction = jobData.metadata?.timeoutAction || "fail";
384
+ this.logger.warn("Webhook await timeout", {
385
+ runId,
386
+ stepName,
387
+ flowName,
388
+ timeout,
389
+ timeoutAction
390
+ });
391
+ eventBus.publish({
392
+ type: "await.timeout",
393
+ flowName,
394
+ runId,
395
+ stepName,
396
+ position,
397
+ awaitType: "webhook",
398
+ timeoutAction,
399
+ data: {
400
+ timeout,
401
+ registeredAt: Date.now() - (timeout || 0),
402
+ timedOutAt: Date.now()
403
+ }
404
+ });
405
+ };
406
+ } else if (awaitType === "event") {
407
+ jobData.handler = async () => {
408
+ const eventBus = getEventBus();
409
+ const timeout = jobData.metadata?.timeout;
410
+ const timeoutAction = jobData.metadata?.timeoutAction || "fail";
411
+ const eventName = jobData.metadata?.eventName;
412
+ this.logger.warn("Event await timeout", {
413
+ runId,
414
+ stepName,
415
+ flowName,
416
+ eventName,
417
+ timeout,
418
+ timeoutAction
419
+ });
420
+ eventBus.publish({
421
+ type: "await.timeout",
422
+ flowName,
423
+ runId,
424
+ stepName,
425
+ position,
426
+ awaitType: "event",
427
+ timeoutAction,
428
+ data: {
429
+ eventName,
430
+ timeout,
431
+ registeredAt: Date.now() - (timeout || 0),
432
+ timedOutAt: Date.now()
433
+ }
434
+ });
435
+ };
436
+ } else {
437
+ this.logger.warn("Cannot reconstruct await pattern", { awaitType, jobId: jobData.id });
438
+ return;
439
+ }
440
+ this.logger.info("Reconstructed await pattern handler", {
441
+ awaitType,
442
+ flowName,
443
+ runId
444
+ });
445
+ } else if (!jobData.handler) {
446
+ this.logger.debug("Skipping job - no handler available, waiting for re-registration", {
447
+ jobId: jobData.id
448
+ });
449
+ return;
450
+ }
451
+ this.jobConfigs.set(jobData.id, jobData);
452
+ if (jobData.type === "cron" && jobData.cron) {
453
+ const cronJob = new CronJob(
454
+ jobData.cron,
455
+ async () => {
456
+ await this.executeWithLock(jobData);
457
+ },
458
+ null,
459
+ true,
460
+ // Start immediately since scheduler.started is already true
461
+ jobData.timezone || "UTC"
462
+ );
463
+ this.jobs.set(jobData.id, cronJob);
464
+ this.logger.info("Recovered cron job", { jobId: jobData.id });
465
+ } else if (jobData.type === "interval" && jobData.interval) {
466
+ const intervalId = setInterval(
467
+ async () => {
468
+ await this.executeWithLock(jobData);
469
+ },
470
+ jobData.interval
471
+ );
472
+ this.jobs.set(jobData.id, intervalId);
473
+ this.logger.info("Recovered interval job", { jobId: jobData.id });
474
+ } else if (jobData.type === "one-time" && jobData.executeAt) {
475
+ const delay = jobData.executeAt - Date.now();
476
+ const isAwaitPattern = jobData.metadata?.component === "await-pattern";
477
+ if (delay > 0) {
478
+ const timeoutId = setTimeout(
479
+ async () => {
480
+ await this.executeWithLock(jobData);
481
+ await this.unschedule(jobData.id);
482
+ },
483
+ delay
484
+ );
485
+ this.jobs.set(jobData.id, timeoutId);
486
+ this.logger.info("Recovered one-time job", { jobId: jobData.id });
487
+ } else if (isAwaitPattern) {
488
+ this.logger.info("Executing overdue await pattern immediately", {
489
+ jobId: jobData.id,
490
+ awaitType: jobData.metadata?.awaitType,
491
+ flowName: jobData.metadata?.flowName
492
+ });
493
+ setImmediate(async () => {
494
+ try {
495
+ await jobData.handler();
496
+ await this.unschedule(jobData.id);
497
+ } catch (error) {
498
+ this.logger.error("Failed to execute overdue await pattern", {
499
+ jobId: jobData.id,
500
+ error: error.message
501
+ });
502
+ }
503
+ });
504
+ } else {
505
+ this.logger.debug("Skipping expired one-time job", { jobId: jobData.id });
506
+ }
507
+ }
508
+ } catch (error) {
509
+ this.logger.error("Failed to recover job", {
510
+ jobId: jobData.id,
511
+ error: error.message
512
+ });
513
+ }
514
+ }
515
+ /**
516
+ * Recover well-known job patterns when index scan is not available
517
+ * This includes:
518
+ * - stall-detection (always exists)
519
+ * - await-time-* (flows waiting on time delays)
520
+ * - await-schedule-* (flows waiting on cron schedules)
521
+ */
522
+ async recoverWellKnownJobs() {
523
+ const knownPatterns = [
524
+ "stall-detection"
525
+ // Note: await-* jobs have dynamic IDs, we can't easily recover them without scanning
526
+ // This is a limitation of KV-only stores
527
+ ];
528
+ for (const jobId of knownPatterns) {
529
+ try {
530
+ const jobKey = `${this.keyPrefix}:jobs:${jobId}`;
531
+ const jobData = await this.store.kv.get(jobKey);
532
+ if (jobData) {
533
+ await this.recoverJob(jobData);
534
+ }
535
+ } catch {
536
+ }
537
+ }
538
+ this.logger.info("Recovered well-known jobs. Await patterns may need manual recovery.");
539
+ }
540
+ async start() {
541
+ if (this.started) return;
542
+ this.started = true;
543
+ await this.recoverJobs();
544
+ this.logger.info("Started with active jobs", { count: this.jobs.size });
545
+ }
546
+ async stop() {
547
+ this.started = false;
548
+ for (const job of this.jobs.values()) {
549
+ if (job instanceof CronJob) {
550
+ job.stop();
551
+ } else {
552
+ clearTimeout(job);
553
+ clearInterval(job);
554
+ }
555
+ }
556
+ for (const timer of this.lockRenewalTimers.values()) {
557
+ clearInterval(timer);
558
+ }
559
+ this.lockRenewalTimers.clear();
560
+ if (this.useIndexLocking && this.store.index.read) {
561
+ const lockIndex = `${this.keyPrefix}:locks`;
562
+ const locks = await this.store.index.read(lockIndex, { limit: 1e3 });
563
+ for (const lock of locks) {
564
+ if (lock.metadata?.instanceId === this.instanceId) {
565
+ await this.releaseLock(lock.id);
566
+ }
567
+ }
568
+ }
569
+ this.jobs.clear();
570
+ this.jobConfigs.clear();
571
+ }
572
+ async getScheduledJobs() {
573
+ return Array.from(this.jobConfigs.values());
574
+ }
575
+ /**
576
+ * Get all persisted jobs from store (for debugging/monitoring)
577
+ * This shows ALL jobs across ALL instances with their runtime stats
578
+ */
579
+ async getAllPersistedJobs() {
580
+ const jobs = [];
581
+ try {
582
+ if (this.store.index.read) {
583
+ const jobIndex = `${this.keyPrefix}:jobs`;
584
+ const entries = await this.store.index.read(jobIndex, { limit: 1e4 });
585
+ for (const entry of entries) {
586
+ if (entry.metadata) {
587
+ const jobConfig = entry.metadata;
588
+ const statsKey = `${this.keyPrefix}:stats:${jobConfig.id}`;
589
+ try {
590
+ const stats = await this.store.kv.get(statsKey);
591
+ if (stats) {
592
+ jobs.push({
593
+ ...jobConfig,
594
+ lastRun: stats.lastRun,
595
+ nextRun: stats.nextRun,
596
+ runCount: stats.runCount,
597
+ failCount: stats.failCount
598
+ });
599
+ } else {
600
+ jobs.push(jobConfig);
601
+ }
602
+ } catch {
603
+ jobs.push(jobConfig);
604
+ }
605
+ }
606
+ }
607
+ } else {
608
+ this.logger.warn("Cannot list all persisted jobs without index support");
609
+ }
610
+ } catch (error) {
611
+ this.logger.error("Error getting persisted jobs", { error: error.message });
612
+ }
613
+ return jobs;
614
+ }
615
+ async isHealthy() {
616
+ try {
617
+ await this.store.kv.get("__health_check__");
618
+ return true;
619
+ } catch {
620
+ return false;
621
+ }
622
+ }
623
+ }