@contember/engine-actions 2.1.0-alpha.9 → 2.1.0-beta.2

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 (405) hide show
  1. package/CLAUDE.md +47 -0
  2. package/dist/development/index.cjs +54 -24
  3. package/dist/development/index.cjs.map +1 -1
  4. package/dist/development/index.js +54 -24
  5. package/dist/development/index.js.map +1 -1
  6. package/dist/development/src/ActionsExecutionContainerHookFactory.cjs +24 -11
  7. package/dist/development/src/ActionsExecutionContainerHookFactory.cjs.map +1 -1
  8. package/dist/development/src/ActionsExecutionContainerHookFactory.js +24 -11
  9. package/dist/development/src/ActionsExecutionContainerHookFactory.js.map +1 -1
  10. package/dist/development/src/ListenerStoreProvider.cjs.map +1 -1
  11. package/dist/development/src/ListenerStoreProvider.js.map +1 -1
  12. package/dist/development/src/authorization/ActionsAuthorizationActions.cjs +2 -0
  13. package/dist/development/src/authorization/ActionsAuthorizationActions.cjs.map +1 -1
  14. package/dist/development/src/authorization/ActionsAuthorizationActions.js +2 -0
  15. package/dist/development/src/authorization/ActionsAuthorizationActions.js.map +1 -1
  16. package/dist/development/src/authorization/ActionsPermissionsFactory.cjs.map +1 -1
  17. package/dist/development/src/authorization/ActionsPermissionsFactory.js.map +1 -1
  18. package/dist/development/src/dispatch/DispatchWorkerSupervisor.cjs +16 -14
  19. package/dist/development/src/dispatch/DispatchWorkerSupervisor.cjs.map +1 -1
  20. package/dist/development/src/dispatch/DispatchWorkerSupervisor.js +16 -14
  21. package/dist/development/src/dispatch/DispatchWorkerSupervisor.js.map +1 -1
  22. package/dist/development/src/dispatch/EventDispatcher.cjs.map +1 -1
  23. package/dist/development/src/dispatch/EventDispatcher.js.map +1 -1
  24. package/dist/development/src/dispatch/EventsRepository.cjs +33 -15
  25. package/dist/development/src/dispatch/EventsRepository.cjs.map +1 -1
  26. package/dist/development/src/dispatch/EventsRepository.js +33 -15
  27. package/dist/development/src/dispatch/EventsRepository.js.map +1 -1
  28. package/dist/development/src/dispatch/LazyDispatchWorker.cjs +67 -0
  29. package/dist/development/src/dispatch/LazyDispatchWorker.cjs.map +1 -0
  30. package/dist/development/src/dispatch/LazyDispatchWorker.js +67 -0
  31. package/dist/development/src/dispatch/LazyDispatchWorker.js.map +1 -0
  32. package/dist/development/src/dispatch/ProjectDispatcher.cjs +3 -3
  33. package/dist/development/src/dispatch/ProjectDispatcher.cjs.map +1 -1
  34. package/dist/development/src/dispatch/ProjectDispatcher.js +2 -2
  35. package/dist/development/src/dispatch/ProjectDispatcher.js.map +1 -1
  36. package/dist/development/src/dispatch/TargetHandlerResolver.cjs.map +1 -1
  37. package/dist/development/src/dispatch/TargetHandlerResolver.js.map +1 -1
  38. package/dist/development/src/dispatch/WebhookFetcher.cjs.map +1 -1
  39. package/dist/development/src/dispatch/WebhookFetcher.js.map +1 -1
  40. package/dist/development/src/dispatch/WebhookTargetHandler.cjs +6 -1
  41. package/dist/development/src/dispatch/WebhookTargetHandler.cjs.map +1 -1
  42. package/dist/development/src/dispatch/WebhookTargetHandler.js +6 -1
  43. package/dist/development/src/dispatch/WebhookTargetHandler.js.map +1 -1
  44. package/dist/development/src/graphql/http/ActionsApiMiddlewareFactory.cjs +1 -0
  45. package/dist/development/src/graphql/http/ActionsApiMiddlewareFactory.cjs.map +1 -1
  46. package/dist/development/src/graphql/http/ActionsApiMiddlewareFactory.js +1 -0
  47. package/dist/development/src/graphql/http/ActionsApiMiddlewareFactory.js.map +1 -1
  48. package/dist/development/src/graphql/http/ActionsContextResolver.cjs +8 -11
  49. package/dist/development/src/graphql/http/ActionsContextResolver.cjs.map +1 -1
  50. package/dist/development/src/graphql/http/ActionsContextResolver.js +8 -11
  51. package/dist/development/src/graphql/http/ActionsContextResolver.js.map +1 -1
  52. package/dist/development/src/graphql/http/ActionsGraphQLHandlerFactory.cjs.map +1 -1
  53. package/dist/development/src/graphql/http/ActionsGraphQLHandlerFactory.js.map +1 -1
  54. package/dist/development/src/graphql/http/ActionsWebsocketControllerFactory.cjs +6 -3
  55. package/dist/development/src/graphql/http/ActionsWebsocketControllerFactory.cjs.map +1 -1
  56. package/dist/development/src/graphql/http/ActionsWebsocketControllerFactory.js +6 -3
  57. package/dist/development/src/graphql/http/ActionsWebsocketControllerFactory.js.map +1 -1
  58. package/dist/development/src/graphql/resolvers/ResolversFactory.cjs +7 -2
  59. package/dist/development/src/graphql/resolvers/ResolversFactory.cjs.map +1 -1
  60. package/dist/development/src/graphql/resolvers/ResolversFactory.js +8 -3
  61. package/dist/development/src/graphql/resolvers/ResolversFactory.js.map +1 -1
  62. package/dist/development/src/graphql/resolvers/mutation/ProcessBatchMutationResolver.cjs.map +1 -1
  63. package/dist/development/src/graphql/resolvers/mutation/ProcessBatchMutationResolver.js.map +1 -1
  64. package/dist/development/src/graphql/resolvers/mutation/RetryEventMutationResolver.cjs +21 -0
  65. package/dist/development/src/graphql/resolvers/mutation/RetryEventMutationResolver.cjs.map +1 -0
  66. package/dist/development/src/graphql/resolvers/mutation/RetryEventMutationResolver.js +21 -0
  67. package/dist/development/src/graphql/resolvers/mutation/RetryEventMutationResolver.js.map +1 -0
  68. package/dist/development/src/graphql/resolvers/mutation/SetVariablesMutationResolver.cjs.map +1 -1
  69. package/dist/development/src/graphql/resolvers/mutation/SetVariablesMutationResolver.js.map +1 -1
  70. package/dist/development/src/graphql/resolvers/mutation/StopEventMutationResolver.cjs +19 -0
  71. package/dist/development/src/graphql/resolvers/mutation/StopEventMutationResolver.cjs.map +1 -0
  72. package/dist/development/src/graphql/resolvers/mutation/StopEventMutationResolver.js +19 -0
  73. package/dist/development/src/graphql/resolvers/mutation/StopEventMutationResolver.js.map +1 -0
  74. package/dist/development/src/graphql/resolvers/query/EventsQueryResolver.cjs +14 -1
  75. package/dist/development/src/graphql/resolvers/query/EventsQueryResolver.cjs.map +1 -1
  76. package/dist/development/src/graphql/resolvers/query/EventsQueryResolver.js +14 -1
  77. package/dist/development/src/graphql/resolvers/query/EventsQueryResolver.js.map +1 -1
  78. package/dist/development/src/graphql/resolvers/query/VariablesQueryResolver.cjs.map +1 -1
  79. package/dist/development/src/graphql/resolvers/query/VariablesQueryResolver.js.map +1 -1
  80. package/dist/development/src/graphql/schema/actions.graphql.cjs +18 -4
  81. package/dist/development/src/graphql/schema/actions.graphql.cjs.map +1 -1
  82. package/dist/development/src/graphql/schema/actions.graphql.js +18 -4
  83. package/dist/development/src/graphql/schema/actions.graphql.js.map +1 -1
  84. package/dist/development/src/migrations/2023-03-10-145000-actions-variables.cjs.map +1 -1
  85. package/dist/development/src/migrations/2023-03-10-145000-actions-variables.js.map +1 -1
  86. package/dist/development/src/migrations/2025-05-28-160000-action-event-user.cjs +16 -0
  87. package/dist/development/src/migrations/2025-05-28-160000-action-event-user.cjs.map +1 -0
  88. package/dist/development/src/migrations/2025-05-28-160000-action-event-user.js +17 -0
  89. package/dist/development/src/migrations/2025-05-28-160000-action-event-user.js.map +1 -0
  90. package/dist/development/src/migrations/index.cjs +3 -1
  91. package/dist/development/src/migrations/index.cjs.map +1 -1
  92. package/dist/development/src/migrations/index.js +3 -1
  93. package/dist/development/src/migrations/index.js.map +1 -1
  94. package/dist/development/src/migrations/snapshot.cjs +5 -2
  95. package/dist/development/src/migrations/snapshot.cjs.map +1 -1
  96. package/dist/development/src/migrations/snapshot.js +5 -2
  97. package/dist/development/src/migrations/snapshot.js.map +1 -1
  98. package/dist/development/src/model/EventByIdQuery.cjs +17 -0
  99. package/dist/development/src/model/EventByIdQuery.cjs.map +1 -0
  100. package/dist/development/src/model/EventByIdQuery.js +17 -0
  101. package/dist/development/src/model/EventByIdQuery.js.map +1 -0
  102. package/dist/development/src/model/EventsInProcessingQuery.cjs.map +1 -1
  103. package/dist/development/src/model/EventsInProcessingQuery.js.map +1 -1
  104. package/dist/development/src/model/EventsToProcessQuery.cjs.map +1 -1
  105. package/dist/development/src/model/EventsToProcessQuery.js.map +1 -1
  106. package/dist/development/src/model/EventsToProcessSpecification.cjs.map +1 -1
  107. package/dist/development/src/model/EventsToProcessSpecification.js.map +1 -1
  108. package/dist/development/src/model/FailedEventsQuery.cjs.map +1 -1
  109. package/dist/development/src/model/FailedEventsQuery.js.map +1 -1
  110. package/dist/development/src/model/SetVariableCommand.cjs.map +1 -1
  111. package/dist/development/src/model/SetVariableCommand.js.map +1 -1
  112. package/dist/development/src/model/VariablesManager.cjs.map +1 -1
  113. package/dist/development/src/model/VariablesManager.js.map +1 -1
  114. package/dist/development/src/model/VariablesQuery.cjs.map +1 -1
  115. package/dist/development/src/model/VariablesQuery.js.map +1 -1
  116. package/dist/development/src/triggers/TriggerHandler.cjs +17 -14
  117. package/dist/development/src/triggers/TriggerHandler.cjs.map +1 -1
  118. package/dist/development/src/triggers/TriggerHandler.js +17 -14
  119. package/dist/development/src/triggers/TriggerHandler.js.map +1 -1
  120. package/dist/development/src/triggers/TriggerIndirectChangesFetcher.cjs +44 -2
  121. package/dist/development/src/triggers/TriggerIndirectChangesFetcher.cjs.map +1 -1
  122. package/dist/development/src/triggers/TriggerIndirectChangesFetcher.js +44 -2
  123. package/dist/development/src/triggers/TriggerIndirectChangesFetcher.js.map +1 -1
  124. package/dist/development/src/triggers/TriggerListenersBuilder.cjs.map +1 -1
  125. package/dist/development/src/triggers/TriggerListenersBuilder.js.map +1 -1
  126. package/dist/development/src/triggers/TriggerListenersFactory.cjs.map +1 -1
  127. package/dist/development/src/triggers/TriggerListenersFactory.js.map +1 -1
  128. package/dist/development/src/triggers/TriggerListenersStore.cjs.map +1 -1
  129. package/dist/development/src/triggers/TriggerListenersStore.js.map +1 -1
  130. package/dist/development/src/triggers/TriggerPayloadBuilder.cjs +45 -16
  131. package/dist/development/src/triggers/TriggerPayloadBuilder.cjs.map +1 -1
  132. package/dist/development/src/triggers/TriggerPayloadBuilder.js +45 -16
  133. package/dist/development/src/triggers/TriggerPayloadBuilder.js.map +1 -1
  134. package/dist/development/src/triggers/TriggerPayloadManager.cjs.map +1 -1
  135. package/dist/development/src/triggers/TriggerPayloadManager.js.map +1 -1
  136. package/dist/development/src/triggers/TriggerPayloadPersister.cjs +36 -20
  137. package/dist/development/src/triggers/TriggerPayloadPersister.cjs.map +1 -1
  138. package/dist/development/src/triggers/TriggerPayloadPersister.js +36 -20
  139. package/dist/development/src/triggers/TriggerPayloadPersister.js.map +1 -1
  140. package/dist/development/src/utils/assertNever.cjs.map +1 -1
  141. package/dist/development/src/utils/assertNever.js.map +1 -1
  142. package/dist/development/src/utils/map.cjs.map +1 -1
  143. package/dist/development/src/utils/map.js.map +1 -1
  144. package/dist/development/src/utils/notifyChannel.cjs +9 -0
  145. package/dist/development/src/utils/notifyChannel.cjs.map +1 -0
  146. package/dist/development/src/utils/notifyChannel.js +9 -0
  147. package/dist/development/src/utils/notifyChannel.js.map +1 -0
  148. package/dist/production/index.cjs +54 -24
  149. package/dist/production/index.cjs.map +1 -1
  150. package/dist/production/index.js +54 -24
  151. package/dist/production/index.js.map +1 -1
  152. package/dist/production/src/ActionsExecutionContainerHookFactory.cjs +24 -11
  153. package/dist/production/src/ActionsExecutionContainerHookFactory.cjs.map +1 -1
  154. package/dist/production/src/ActionsExecutionContainerHookFactory.js +24 -11
  155. package/dist/production/src/ActionsExecutionContainerHookFactory.js.map +1 -1
  156. package/dist/production/src/ListenerStoreProvider.cjs.map +1 -1
  157. package/dist/production/src/ListenerStoreProvider.js.map +1 -1
  158. package/dist/production/src/authorization/ActionsAuthorizationActions.cjs +2 -0
  159. package/dist/production/src/authorization/ActionsAuthorizationActions.cjs.map +1 -1
  160. package/dist/production/src/authorization/ActionsAuthorizationActions.js +2 -0
  161. package/dist/production/src/authorization/ActionsAuthorizationActions.js.map +1 -1
  162. package/dist/production/src/authorization/ActionsPermissionsFactory.cjs.map +1 -1
  163. package/dist/production/src/authorization/ActionsPermissionsFactory.js.map +1 -1
  164. package/dist/production/src/dispatch/DispatchWorkerSupervisor.cjs +16 -14
  165. package/dist/production/src/dispatch/DispatchWorkerSupervisor.cjs.map +1 -1
  166. package/dist/production/src/dispatch/DispatchWorkerSupervisor.js +16 -14
  167. package/dist/production/src/dispatch/DispatchWorkerSupervisor.js.map +1 -1
  168. package/dist/production/src/dispatch/EventDispatcher.cjs.map +1 -1
  169. package/dist/production/src/dispatch/EventDispatcher.js.map +1 -1
  170. package/dist/production/src/dispatch/EventsRepository.cjs +33 -15
  171. package/dist/production/src/dispatch/EventsRepository.cjs.map +1 -1
  172. package/dist/production/src/dispatch/EventsRepository.js +33 -15
  173. package/dist/production/src/dispatch/EventsRepository.js.map +1 -1
  174. package/dist/production/src/dispatch/LazyDispatchWorker.cjs +67 -0
  175. package/dist/production/src/dispatch/LazyDispatchWorker.cjs.map +1 -0
  176. package/dist/production/src/dispatch/LazyDispatchWorker.js +67 -0
  177. package/dist/production/src/dispatch/LazyDispatchWorker.js.map +1 -0
  178. package/dist/production/src/dispatch/ProjectDispatcher.cjs +3 -3
  179. package/dist/production/src/dispatch/ProjectDispatcher.cjs.map +1 -1
  180. package/dist/production/src/dispatch/ProjectDispatcher.js +2 -2
  181. package/dist/production/src/dispatch/ProjectDispatcher.js.map +1 -1
  182. package/dist/production/src/dispatch/TargetHandlerResolver.cjs.map +1 -1
  183. package/dist/production/src/dispatch/TargetHandlerResolver.js.map +1 -1
  184. package/dist/production/src/dispatch/WebhookFetcher.cjs.map +1 -1
  185. package/dist/production/src/dispatch/WebhookFetcher.js.map +1 -1
  186. package/dist/production/src/dispatch/WebhookTargetHandler.cjs +6 -1
  187. package/dist/production/src/dispatch/WebhookTargetHandler.cjs.map +1 -1
  188. package/dist/production/src/dispatch/WebhookTargetHandler.js +6 -1
  189. package/dist/production/src/dispatch/WebhookTargetHandler.js.map +1 -1
  190. package/dist/production/src/graphql/http/ActionsApiMiddlewareFactory.cjs +1 -0
  191. package/dist/production/src/graphql/http/ActionsApiMiddlewareFactory.cjs.map +1 -1
  192. package/dist/production/src/graphql/http/ActionsApiMiddlewareFactory.js +1 -0
  193. package/dist/production/src/graphql/http/ActionsApiMiddlewareFactory.js.map +1 -1
  194. package/dist/production/src/graphql/http/ActionsContextResolver.cjs +8 -11
  195. package/dist/production/src/graphql/http/ActionsContextResolver.cjs.map +1 -1
  196. package/dist/production/src/graphql/http/ActionsContextResolver.js +8 -11
  197. package/dist/production/src/graphql/http/ActionsContextResolver.js.map +1 -1
  198. package/dist/production/src/graphql/http/ActionsGraphQLHandlerFactory.cjs.map +1 -1
  199. package/dist/production/src/graphql/http/ActionsGraphQLHandlerFactory.js.map +1 -1
  200. package/dist/production/src/graphql/http/ActionsWebsocketControllerFactory.cjs +6 -3
  201. package/dist/production/src/graphql/http/ActionsWebsocketControllerFactory.cjs.map +1 -1
  202. package/dist/production/src/graphql/http/ActionsWebsocketControllerFactory.js +6 -3
  203. package/dist/production/src/graphql/http/ActionsWebsocketControllerFactory.js.map +1 -1
  204. package/dist/production/src/graphql/resolvers/ResolversFactory.cjs +7 -2
  205. package/dist/production/src/graphql/resolvers/ResolversFactory.cjs.map +1 -1
  206. package/dist/production/src/graphql/resolvers/ResolversFactory.js +8 -3
  207. package/dist/production/src/graphql/resolvers/ResolversFactory.js.map +1 -1
  208. package/dist/production/src/graphql/resolvers/mutation/ProcessBatchMutationResolver.cjs.map +1 -1
  209. package/dist/production/src/graphql/resolvers/mutation/ProcessBatchMutationResolver.js.map +1 -1
  210. package/dist/production/src/graphql/resolvers/mutation/RetryEventMutationResolver.cjs +21 -0
  211. package/dist/production/src/graphql/resolvers/mutation/RetryEventMutationResolver.cjs.map +1 -0
  212. package/dist/production/src/graphql/resolvers/mutation/RetryEventMutationResolver.js +21 -0
  213. package/dist/production/src/graphql/resolvers/mutation/RetryEventMutationResolver.js.map +1 -0
  214. package/dist/production/src/graphql/resolvers/mutation/SetVariablesMutationResolver.cjs.map +1 -1
  215. package/dist/production/src/graphql/resolvers/mutation/SetVariablesMutationResolver.js.map +1 -1
  216. package/dist/production/src/graphql/resolvers/mutation/StopEventMutationResolver.cjs +19 -0
  217. package/dist/production/src/graphql/resolvers/mutation/StopEventMutationResolver.cjs.map +1 -0
  218. package/dist/production/src/graphql/resolvers/mutation/StopEventMutationResolver.js +19 -0
  219. package/dist/production/src/graphql/resolvers/mutation/StopEventMutationResolver.js.map +1 -0
  220. package/dist/production/src/graphql/resolvers/query/EventsQueryResolver.cjs +14 -1
  221. package/dist/production/src/graphql/resolvers/query/EventsQueryResolver.cjs.map +1 -1
  222. package/dist/production/src/graphql/resolvers/query/EventsQueryResolver.js +14 -1
  223. package/dist/production/src/graphql/resolvers/query/EventsQueryResolver.js.map +1 -1
  224. package/dist/production/src/graphql/resolvers/query/VariablesQueryResolver.cjs.map +1 -1
  225. package/dist/production/src/graphql/resolvers/query/VariablesQueryResolver.js.map +1 -1
  226. package/dist/production/src/graphql/schema/actions.graphql.cjs +18 -4
  227. package/dist/production/src/graphql/schema/actions.graphql.cjs.map +1 -1
  228. package/dist/production/src/graphql/schema/actions.graphql.js +18 -4
  229. package/dist/production/src/graphql/schema/actions.graphql.js.map +1 -1
  230. package/dist/production/src/migrations/2023-03-10-145000-actions-variables.cjs.map +1 -1
  231. package/dist/production/src/migrations/2023-03-10-145000-actions-variables.js.map +1 -1
  232. package/dist/production/src/migrations/2025-05-28-160000-action-event-user.cjs +16 -0
  233. package/dist/production/src/migrations/2025-05-28-160000-action-event-user.cjs.map +1 -0
  234. package/dist/production/src/migrations/2025-05-28-160000-action-event-user.js +17 -0
  235. package/dist/production/src/migrations/2025-05-28-160000-action-event-user.js.map +1 -0
  236. package/dist/production/src/migrations/index.cjs +3 -1
  237. package/dist/production/src/migrations/index.cjs.map +1 -1
  238. package/dist/production/src/migrations/index.js +3 -1
  239. package/dist/production/src/migrations/index.js.map +1 -1
  240. package/dist/production/src/migrations/snapshot.cjs +5 -2
  241. package/dist/production/src/migrations/snapshot.cjs.map +1 -1
  242. package/dist/production/src/migrations/snapshot.js +5 -2
  243. package/dist/production/src/migrations/snapshot.js.map +1 -1
  244. package/dist/production/src/model/EventByIdQuery.cjs +17 -0
  245. package/dist/production/src/model/EventByIdQuery.cjs.map +1 -0
  246. package/dist/production/src/model/EventByIdQuery.js +17 -0
  247. package/dist/production/src/model/EventByIdQuery.js.map +1 -0
  248. package/dist/production/src/model/EventsInProcessingQuery.cjs.map +1 -1
  249. package/dist/production/src/model/EventsInProcessingQuery.js.map +1 -1
  250. package/dist/production/src/model/EventsToProcessQuery.cjs.map +1 -1
  251. package/dist/production/src/model/EventsToProcessQuery.js.map +1 -1
  252. package/dist/production/src/model/EventsToProcessSpecification.cjs.map +1 -1
  253. package/dist/production/src/model/EventsToProcessSpecification.js.map +1 -1
  254. package/dist/production/src/model/FailedEventsQuery.cjs.map +1 -1
  255. package/dist/production/src/model/FailedEventsQuery.js.map +1 -1
  256. package/dist/production/src/model/SetVariableCommand.cjs.map +1 -1
  257. package/dist/production/src/model/SetVariableCommand.js.map +1 -1
  258. package/dist/production/src/model/VariablesManager.cjs.map +1 -1
  259. package/dist/production/src/model/VariablesManager.js.map +1 -1
  260. package/dist/production/src/model/VariablesQuery.cjs.map +1 -1
  261. package/dist/production/src/model/VariablesQuery.js.map +1 -1
  262. package/dist/production/src/triggers/TriggerHandler.cjs +17 -14
  263. package/dist/production/src/triggers/TriggerHandler.cjs.map +1 -1
  264. package/dist/production/src/triggers/TriggerHandler.js +17 -14
  265. package/dist/production/src/triggers/TriggerHandler.js.map +1 -1
  266. package/dist/production/src/triggers/TriggerIndirectChangesFetcher.cjs +44 -2
  267. package/dist/production/src/triggers/TriggerIndirectChangesFetcher.cjs.map +1 -1
  268. package/dist/production/src/triggers/TriggerIndirectChangesFetcher.js +44 -2
  269. package/dist/production/src/triggers/TriggerIndirectChangesFetcher.js.map +1 -1
  270. package/dist/production/src/triggers/TriggerListenersBuilder.cjs.map +1 -1
  271. package/dist/production/src/triggers/TriggerListenersBuilder.js.map +1 -1
  272. package/dist/production/src/triggers/TriggerListenersFactory.cjs.map +1 -1
  273. package/dist/production/src/triggers/TriggerListenersFactory.js.map +1 -1
  274. package/dist/production/src/triggers/TriggerListenersStore.cjs.map +1 -1
  275. package/dist/production/src/triggers/TriggerListenersStore.js.map +1 -1
  276. package/dist/production/src/triggers/TriggerPayloadBuilder.cjs +45 -16
  277. package/dist/production/src/triggers/TriggerPayloadBuilder.cjs.map +1 -1
  278. package/dist/production/src/triggers/TriggerPayloadBuilder.js +45 -16
  279. package/dist/production/src/triggers/TriggerPayloadBuilder.js.map +1 -1
  280. package/dist/production/src/triggers/TriggerPayloadManager.cjs.map +1 -1
  281. package/dist/production/src/triggers/TriggerPayloadManager.js.map +1 -1
  282. package/dist/production/src/triggers/TriggerPayloadPersister.cjs +36 -20
  283. package/dist/production/src/triggers/TriggerPayloadPersister.cjs.map +1 -1
  284. package/dist/production/src/triggers/TriggerPayloadPersister.js +36 -20
  285. package/dist/production/src/triggers/TriggerPayloadPersister.js.map +1 -1
  286. package/dist/production/src/utils/assertNever.cjs.map +1 -1
  287. package/dist/production/src/utils/assertNever.js.map +1 -1
  288. package/dist/production/src/utils/map.cjs.map +1 -1
  289. package/dist/production/src/utils/map.js.map +1 -1
  290. package/dist/production/src/utils/notifyChannel.cjs +9 -0
  291. package/dist/production/src/utils/notifyChannel.cjs.map +1 -0
  292. package/dist/production/src/utils/notifyChannel.js +9 -0
  293. package/dist/production/src/utils/notifyChannel.js.map +1 -0
  294. package/dist/tests/cases/unit/lazyDispatchWorker.test.d.ts +2 -0
  295. package/dist/tests/cases/unit/lazyDispatchWorker.test.d.ts.map +1 -0
  296. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  297. package/dist/types/ActionsExecutionContainerHookFactory.d.ts.map +1 -1
  298. package/dist/types/authorization/ActionsAuthorizationActions.d.ts +10 -0
  299. package/dist/types/authorization/ActionsAuthorizationActions.d.ts.map +1 -1
  300. package/dist/types/dispatch/DispatchWorkerSupervisor.d.ts.map +1 -1
  301. package/dist/types/dispatch/EventDispatcher.d.ts.map +1 -1
  302. package/dist/types/dispatch/EventsRepository.d.ts +2 -1
  303. package/dist/types/dispatch/EventsRepository.d.ts.map +1 -1
  304. package/dist/types/dispatch/LazyDispatchWorker.d.ts +11 -0
  305. package/dist/types/dispatch/LazyDispatchWorker.d.ts.map +1 -0
  306. package/dist/types/dispatch/ProjectDispatcher.d.ts.map +1 -1
  307. package/dist/types/dispatch/WebhookTargetHandler.d.ts.map +1 -1
  308. package/dist/types/dispatch/types.d.ts +1 -1
  309. package/dist/types/dispatch/types.d.ts.map +1 -1
  310. package/dist/types/graphql/http/ActionsApiMiddlewareFactory.d.ts.map +1 -1
  311. package/dist/types/graphql/http/ActionsContextResolver.d.ts.map +1 -1
  312. package/dist/types/graphql/http/ActionsGraphQLHandlerFactory.d.ts.map +1 -1
  313. package/dist/types/graphql/http/ActionsWebsocketControllerFactory.d.ts.map +1 -1
  314. package/dist/types/graphql/resolvers/ActionsContext.d.ts +3 -0
  315. package/dist/types/graphql/resolvers/ActionsContext.d.ts.map +1 -1
  316. package/dist/types/graphql/resolvers/ResolversFactory.d.ts +4 -2
  317. package/dist/types/graphql/resolvers/ResolversFactory.d.ts.map +1 -1
  318. package/dist/types/graphql/resolvers/mutation/RetryEventMutationResolver.d.ts +11 -0
  319. package/dist/types/graphql/resolvers/mutation/RetryEventMutationResolver.d.ts.map +1 -0
  320. package/dist/types/graphql/resolvers/mutation/SetVariablesMutationResolver.d.ts.map +1 -1
  321. package/dist/types/graphql/resolvers/mutation/StopEventMutationResolver.d.ts +11 -0
  322. package/dist/types/graphql/resolvers/mutation/StopEventMutationResolver.d.ts.map +1 -0
  323. package/dist/types/graphql/resolvers/mutation/index.d.ts +2 -0
  324. package/dist/types/graphql/resolvers/mutation/index.d.ts.map +1 -1
  325. package/dist/types/graphql/resolvers/query/EventsQueryResolver.d.ts +3 -0
  326. package/dist/types/graphql/resolvers/query/EventsQueryResolver.d.ts.map +1 -1
  327. package/dist/types/graphql/resolvers/query/VariablesQueryResolver.d.ts.map +1 -1
  328. package/dist/types/graphql/schema/actions.graphql.d.ts.map +1 -1
  329. package/dist/types/graphql/schema/index.d.ts +45 -2
  330. package/dist/types/graphql/schema/index.d.ts.map +1 -1
  331. package/dist/types/index.d.ts +1 -1
  332. package/dist/types/index.d.ts.map +1 -1
  333. package/dist/types/migrations/2023-03-10-145000-actions-variables.d.ts.map +1 -1
  334. package/dist/types/migrations/2025-05-28-160000-action-event-user.d.ts +3 -0
  335. package/dist/types/migrations/2025-05-28-160000-action-event-user.d.ts.map +1 -0
  336. package/dist/types/migrations/index.d.ts.map +1 -1
  337. package/dist/types/migrations/snapshot.d.ts.map +1 -1
  338. package/dist/types/model/EventByIdQuery.d.ts +8 -0
  339. package/dist/types/model/EventByIdQuery.d.ts.map +1 -0
  340. package/dist/types/model/EventsToProcessSpecification.d.ts.map +1 -1
  341. package/dist/types/model/SetVariableCommand.d.ts.map +1 -1
  342. package/dist/types/model/types.d.ts +3 -0
  343. package/dist/types/model/types.d.ts.map +1 -1
  344. package/dist/types/triggers/TriggerHandler.d.ts.map +1 -1
  345. package/dist/types/triggers/TriggerIndirectChangesFetcher.d.ts +11 -3
  346. package/dist/types/triggers/TriggerIndirectChangesFetcher.d.ts.map +1 -1
  347. package/dist/types/triggers/TriggerListeners.d.ts.map +1 -1
  348. package/dist/types/triggers/TriggerListenersBuilder.d.ts.map +1 -1
  349. package/dist/types/triggers/TriggerListenersStore.d.ts +2 -2
  350. package/dist/types/triggers/TriggerListenersStore.d.ts.map +1 -1
  351. package/dist/types/triggers/TriggerPayloadBuilder.d.ts.map +1 -1
  352. package/dist/types/triggers/TriggerPayloadManager.d.ts +2 -1
  353. package/dist/types/triggers/TriggerPayloadManager.d.ts.map +1 -1
  354. package/dist/types/triggers/TriggerPayloadPersister.d.ts +9 -4
  355. package/dist/types/triggers/TriggerPayloadPersister.d.ts.map +1 -1
  356. package/dist/types/tsconfig.tsbuildinfo +1 -1
  357. package/dist/types/utils/notifyChannel.d.ts +4 -0
  358. package/dist/types/utils/notifyChannel.d.ts.map +1 -0
  359. package/graphql.codegen.yml +2 -2
  360. package/package.json +26 -21
  361. package/src/ActionsExecutionContainerHookFactory.ts +27 -11
  362. package/src/authorization/ActionsAuthorizationActions.ts +2 -0
  363. package/src/dispatch/DispatchWorkerSupervisor.ts +17 -16
  364. package/src/dispatch/EventDispatcher.ts +0 -2
  365. package/src/dispatch/EventsRepository.ts +63 -43
  366. package/src/dispatch/LazyDispatchWorker.ts +72 -0
  367. package/src/dispatch/ProjectDispatcher.ts +6 -11
  368. package/src/dispatch/WebhookTargetHandler.ts +18 -9
  369. package/src/dispatch/types.ts +1 -2
  370. package/src/graphql/http/ActionsApiMiddlewareFactory.ts +7 -5
  371. package/src/graphql/http/ActionsContextResolver.ts +1 -2
  372. package/src/graphql/http/ActionsGraphQLHandlerFactory.ts +0 -1
  373. package/src/graphql/http/ActionsWebsocketControllerFactory.ts +7 -5
  374. package/src/graphql/resolvers/ActionsContext.ts +1 -0
  375. package/src/graphql/resolvers/ResolversFactory.ts +9 -2
  376. package/src/graphql/resolvers/mutation/RetryEventMutationResolver.ts +22 -0
  377. package/src/graphql/resolvers/mutation/SetVariablesMutationResolver.ts +0 -1
  378. package/src/graphql/resolvers/mutation/StopEventMutationResolver.ts +19 -0
  379. package/src/graphql/resolvers/mutation/index.ts +2 -0
  380. package/src/graphql/resolvers/query/EventsQueryResolver.ts +15 -8
  381. package/src/graphql/resolvers/query/VariablesQueryResolver.ts +0 -1
  382. package/src/graphql/schema/actions.graphql.ts +18 -4
  383. package/src/graphql/schema/index.ts +84 -30
  384. package/src/index.ts +66 -35
  385. package/src/migrations/2023-03-10-145000-actions-variables.ts +1 -1
  386. package/src/migrations/2025-05-28-160000-action-event-user.ts +16 -0
  387. package/src/migrations/index.ts +2 -0
  388. package/src/migrations/snapshot.ts +6 -3
  389. package/src/model/EventByIdQuery.ts +21 -0
  390. package/src/model/EventsToProcessSpecification.ts +9 -8
  391. package/src/model/SetVariableCommand.ts +0 -1
  392. package/src/model/types.ts +3 -0
  393. package/src/triggers/TriggerHandler.ts +16 -15
  394. package/src/triggers/TriggerIndirectChangesFetcher.ts +62 -3
  395. package/src/triggers/TriggerListeners.ts +1 -8
  396. package/src/triggers/TriggerListenersBuilder.ts +3 -6
  397. package/src/triggers/TriggerListenersStore.ts +2 -2
  398. package/src/triggers/TriggerPayloadBuilder.ts +43 -13
  399. package/src/triggers/TriggerPayloadManager.ts +2 -4
  400. package/src/triggers/TriggerPayloadPersister.ts +28 -10
  401. package/src/utils/notifyChannel.ts +6 -0
  402. package/tests/cases/unit/generator.test.ts +133 -136
  403. package/tests/cases/unit/lazyDispatchWorker.test.ts +226 -0
  404. package/tests/cases/unit/webhookHandler.test.ts +47 -35
  405. package/vitest.config.ts +0 -3
@@ -63,21 +63,23 @@ class DispatchWorkerSupervisor {
63
63
  throw e;
64
64
  }
65
65
  };
66
- const projectTracker = new engineCommon.Supervisor(new Database.AcquiringListener(
67
- tenantContainer.databaseContext.client,
68
- "project_updated",
69
- async () => {
70
- logger.debug("Project config change detected, reloading dispatch workers");
71
- await endProjectWorkers();
72
- try {
73
- await startWorkers(true);
74
- } catch (e) {
75
- logger.error(e, { message: "Dispatch workers reload failed, terminating" });
76
- await endAll();
77
- onError(e);
66
+ const projectTracker = new engineCommon.Supervisor(
67
+ new Database.AcquiringListener(
68
+ tenantContainer.databaseContext.client,
69
+ "project_updated",
70
+ async () => {
71
+ logger.debug("Project config change detected, reloading dispatch workers");
72
+ await endProjectWorkers();
73
+ try {
74
+ await startWorkers(true);
75
+ } catch (e) {
76
+ logger.error(e, { message: "Dispatch workers reload failed, terminating" });
77
+ await endAll();
78
+ onError(e);
79
+ }
78
80
  }
79
- }
80
- ));
81
+ )
82
+ );
81
83
  const runningProjectTracker = await projectTracker.run({
82
84
  logger,
83
85
  onError: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"DispatchWorkerSupervisor.cjs","sources":["../../../../../packages/engine-actions/src/dispatch/DispatchWorkerSupervisor.ts"],"sourcesContent":["import { ProjectContainer, ProjectGroupContainer } from '@contember/engine-http'\nimport { AcquiringListener } from '@contember/database'\nimport { Runnable, RunnableArgs, Running, Supervisor } from '@contember/engine-common'\nimport { ProjectDispatcherFactory } from './ProjectDispatcher'\nimport { Logger } from '@contember/logger'\nimport { ImplementationException } from '../ImplementationException'\n\nexport class DispatchWorkerSupervisorFactory {\n\n\tconstructor(\n\t\tprivate projectDispatcherFactory: ProjectDispatcherFactory,\n\t) {\n\t}\n\n\tpublic create(projectGroup: ProjectGroupContainer): DispatchWorkerSupervisor {\n\t\treturn new DispatchWorkerSupervisor(this.projectDispatcherFactory, projectGroup)\n\t}\n}\n\nexport class DispatchWorkerSupervisor implements Runnable {\n\tconstructor(\n\t\tprivate projectDispatcherFactory: ProjectDispatcherFactory,\n\t\tprivate projectGroup: ProjectGroupContainer,\n\t) {\n\t}\n\n\tpublic async run({ logger, onError }: RunnableArgs) {\n\t\tconst projectGroup = this.projectGroup\n\t\tconst tenantContainer = projectGroup.tenantContainer\n\t\tconst projectContainerResolver = projectGroup.projectContainerResolver\n\n\t\tconst running = new Map<string, { worker: Promise<Running>; container: ProjectContainer }>()\n\n\t\tconst cleanupListener = projectContainerResolver.on('destroy', async ({ container }) => {\n\t\t\tconst runningForProject = running.get(container.project.slug)\n\t\t\tif (!runningForProject) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\trunning.delete(container.project.slug)\n\t\t\tawait (await runningForProject.worker).end()\n\t\t})\n\n\t\tconst refreshProjectWorker = async (container: ProjectContainer, isReloading: boolean) => {\n\t\t\tconst db = container.systemDatabaseContext\n\t\t\tconst current = running.get(container.project.slug)\n\t\t\tif (current && current.container === container) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst dispatcher = this.projectDispatcherFactory.create({\n\t\t\t\tdb,\n\t\t\t\tcontentSchemaResolver: container.contentSchemaResolver,\n\t\t\t\tprojectSlug: container.project.slug,\n\t\t\t})\n\t\t\tconst supervisedDispatcher = new Supervisor(\n\t\t\t\tdispatcher,\n\t\t\t\t{ startupMax: isReloading ? Number.MAX_VALUE : 10 },\n\t\t\t)\n\t\t\tconst worker = supervisedDispatcher.run({\n\t\t\t\tlogger,\n\t\t\t\tonError: () => {\n\t\t\t\t\tthrow new ImplementationException('supervised project dispatcher crashed')\n\t\t\t\t},\n\t\t\t})\n\t\t\trunning.set(container.project.slug, { worker, container })\n\t\t\ttry {\n\t\t\t\tif (current) {\n\t\t\t\t\tawait (await current.worker).end()\n\t\t\t\t}\n\t\t\t\tawait worker\n\t\t\t\tlogger.debug('Project dispatch worker started', { project: container.project.slug })\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(e, { message: 'Project dispatch worker start failed', project: container.project.slug })\n\t\t\t\trunning.delete(container.project.slug)\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\tconst projectTracker = new Supervisor(new AcquiringListener(\n\t\t\ttenantContainer.databaseContext.client,\n\t\t\t'project_updated',\n\t\t\tasync () => {\n\t\t\t\tlogger.debug('Project config change detected, reloading dispatch workers')\n\t\t\t\tawait endProjectWorkers()\n\t\t\t\ttry {\n\t\t\t\t\tawait startWorkers(true)\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlogger.error(e, { message: 'Dispatch workers reload failed, terminating' })\n\t\t\t\t\tawait endAll()\n\t\t\t\t\tonError(e)\n\t\t\t\t}\n\t\t\t},\n\t\t))\n\n\t\tconst runningProjectTracker = await projectTracker.run({\n\t\t\tlogger,\n\t\t\tonError: () => {\n\t\t\t\tthrow new ImplementationException('supervised project tracker crashed')\n\t\t\t},\n\t\t})\n\t\tconst fetchProjects = async () => await tenantContainer.projectManager.getProjects(tenantContainer.databaseContext)\n\n\t\tconst startWorkers = async (isReloading: boolean) => {\n\t\t\ttry {\n\t\t\t\tconst projects = await fetchProjects()\n\t\t\t\tfor (const project of projects) {\n\t\t\t\t\tconst container = await projectGroup.projectContainerResolver.getProjectContainer(project.slug)\n\t\t\t\t\tif (container) {\n\t\t\t\t\t\tawait refreshProjectWorker(container, isReloading)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tawait endAll()\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\tconst endProjectWorkers = async () => {\n\t\t\tconst workers = [...running.values()]\n\t\t\trunning.clear()\n\t\t\tawait Promise.allSettled(workers.map(async ({ worker }) => await (await worker).end()))\n\t\t}\n\t\tconst endAll = async () => {\n\t\t\tlogger.debug('Terminating project dispatch workers...')\n\t\t\tcleanupListener()\n\t\t\ttry {\n\t\t\t\tawait runningProjectTracker.end()\n\t\t\t} catch {\n\t\t\t}\n\t\t\tawait endProjectWorkers()\n\t\t\tlogger.debug('Project dispatch workers terminated')\n\t\t}\n\n\t\tawait startWorkers(false)\n\n\t\treturn {\n\t\t\tend: endAll,\n\t\t}\n\t}\n}\n"],"names":["Supervisor","ImplementationException","AcquiringListener"],"mappings":"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"}
1
+ {"version":3,"file":"DispatchWorkerSupervisor.cjs","sources":["../../../../../packages/engine-actions/src/dispatch/DispatchWorkerSupervisor.ts"],"sourcesContent":["import { ProjectContainer, ProjectGroupContainer } from '@contember/engine-http'\nimport { AcquiringListener } from '@contember/database'\nimport { Runnable, RunnableArgs, Running, Supervisor } from '@contember/engine-common'\nimport { ProjectDispatcherFactory } from './ProjectDispatcher'\nimport { Logger } from '@contember/logger'\nimport { ImplementationException } from '../ImplementationException'\n\nexport class DispatchWorkerSupervisorFactory {\n\tconstructor(\n\t\tprivate projectDispatcherFactory: ProjectDispatcherFactory,\n\t) {\n\t}\n\n\tpublic create(projectGroup: ProjectGroupContainer): DispatchWorkerSupervisor {\n\t\treturn new DispatchWorkerSupervisor(this.projectDispatcherFactory, projectGroup)\n\t}\n}\n\nexport class DispatchWorkerSupervisor implements Runnable {\n\tconstructor(\n\t\tprivate projectDispatcherFactory: ProjectDispatcherFactory,\n\t\tprivate projectGroup: ProjectGroupContainer,\n\t) {\n\t}\n\n\tpublic async run({ logger, onError }: RunnableArgs) {\n\t\tconst projectGroup = this.projectGroup\n\t\tconst tenantContainer = projectGroup.tenantContainer\n\t\tconst projectContainerResolver = projectGroup.projectContainerResolver\n\n\t\tconst running = new Map<string, { worker: Promise<Running>; container: ProjectContainer }>()\n\n\t\tconst cleanupListener = projectContainerResolver.on('destroy', async ({ container }) => {\n\t\t\tconst runningForProject = running.get(container.project.slug)\n\t\t\tif (!runningForProject) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\trunning.delete(container.project.slug)\n\t\t\tawait (await runningForProject.worker).end()\n\t\t})\n\n\t\tconst refreshProjectWorker = async (container: ProjectContainer, isReloading: boolean) => {\n\t\t\tconst db = container.systemDatabaseContext\n\t\t\tconst current = running.get(container.project.slug)\n\t\t\tif (current && current.container === container) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst dispatcher = this.projectDispatcherFactory.create({\n\t\t\t\tdb,\n\t\t\t\tcontentSchemaResolver: container.contentSchemaResolver,\n\t\t\t\tprojectSlug: container.project.slug,\n\t\t\t})\n\t\t\tconst supervisedDispatcher = new Supervisor(\n\t\t\t\tdispatcher,\n\t\t\t\t{ startupMax: isReloading ? Number.MAX_VALUE : 10 },\n\t\t\t)\n\t\t\tconst worker = supervisedDispatcher.run({\n\t\t\t\tlogger,\n\t\t\t\tonError: () => {\n\t\t\t\t\tthrow new ImplementationException('supervised project dispatcher crashed')\n\t\t\t\t},\n\t\t\t})\n\t\t\trunning.set(container.project.slug, { worker, container })\n\t\t\ttry {\n\t\t\t\tif (current) {\n\t\t\t\t\tawait (await current.worker).end()\n\t\t\t\t}\n\t\t\t\tawait worker\n\t\t\t\tlogger.debug('Project dispatch worker started', { project: container.project.slug })\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(e, { message: 'Project dispatch worker start failed', project: container.project.slug })\n\t\t\t\trunning.delete(container.project.slug)\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\tconst projectTracker = new Supervisor(\n\t\t\tnew AcquiringListener(\n\t\t\t\ttenantContainer.databaseContext.client,\n\t\t\t\t'project_updated',\n\t\t\t\tasync () => {\n\t\t\t\t\tlogger.debug('Project config change detected, reloading dispatch workers')\n\t\t\t\t\tawait endProjectWorkers()\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait startWorkers(true)\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tlogger.error(e, { message: 'Dispatch workers reload failed, terminating' })\n\t\t\t\t\t\tawait endAll()\n\t\t\t\t\t\tonError(e)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t)\n\n\t\tconst runningProjectTracker = await projectTracker.run({\n\t\t\tlogger,\n\t\t\tonError: () => {\n\t\t\t\tthrow new ImplementationException('supervised project tracker crashed')\n\t\t\t},\n\t\t})\n\t\tconst fetchProjects = async () => await tenantContainer.projectManager.getProjects(tenantContainer.databaseContext)\n\n\t\tconst startWorkers = async (isReloading: boolean) => {\n\t\t\ttry {\n\t\t\t\tconst projects = await fetchProjects()\n\t\t\t\tfor (const project of projects) {\n\t\t\t\t\tconst container = await projectGroup.projectContainerResolver.getProjectContainer(project.slug)\n\t\t\t\t\tif (container) {\n\t\t\t\t\t\tawait refreshProjectWorker(container, isReloading)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tawait endAll()\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\tconst endProjectWorkers = async () => {\n\t\t\tconst workers = [...running.values()]\n\t\t\trunning.clear()\n\t\t\tawait Promise.allSettled(workers.map(async ({ worker }) => await (await worker).end()))\n\t\t}\n\t\tconst endAll = async () => {\n\t\t\tlogger.debug('Terminating project dispatch workers...')\n\t\t\tcleanupListener()\n\t\t\ttry {\n\t\t\t\tawait runningProjectTracker.end()\n\t\t\t} catch {\n\t\t\t}\n\t\t\tawait endProjectWorkers()\n\t\t\tlogger.debug('Project dispatch workers terminated')\n\t\t}\n\n\t\tawait startWorkers(false)\n\n\t\treturn {\n\t\t\tend: endAll,\n\t\t}\n\t}\n}\n"],"names":["Supervisor","ImplementationException","AcquiringListener"],"mappings":"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"}
@@ -61,21 +61,23 @@ class DispatchWorkerSupervisor {
61
61
  throw e;
62
62
  }
63
63
  };
64
- const projectTracker = new Supervisor(new AcquiringListener(
65
- tenantContainer.databaseContext.client,
66
- "project_updated",
67
- async () => {
68
- logger.debug("Project config change detected, reloading dispatch workers");
69
- await endProjectWorkers();
70
- try {
71
- await startWorkers(true);
72
- } catch (e) {
73
- logger.error(e, { message: "Dispatch workers reload failed, terminating" });
74
- await endAll();
75
- onError(e);
64
+ const projectTracker = new Supervisor(
65
+ new AcquiringListener(
66
+ tenantContainer.databaseContext.client,
67
+ "project_updated",
68
+ async () => {
69
+ logger.debug("Project config change detected, reloading dispatch workers");
70
+ await endProjectWorkers();
71
+ try {
72
+ await startWorkers(true);
73
+ } catch (e) {
74
+ logger.error(e, { message: "Dispatch workers reload failed, terminating" });
75
+ await endAll();
76
+ onError(e);
77
+ }
76
78
  }
77
- }
78
- ));
79
+ )
80
+ );
79
81
  const runningProjectTracker = await projectTracker.run({
80
82
  logger,
81
83
  onError: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"DispatchWorkerSupervisor.js","sources":["../../../../../packages/engine-actions/src/dispatch/DispatchWorkerSupervisor.ts"],"sourcesContent":["import { ProjectContainer, ProjectGroupContainer } from '@contember/engine-http'\nimport { AcquiringListener } from '@contember/database'\nimport { Runnable, RunnableArgs, Running, Supervisor } from '@contember/engine-common'\nimport { ProjectDispatcherFactory } from './ProjectDispatcher'\nimport { Logger } from '@contember/logger'\nimport { ImplementationException } from '../ImplementationException'\n\nexport class DispatchWorkerSupervisorFactory {\n\n\tconstructor(\n\t\tprivate projectDispatcherFactory: ProjectDispatcherFactory,\n\t) {\n\t}\n\n\tpublic create(projectGroup: ProjectGroupContainer): DispatchWorkerSupervisor {\n\t\treturn new DispatchWorkerSupervisor(this.projectDispatcherFactory, projectGroup)\n\t}\n}\n\nexport class DispatchWorkerSupervisor implements Runnable {\n\tconstructor(\n\t\tprivate projectDispatcherFactory: ProjectDispatcherFactory,\n\t\tprivate projectGroup: ProjectGroupContainer,\n\t) {\n\t}\n\n\tpublic async run({ logger, onError }: RunnableArgs) {\n\t\tconst projectGroup = this.projectGroup\n\t\tconst tenantContainer = projectGroup.tenantContainer\n\t\tconst projectContainerResolver = projectGroup.projectContainerResolver\n\n\t\tconst running = new Map<string, { worker: Promise<Running>; container: ProjectContainer }>()\n\n\t\tconst cleanupListener = projectContainerResolver.on('destroy', async ({ container }) => {\n\t\t\tconst runningForProject = running.get(container.project.slug)\n\t\t\tif (!runningForProject) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\trunning.delete(container.project.slug)\n\t\t\tawait (await runningForProject.worker).end()\n\t\t})\n\n\t\tconst refreshProjectWorker = async (container: ProjectContainer, isReloading: boolean) => {\n\t\t\tconst db = container.systemDatabaseContext\n\t\t\tconst current = running.get(container.project.slug)\n\t\t\tif (current && current.container === container) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst dispatcher = this.projectDispatcherFactory.create({\n\t\t\t\tdb,\n\t\t\t\tcontentSchemaResolver: container.contentSchemaResolver,\n\t\t\t\tprojectSlug: container.project.slug,\n\t\t\t})\n\t\t\tconst supervisedDispatcher = new Supervisor(\n\t\t\t\tdispatcher,\n\t\t\t\t{ startupMax: isReloading ? Number.MAX_VALUE : 10 },\n\t\t\t)\n\t\t\tconst worker = supervisedDispatcher.run({\n\t\t\t\tlogger,\n\t\t\t\tonError: () => {\n\t\t\t\t\tthrow new ImplementationException('supervised project dispatcher crashed')\n\t\t\t\t},\n\t\t\t})\n\t\t\trunning.set(container.project.slug, { worker, container })\n\t\t\ttry {\n\t\t\t\tif (current) {\n\t\t\t\t\tawait (await current.worker).end()\n\t\t\t\t}\n\t\t\t\tawait worker\n\t\t\t\tlogger.debug('Project dispatch worker started', { project: container.project.slug })\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(e, { message: 'Project dispatch worker start failed', project: container.project.slug })\n\t\t\t\trunning.delete(container.project.slug)\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\tconst projectTracker = new Supervisor(new AcquiringListener(\n\t\t\ttenantContainer.databaseContext.client,\n\t\t\t'project_updated',\n\t\t\tasync () => {\n\t\t\t\tlogger.debug('Project config change detected, reloading dispatch workers')\n\t\t\t\tawait endProjectWorkers()\n\t\t\t\ttry {\n\t\t\t\t\tawait startWorkers(true)\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlogger.error(e, { message: 'Dispatch workers reload failed, terminating' })\n\t\t\t\t\tawait endAll()\n\t\t\t\t\tonError(e)\n\t\t\t\t}\n\t\t\t},\n\t\t))\n\n\t\tconst runningProjectTracker = await projectTracker.run({\n\t\t\tlogger,\n\t\t\tonError: () => {\n\t\t\t\tthrow new ImplementationException('supervised project tracker crashed')\n\t\t\t},\n\t\t})\n\t\tconst fetchProjects = async () => await tenantContainer.projectManager.getProjects(tenantContainer.databaseContext)\n\n\t\tconst startWorkers = async (isReloading: boolean) => {\n\t\t\ttry {\n\t\t\t\tconst projects = await fetchProjects()\n\t\t\t\tfor (const project of projects) {\n\t\t\t\t\tconst container = await projectGroup.projectContainerResolver.getProjectContainer(project.slug)\n\t\t\t\t\tif (container) {\n\t\t\t\t\t\tawait refreshProjectWorker(container, isReloading)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tawait endAll()\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\tconst endProjectWorkers = async () => {\n\t\t\tconst workers = [...running.values()]\n\t\t\trunning.clear()\n\t\t\tawait Promise.allSettled(workers.map(async ({ worker }) => await (await worker).end()))\n\t\t}\n\t\tconst endAll = async () => {\n\t\t\tlogger.debug('Terminating project dispatch workers...')\n\t\t\tcleanupListener()\n\t\t\ttry {\n\t\t\t\tawait runningProjectTracker.end()\n\t\t\t} catch {\n\t\t\t}\n\t\t\tawait endProjectWorkers()\n\t\t\tlogger.debug('Project dispatch workers terminated')\n\t\t}\n\n\t\tawait startWorkers(false)\n\n\t\treturn {\n\t\t\tend: endAll,\n\t\t}\n\t}\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DispatchWorkerSupervisor.js","sources":["../../../../../packages/engine-actions/src/dispatch/DispatchWorkerSupervisor.ts"],"sourcesContent":["import { ProjectContainer, ProjectGroupContainer } from '@contember/engine-http'\nimport { AcquiringListener } from '@contember/database'\nimport { Runnable, RunnableArgs, Running, Supervisor } from '@contember/engine-common'\nimport { ProjectDispatcherFactory } from './ProjectDispatcher'\nimport { Logger } from '@contember/logger'\nimport { ImplementationException } from '../ImplementationException'\n\nexport class DispatchWorkerSupervisorFactory {\n\tconstructor(\n\t\tprivate projectDispatcherFactory: ProjectDispatcherFactory,\n\t) {\n\t}\n\n\tpublic create(projectGroup: ProjectGroupContainer): DispatchWorkerSupervisor {\n\t\treturn new DispatchWorkerSupervisor(this.projectDispatcherFactory, projectGroup)\n\t}\n}\n\nexport class DispatchWorkerSupervisor implements Runnable {\n\tconstructor(\n\t\tprivate projectDispatcherFactory: ProjectDispatcherFactory,\n\t\tprivate projectGroup: ProjectGroupContainer,\n\t) {\n\t}\n\n\tpublic async run({ logger, onError }: RunnableArgs) {\n\t\tconst projectGroup = this.projectGroup\n\t\tconst tenantContainer = projectGroup.tenantContainer\n\t\tconst projectContainerResolver = projectGroup.projectContainerResolver\n\n\t\tconst running = new Map<string, { worker: Promise<Running>; container: ProjectContainer }>()\n\n\t\tconst cleanupListener = projectContainerResolver.on('destroy', async ({ container }) => {\n\t\t\tconst runningForProject = running.get(container.project.slug)\n\t\t\tif (!runningForProject) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\trunning.delete(container.project.slug)\n\t\t\tawait (await runningForProject.worker).end()\n\t\t})\n\n\t\tconst refreshProjectWorker = async (container: ProjectContainer, isReloading: boolean) => {\n\t\t\tconst db = container.systemDatabaseContext\n\t\t\tconst current = running.get(container.project.slug)\n\t\t\tif (current && current.container === container) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst dispatcher = this.projectDispatcherFactory.create({\n\t\t\t\tdb,\n\t\t\t\tcontentSchemaResolver: container.contentSchemaResolver,\n\t\t\t\tprojectSlug: container.project.slug,\n\t\t\t})\n\t\t\tconst supervisedDispatcher = new Supervisor(\n\t\t\t\tdispatcher,\n\t\t\t\t{ startupMax: isReloading ? Number.MAX_VALUE : 10 },\n\t\t\t)\n\t\t\tconst worker = supervisedDispatcher.run({\n\t\t\t\tlogger,\n\t\t\t\tonError: () => {\n\t\t\t\t\tthrow new ImplementationException('supervised project dispatcher crashed')\n\t\t\t\t},\n\t\t\t})\n\t\t\trunning.set(container.project.slug, { worker, container })\n\t\t\ttry {\n\t\t\t\tif (current) {\n\t\t\t\t\tawait (await current.worker).end()\n\t\t\t\t}\n\t\t\t\tawait worker\n\t\t\t\tlogger.debug('Project dispatch worker started', { project: container.project.slug })\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(e, { message: 'Project dispatch worker start failed', project: container.project.slug })\n\t\t\t\trunning.delete(container.project.slug)\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\tconst projectTracker = new Supervisor(\n\t\t\tnew AcquiringListener(\n\t\t\t\ttenantContainer.databaseContext.client,\n\t\t\t\t'project_updated',\n\t\t\t\tasync () => {\n\t\t\t\t\tlogger.debug('Project config change detected, reloading dispatch workers')\n\t\t\t\t\tawait endProjectWorkers()\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait startWorkers(true)\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tlogger.error(e, { message: 'Dispatch workers reload failed, terminating' })\n\t\t\t\t\t\tawait endAll()\n\t\t\t\t\t\tonError(e)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t)\n\n\t\tconst runningProjectTracker = await projectTracker.run({\n\t\t\tlogger,\n\t\t\tonError: () => {\n\t\t\t\tthrow new ImplementationException('supervised project tracker crashed')\n\t\t\t},\n\t\t})\n\t\tconst fetchProjects = async () => await tenantContainer.projectManager.getProjects(tenantContainer.databaseContext)\n\n\t\tconst startWorkers = async (isReloading: boolean) => {\n\t\t\ttry {\n\t\t\t\tconst projects = await fetchProjects()\n\t\t\t\tfor (const project of projects) {\n\t\t\t\t\tconst container = await projectGroup.projectContainerResolver.getProjectContainer(project.slug)\n\t\t\t\t\tif (container) {\n\t\t\t\t\t\tawait refreshProjectWorker(container, isReloading)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tawait endAll()\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\t\tconst endProjectWorkers = async () => {\n\t\t\tconst workers = [...running.values()]\n\t\t\trunning.clear()\n\t\t\tawait Promise.allSettled(workers.map(async ({ worker }) => await (await worker).end()))\n\t\t}\n\t\tconst endAll = async () => {\n\t\t\tlogger.debug('Terminating project dispatch workers...')\n\t\t\tcleanupListener()\n\t\t\ttry {\n\t\t\t\tawait runningProjectTracker.end()\n\t\t\t} catch {\n\t\t\t}\n\t\t\tawait endProjectWorkers()\n\t\t\tlogger.debug('Project dispatch workers terminated')\n\t\t}\n\n\t\tawait startWorkers(false)\n\n\t\treturn {\n\t\t\tend: endAll,\n\t\t}\n\t}\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"EventDispatcher.cjs","sources":["../../../../../packages/engine-actions/src/dispatch/EventDispatcher.ts"],"sourcesContent":["import { EventsRepository } from './EventsRepository'\nimport { TargetHandlerResolver } from './TargetHandlerResolver'\nimport { HandledEvent } from './types'\nimport { Logger } from '@contember/logger'\nimport { ContentSchemaResolver } from '@contember/engine-http'\nimport { DatabaseContext } from '@contember/engine-system-api'\nimport { VariablesManager } from '../model/VariablesManager'\n\n\ntype ProcessBatchArgs = {\n\tdb: DatabaseContext\n\tcontentSchemaResolver: ContentSchemaResolver\n\tlogger: Logger\n}\n\ntype ProcessBatchResult = {\n\tsucceed: number\n\tfailed: number\n\tbackoffMs: number | undefined\n}\n\nexport class EventDispatcher {\n\n\tconstructor(\n\t\tprivate readonly eventsRepository: EventsRepository,\n\t\tprivate readonly variablesManager: VariablesManager,\n\t\tprivate readonly invokeResolver: TargetHandlerResolver,\n\t) {\n\t}\n\n\tasync processBatch({ db, contentSchemaResolver, logger }: ProcessBatchArgs): Promise<ProcessBatchResult> {\n\t\tconst schema = (await contentSchemaResolver.getSchema({ db, normalize: true })).schema\n\t\tconst batch = await this.eventsRepository.fetchBatch(schema.actions, db.client)\n\t\tconst batchId = Math.random().toString().substring(2)\n\t\tconst batchLogger = logger.child({ loc: 'Actions.EventDispatcher', batchId })\n\t\tif (!batch.ok) {\n\t\t\tbatchLogger.debug('Nothing to process', {\n\t\t\t\tbackoffMs: batch.backoffMs ?? 'undefined',\n\t\t\t})\n\t\t\treturn { failed: 0, succeed: 0, backoffMs: batch.backoffMs }\n\t\t}\n\t\tconst { target, events } = batch\n\t\ttry {\n\t\t\tconst handler = this.invokeResolver.resolveHandler(target)\n\t\t\tbatchLogger.debug('Processing started', {\n\t\t\t\tevents: batch.events.map(it => it.id),\n\t\t\t})\n\t\t\tconst variables = await this.variablesManager.fetchVariables(db)\n\t\t\tconst handledEvents = await handler.handle({ target, events, logger: batchLogger, variables })\n\t\t\tconst [succeed, failed] = await this.eventsRepository.persistProcessed(db.client, handledEvents)\n\t\t\tbatchLogger.debug('Processing done', { succeed, failed })\n\t\t\treturn { succeed, failed, backoffMs: 0 }\n\t\t} catch (e) {\n\t\t\tlogger.error(e, { loc: 'EventDispatcher', batchId })\n\t\t\tconst failedEvents = events.map((it): HandledEvent => ({\n\t\t\t\trow: it,\n\t\t\t\tresult: { ok: false, errorMessage: `Internal error` },\n\t\t\t}))\n\t\t\tawait this.eventsRepository.persistProcessed(db.client, failedEvents)\n\n\t\t\treturn { succeed: 0, failed: batch.events.length, backoffMs: 0 }\n\t\t}\n\t}\n}\n"],"names":[],"mappings":";;AAqBO,MAAM,gBAAgB;AAAA,EAE5B,YACkB,kBACA,kBACA,gBAChB;AAHgB,SAAA,mBAAA;AACA,SAAA,mBAAA;AACA,SAAA,iBAAA;AAAA,EAAA;AAAA,EAIlB,MAAM,aAAa,EAAE,IAAI,uBAAuB,UAAyD;AAClG,UAAA,UAAU,MAAM,sBAAsB,UAAU,EAAE,IAAI,WAAW,KAAM,CAAA,GAAG;AAC1E,UAAA,QAAQ,MAAM,KAAK,iBAAiB,WAAW,OAAO,SAAS,GAAG,MAAM;AAC9E,UAAM,UAAU,KAAK,OAAA,EAAS,SAAS,EAAE,UAAU,CAAC;AACpD,UAAM,cAAc,OAAO,MAAM,EAAE,KAAK,2BAA2B,SAAS;AACxE,QAAA,CAAC,MAAM,IAAI;AACd,kBAAY,MAAM,sBAAsB;AAAA,QACvC,WAAW,MAAM,aAAa;AAAA,MAAA,CAC9B;AACD,aAAO,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,MAAM,UAAU;AAAA,IAAA;AAEtD,UAAA,EAAE,QAAQ,OAAA,IAAW;AACvB,QAAA;AACH,YAAM,UAAU,KAAK,eAAe,eAAe,MAAM;AACzD,kBAAY,MAAM,sBAAsB;AAAA,QACvC,QAAQ,MAAM,OAAO,IAAI,CAAA,OAAM,GAAG,EAAE;AAAA,MAAA,CACpC;AACD,YAAM,YAAY,MAAM,KAAK,iBAAiB,eAAe,EAAE;AACzD,YAAA,gBAAgB,MAAM,QAAQ,OAAO,EAAE,QAAQ,QAAQ,QAAQ,aAAa,WAAW;AACvF,YAAA,CAAC,SAAS,MAAM,IAAI,MAAM,KAAK,iBAAiB,iBAAiB,GAAG,QAAQ,aAAa;AAC/F,kBAAY,MAAM,mBAAmB,EAAE,SAAS,QAAQ;AACxD,aAAO,EAAE,SAAS,QAAQ,WAAW,EAAE;AAAA,aAC/B,GAAG;AACX,aAAO,MAAM,GAAG,EAAE,KAAK,mBAAmB,SAAS;AACnD,YAAM,eAAe,OAAO,IAAI,CAAC,QAAsB;AAAA,QACtD,KAAK;AAAA,QACL,QAAQ,EAAE,IAAI,OAAO,cAAc,iBAAiB;AAAA,MAAA,EACnD;AACF,YAAM,KAAK,iBAAiB,iBAAiB,GAAG,QAAQ,YAAY;AAE7D,aAAA,EAAE,SAAS,GAAG,QAAQ,MAAM,OAAO,QAAQ,WAAW,EAAE;AAAA,IAAA;AAAA,EAChE;AAEF;;"}
1
+ {"version":3,"file":"EventDispatcher.cjs","sources":["../../../../../packages/engine-actions/src/dispatch/EventDispatcher.ts"],"sourcesContent":["import { EventsRepository } from './EventsRepository'\nimport { TargetHandlerResolver } from './TargetHandlerResolver'\nimport { HandledEvent } from './types'\nimport { Logger } from '@contember/logger'\nimport { ContentSchemaResolver } from '@contember/engine-http'\nimport { DatabaseContext } from '@contember/engine-system-api'\nimport { VariablesManager } from '../model/VariablesManager'\n\ntype ProcessBatchArgs = {\n\tdb: DatabaseContext\n\tcontentSchemaResolver: ContentSchemaResolver\n\tlogger: Logger\n}\n\ntype ProcessBatchResult = {\n\tsucceed: number\n\tfailed: number\n\tbackoffMs: number | undefined\n}\n\nexport class EventDispatcher {\n\tconstructor(\n\t\tprivate readonly eventsRepository: EventsRepository,\n\t\tprivate readonly variablesManager: VariablesManager,\n\t\tprivate readonly invokeResolver: TargetHandlerResolver,\n\t) {\n\t}\n\n\tasync processBatch({ db, contentSchemaResolver, logger }: ProcessBatchArgs): Promise<ProcessBatchResult> {\n\t\tconst schema = (await contentSchemaResolver.getSchema({ db, normalize: true })).schema\n\t\tconst batch = await this.eventsRepository.fetchBatch(schema.actions, db.client)\n\t\tconst batchId = Math.random().toString().substring(2)\n\t\tconst batchLogger = logger.child({ loc: 'Actions.EventDispatcher', batchId })\n\t\tif (!batch.ok) {\n\t\t\tbatchLogger.debug('Nothing to process', {\n\t\t\t\tbackoffMs: batch.backoffMs ?? 'undefined',\n\t\t\t})\n\t\t\treturn { failed: 0, succeed: 0, backoffMs: batch.backoffMs }\n\t\t}\n\t\tconst { target, events } = batch\n\t\ttry {\n\t\t\tconst handler = this.invokeResolver.resolveHandler(target)\n\t\t\tbatchLogger.debug('Processing started', {\n\t\t\t\tevents: batch.events.map(it => it.id),\n\t\t\t})\n\t\t\tconst variables = await this.variablesManager.fetchVariables(db)\n\t\t\tconst handledEvents = await handler.handle({ target, events, logger: batchLogger, variables })\n\t\t\tconst [succeed, failed] = await this.eventsRepository.persistProcessed(db.client, handledEvents)\n\t\t\tbatchLogger.debug('Processing done', { succeed, failed })\n\t\t\treturn { succeed, failed, backoffMs: 0 }\n\t\t} catch (e) {\n\t\t\tlogger.error(e, { loc: 'EventDispatcher', batchId })\n\t\t\tconst failedEvents = events.map((it): HandledEvent => ({\n\t\t\t\trow: it,\n\t\t\t\tresult: { ok: false, errorMessage: `Internal error` },\n\t\t\t}))\n\t\t\tawait this.eventsRepository.persistProcessed(db.client, failedEvents)\n\n\t\t\treturn { succeed: 0, failed: batch.events.length, backoffMs: 0 }\n\t\t}\n\t}\n}\n"],"names":[],"mappings":";;AAoBO,MAAM,gBAAgB;AAAA,EAC5B,YACkB,kBACA,kBACA,gBAChB;AAHgB,SAAA,mBAAA;AACA,SAAA,mBAAA;AACA,SAAA,iBAAA;AAAA,EAElB;AAAA,EAEA,MAAM,aAAa,EAAE,IAAI,uBAAuB,UAAyD;AACxG,UAAM,UAAU,MAAM,sBAAsB,UAAU,EAAE,IAAI,WAAW,KAAA,CAAM,GAAG;AAChF,UAAM,QAAQ,MAAM,KAAK,iBAAiB,WAAW,OAAO,SAAS,GAAG,MAAM;AAC9E,UAAM,UAAU,KAAK,OAAA,EAAS,SAAA,EAAW,UAAU,CAAC;AACpD,UAAM,cAAc,OAAO,MAAM,EAAE,KAAK,2BAA2B,SAAS;AAC5E,QAAI,CAAC,MAAM,IAAI;AACd,kBAAY,MAAM,sBAAsB;AAAA,QACvC,WAAW,MAAM,aAAa;AAAA,MAAA,CAC9B;AACD,aAAO,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,MAAM,UAAA;AAAA,IAClD;AACA,UAAM,EAAE,QAAQ,OAAA,IAAW;AAC3B,QAAI;AACH,YAAM,UAAU,KAAK,eAAe,eAAe,MAAM;AACzD,kBAAY,MAAM,sBAAsB;AAAA,QACvC,QAAQ,MAAM,OAAO,IAAI,CAAA,OAAM,GAAG,EAAE;AAAA,MAAA,CACpC;AACD,YAAM,YAAY,MAAM,KAAK,iBAAiB,eAAe,EAAE;AAC/D,YAAM,gBAAgB,MAAM,QAAQ,OAAO,EAAE,QAAQ,QAAQ,QAAQ,aAAa,WAAW;AAC7F,YAAM,CAAC,SAAS,MAAM,IAAI,MAAM,KAAK,iBAAiB,iBAAiB,GAAG,QAAQ,aAAa;AAC/F,kBAAY,MAAM,mBAAmB,EAAE,SAAS,QAAQ;AACxD,aAAO,EAAE,SAAS,QAAQ,WAAW,EAAA;AAAA,IACtC,SAAS,GAAG;AACX,aAAO,MAAM,GAAG,EAAE,KAAK,mBAAmB,SAAS;AACnD,YAAM,eAAe,OAAO,IAAI,CAAC,QAAsB;AAAA,QACtD,KAAK;AAAA,QACL,QAAQ,EAAE,IAAI,OAAO,cAAc,iBAAA;AAAA,MAAiB,EACnD;AACF,YAAM,KAAK,iBAAiB,iBAAiB,GAAG,QAAQ,YAAY;AAEpE,aAAO,EAAE,SAAS,GAAG,QAAQ,MAAM,OAAO,QAAQ,WAAW,EAAA;AAAA,IAC9D;AAAA,EACD;AACD;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"EventDispatcher.js","sources":["../../../../../packages/engine-actions/src/dispatch/EventDispatcher.ts"],"sourcesContent":["import { EventsRepository } from './EventsRepository'\nimport { TargetHandlerResolver } from './TargetHandlerResolver'\nimport { HandledEvent } from './types'\nimport { Logger } from '@contember/logger'\nimport { ContentSchemaResolver } from '@contember/engine-http'\nimport { DatabaseContext } from '@contember/engine-system-api'\nimport { VariablesManager } from '../model/VariablesManager'\n\n\ntype ProcessBatchArgs = {\n\tdb: DatabaseContext\n\tcontentSchemaResolver: ContentSchemaResolver\n\tlogger: Logger\n}\n\ntype ProcessBatchResult = {\n\tsucceed: number\n\tfailed: number\n\tbackoffMs: number | undefined\n}\n\nexport class EventDispatcher {\n\n\tconstructor(\n\t\tprivate readonly eventsRepository: EventsRepository,\n\t\tprivate readonly variablesManager: VariablesManager,\n\t\tprivate readonly invokeResolver: TargetHandlerResolver,\n\t) {\n\t}\n\n\tasync processBatch({ db, contentSchemaResolver, logger }: ProcessBatchArgs): Promise<ProcessBatchResult> {\n\t\tconst schema = (await contentSchemaResolver.getSchema({ db, normalize: true })).schema\n\t\tconst batch = await this.eventsRepository.fetchBatch(schema.actions, db.client)\n\t\tconst batchId = Math.random().toString().substring(2)\n\t\tconst batchLogger = logger.child({ loc: 'Actions.EventDispatcher', batchId })\n\t\tif (!batch.ok) {\n\t\t\tbatchLogger.debug('Nothing to process', {\n\t\t\t\tbackoffMs: batch.backoffMs ?? 'undefined',\n\t\t\t})\n\t\t\treturn { failed: 0, succeed: 0, backoffMs: batch.backoffMs }\n\t\t}\n\t\tconst { target, events } = batch\n\t\ttry {\n\t\t\tconst handler = this.invokeResolver.resolveHandler(target)\n\t\t\tbatchLogger.debug('Processing started', {\n\t\t\t\tevents: batch.events.map(it => it.id),\n\t\t\t})\n\t\t\tconst variables = await this.variablesManager.fetchVariables(db)\n\t\t\tconst handledEvents = await handler.handle({ target, events, logger: batchLogger, variables })\n\t\t\tconst [succeed, failed] = await this.eventsRepository.persistProcessed(db.client, handledEvents)\n\t\t\tbatchLogger.debug('Processing done', { succeed, failed })\n\t\t\treturn { succeed, failed, backoffMs: 0 }\n\t\t} catch (e) {\n\t\t\tlogger.error(e, { loc: 'EventDispatcher', batchId })\n\t\t\tconst failedEvents = events.map((it): HandledEvent => ({\n\t\t\t\trow: it,\n\t\t\t\tresult: { ok: false, errorMessage: `Internal error` },\n\t\t\t}))\n\t\t\tawait this.eventsRepository.persistProcessed(db.client, failedEvents)\n\n\t\t\treturn { succeed: 0, failed: batch.events.length, backoffMs: 0 }\n\t\t}\n\t}\n}\n"],"names":[],"mappings":"AAqBO,MAAM,gBAAgB;AAAA,EAE5B,YACkB,kBACA,kBACA,gBAChB;AAHgB,SAAA,mBAAA;AACA,SAAA,mBAAA;AACA,SAAA,iBAAA;AAAA,EAAA;AAAA,EAIlB,MAAM,aAAa,EAAE,IAAI,uBAAuB,UAAyD;AAClG,UAAA,UAAU,MAAM,sBAAsB,UAAU,EAAE,IAAI,WAAW,KAAM,CAAA,GAAG;AAC1E,UAAA,QAAQ,MAAM,KAAK,iBAAiB,WAAW,OAAO,SAAS,GAAG,MAAM;AAC9E,UAAM,UAAU,KAAK,OAAA,EAAS,SAAS,EAAE,UAAU,CAAC;AACpD,UAAM,cAAc,OAAO,MAAM,EAAE,KAAK,2BAA2B,SAAS;AACxE,QAAA,CAAC,MAAM,IAAI;AACd,kBAAY,MAAM,sBAAsB;AAAA,QACvC,WAAW,MAAM,aAAa;AAAA,MAAA,CAC9B;AACD,aAAO,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,MAAM,UAAU;AAAA,IAAA;AAEtD,UAAA,EAAE,QAAQ,OAAA,IAAW;AACvB,QAAA;AACH,YAAM,UAAU,KAAK,eAAe,eAAe,MAAM;AACzD,kBAAY,MAAM,sBAAsB;AAAA,QACvC,QAAQ,MAAM,OAAO,IAAI,CAAA,OAAM,GAAG,EAAE;AAAA,MAAA,CACpC;AACD,YAAM,YAAY,MAAM,KAAK,iBAAiB,eAAe,EAAE;AACzD,YAAA,gBAAgB,MAAM,QAAQ,OAAO,EAAE,QAAQ,QAAQ,QAAQ,aAAa,WAAW;AACvF,YAAA,CAAC,SAAS,MAAM,IAAI,MAAM,KAAK,iBAAiB,iBAAiB,GAAG,QAAQ,aAAa;AAC/F,kBAAY,MAAM,mBAAmB,EAAE,SAAS,QAAQ;AACxD,aAAO,EAAE,SAAS,QAAQ,WAAW,EAAE;AAAA,aAC/B,GAAG;AACX,aAAO,MAAM,GAAG,EAAE,KAAK,mBAAmB,SAAS;AACnD,YAAM,eAAe,OAAO,IAAI,CAAC,QAAsB;AAAA,QACtD,KAAK;AAAA,QACL,QAAQ,EAAE,IAAI,OAAO,cAAc,iBAAiB;AAAA,MAAA,EACnD;AACF,YAAM,KAAK,iBAAiB,iBAAiB,GAAG,QAAQ,YAAY;AAE7D,aAAA,EAAE,SAAS,GAAG,QAAQ,MAAM,OAAO,QAAQ,WAAW,EAAE;AAAA,IAAA;AAAA,EAChE;AAEF;"}
1
+ {"version":3,"file":"EventDispatcher.js","sources":["../../../../../packages/engine-actions/src/dispatch/EventDispatcher.ts"],"sourcesContent":["import { EventsRepository } from './EventsRepository'\nimport { TargetHandlerResolver } from './TargetHandlerResolver'\nimport { HandledEvent } from './types'\nimport { Logger } from '@contember/logger'\nimport { ContentSchemaResolver } from '@contember/engine-http'\nimport { DatabaseContext } from '@contember/engine-system-api'\nimport { VariablesManager } from '../model/VariablesManager'\n\ntype ProcessBatchArgs = {\n\tdb: DatabaseContext\n\tcontentSchemaResolver: ContentSchemaResolver\n\tlogger: Logger\n}\n\ntype ProcessBatchResult = {\n\tsucceed: number\n\tfailed: number\n\tbackoffMs: number | undefined\n}\n\nexport class EventDispatcher {\n\tconstructor(\n\t\tprivate readonly eventsRepository: EventsRepository,\n\t\tprivate readonly variablesManager: VariablesManager,\n\t\tprivate readonly invokeResolver: TargetHandlerResolver,\n\t) {\n\t}\n\n\tasync processBatch({ db, contentSchemaResolver, logger }: ProcessBatchArgs): Promise<ProcessBatchResult> {\n\t\tconst schema = (await contentSchemaResolver.getSchema({ db, normalize: true })).schema\n\t\tconst batch = await this.eventsRepository.fetchBatch(schema.actions, db.client)\n\t\tconst batchId = Math.random().toString().substring(2)\n\t\tconst batchLogger = logger.child({ loc: 'Actions.EventDispatcher', batchId })\n\t\tif (!batch.ok) {\n\t\t\tbatchLogger.debug('Nothing to process', {\n\t\t\t\tbackoffMs: batch.backoffMs ?? 'undefined',\n\t\t\t})\n\t\t\treturn { failed: 0, succeed: 0, backoffMs: batch.backoffMs }\n\t\t}\n\t\tconst { target, events } = batch\n\t\ttry {\n\t\t\tconst handler = this.invokeResolver.resolveHandler(target)\n\t\t\tbatchLogger.debug('Processing started', {\n\t\t\t\tevents: batch.events.map(it => it.id),\n\t\t\t})\n\t\t\tconst variables = await this.variablesManager.fetchVariables(db)\n\t\t\tconst handledEvents = await handler.handle({ target, events, logger: batchLogger, variables })\n\t\t\tconst [succeed, failed] = await this.eventsRepository.persistProcessed(db.client, handledEvents)\n\t\t\tbatchLogger.debug('Processing done', { succeed, failed })\n\t\t\treturn { succeed, failed, backoffMs: 0 }\n\t\t} catch (e) {\n\t\t\tlogger.error(e, { loc: 'EventDispatcher', batchId })\n\t\t\tconst failedEvents = events.map((it): HandledEvent => ({\n\t\t\t\trow: it,\n\t\t\t\tresult: { ok: false, errorMessage: `Internal error` },\n\t\t\t}))\n\t\t\tawait this.eventsRepository.persistProcessed(db.client, failedEvents)\n\n\t\t\treturn { succeed: 0, failed: batch.events.length, backoffMs: 0 }\n\t\t}\n\t}\n}\n"],"names":[],"mappings":"AAoBO,MAAM,gBAAgB;AAAA,EAC5B,YACkB,kBACA,kBACA,gBAChB;AAHgB,SAAA,mBAAA;AACA,SAAA,mBAAA;AACA,SAAA,iBAAA;AAAA,EAElB;AAAA,EAEA,MAAM,aAAa,EAAE,IAAI,uBAAuB,UAAyD;AACxG,UAAM,UAAU,MAAM,sBAAsB,UAAU,EAAE,IAAI,WAAW,KAAA,CAAM,GAAG;AAChF,UAAM,QAAQ,MAAM,KAAK,iBAAiB,WAAW,OAAO,SAAS,GAAG,MAAM;AAC9E,UAAM,UAAU,KAAK,OAAA,EAAS,SAAA,EAAW,UAAU,CAAC;AACpD,UAAM,cAAc,OAAO,MAAM,EAAE,KAAK,2BAA2B,SAAS;AAC5E,QAAI,CAAC,MAAM,IAAI;AACd,kBAAY,MAAM,sBAAsB;AAAA,QACvC,WAAW,MAAM,aAAa;AAAA,MAAA,CAC9B;AACD,aAAO,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,MAAM,UAAA;AAAA,IAClD;AACA,UAAM,EAAE,QAAQ,OAAA,IAAW;AAC3B,QAAI;AACH,YAAM,UAAU,KAAK,eAAe,eAAe,MAAM;AACzD,kBAAY,MAAM,sBAAsB;AAAA,QACvC,QAAQ,MAAM,OAAO,IAAI,CAAA,OAAM,GAAG,EAAE;AAAA,MAAA,CACpC;AACD,YAAM,YAAY,MAAM,KAAK,iBAAiB,eAAe,EAAE;AAC/D,YAAM,gBAAgB,MAAM,QAAQ,OAAO,EAAE,QAAQ,QAAQ,QAAQ,aAAa,WAAW;AAC7F,YAAM,CAAC,SAAS,MAAM,IAAI,MAAM,KAAK,iBAAiB,iBAAiB,GAAG,QAAQ,aAAa;AAC/F,kBAAY,MAAM,mBAAmB,EAAE,SAAS,QAAQ;AACxD,aAAO,EAAE,SAAS,QAAQ,WAAW,EAAA;AAAA,IACtC,SAAS,GAAG;AACX,aAAO,MAAM,GAAG,EAAE,KAAK,mBAAmB,SAAS;AACnD,YAAM,eAAe,OAAO,IAAI,CAAC,QAAsB;AAAA,QACtD,KAAK;AAAA,QACL,QAAQ,EAAE,IAAI,OAAO,cAAc,iBAAA;AAAA,MAAiB,EACnD;AACF,YAAM,KAAK,iBAAiB,iBAAiB,GAAG,QAAQ,YAAY;AAEpE,aAAO,EAAE,SAAS,GAAG,QAAQ,MAAM,OAAO,QAAQ,WAAW,EAAA;AAAA,IAC9D;AAAA,EACD;AACD;"}
@@ -28,10 +28,7 @@ class EventsRepository {
28
28
  async fetchInternal(db, limit, targetName) {
29
29
  const visibleAt = /* @__PURE__ */ new Date();
30
30
  visibleAt.setTime(visibleAt.getTime() + ACK_TIMEOUT_MS);
31
- return await Database.UpdateBuilder.create().table("actions_event").with(
32
- "events",
33
- (qb) => qb.select((it) => it.raw("*")).from("actions_event").match(EventsToProcessSpecification.eventsToProcessSpecification).where(targetName ? { target: targetName } : {}).limit(limit).lock(Database.LockType.forNoKeyUpdate, Database.LockModifier.skipLocked)
34
- ).values({
31
+ return await Database.UpdateBuilder.create().table("actions_event").with("events", (qb) => qb.select((it) => it.raw("*")).from("actions_event").match(EventsToProcessSpecification.eventsToProcessSpecification).where(targetName ? { target: targetName } : {}).limit(limit).lock(Database.LockType.forNoKeyUpdate, Database.LockModifier.skipLocked)).values({
35
32
  state: "processing",
36
33
  last_state_change: /* @__PURE__ */ new Date(),
37
34
  visible_at: visibleAt
@@ -52,10 +49,27 @@ class EventsRepository {
52
49
  }
53
50
  async requeue(db, events) {
54
51
  await Database.UpdateBuilder.create().table("actions_event").values({
55
- state: (it) => it.raw("CASE WHEN num_retries = 0 THEN ? ELSE ? END", "created", "retrying"),
52
+ state: (it) => it.raw(
53
+ `
54
+ CASE
55
+ WHEN num_retries = 0 THEN
56
+ ?::__SCHEMA__.actions_trigger_state
57
+ ELSE
58
+ ?::__SCHEMA__.actions_trigger_state END
59
+ `,
60
+ "created",
61
+ "retrying"
62
+ ),
56
63
  last_state_change: /* @__PURE__ */ new Date(),
57
64
  visible_at: /* @__PURE__ */ new Date()
58
- }).where((it) => it.in("id", events.map((it2) => it2.id))).execute(db);
65
+ }).where((it) => it.in("id", events)).execute(db);
66
+ }
67
+ async markStopped(db, events) {
68
+ await Database.UpdateBuilder.create().table("actions_event").values({
69
+ state: "stopped",
70
+ last_state_change: /* @__PURE__ */ new Date(),
71
+ resolved_at: /* @__PURE__ */ new Date()
72
+ }).where((it) => it.in("id", events)).execute(db);
59
73
  }
60
74
  async markSucceed(db, rows) {
61
75
  const now = /* @__PURE__ */ new Date();
@@ -67,13 +81,15 @@ class EventsRepository {
67
81
  }).where((it) => it.in("id", rows.map((it2) => it2.id))).execute(db);
68
82
  }
69
83
  async markFailed(db, event) {
70
- const numRetries = event.row.num_retries;
84
+ const numRetries = event.row.num_retries + 1;
71
85
  const now = /* @__PURE__ */ new Date();
72
86
  const nextAttempt = /* @__PURE__ */ new Date();
73
- nextAttempt.setTime(nextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries));
87
+ nextAttempt.setTime(
88
+ nextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries)
89
+ );
74
90
  await Database.UpdateBuilder.create().table("actions_event").values({
75
91
  last_state_change: now,
76
- num_retries: event.row.num_retries + 1,
92
+ num_retries: numRetries,
77
93
  log: JSON.stringify([...event.row.log, event.result]),
78
94
  ...numRetries < (event.target?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS) ? {
79
95
  state: "retrying",
@@ -84,13 +100,15 @@ class EventsRepository {
84
100
  }).where({ id: event.row.id }).execute(db);
85
101
  }
86
102
  async markFailedOnUnknownTarget(db, targetName, primaryEventId) {
87
- await Database.UpdateBuilder.create().table("actions_event").where((it) => it.or(
88
- (it2) => it2.and(
89
- (it3) => it3.in("state", ["retrying", "created", "processing"]).compare("visible_at", Database.Operator.lte, "now").compare("target", Database.Operator.eq, targetName)
90
- ).and(
91
- (it3) => it3.compare("id", Database.Operator.eq, primaryEventId)
103
+ await Database.UpdateBuilder.create().table("actions_event").where(
104
+ (it) => it.or(
105
+ (it2) => it2.and(
106
+ (it3) => it3.in("state", ["retrying", "created", "processing"]).compare("visible_at", Database.Operator.lte, "now").compare("target", Database.Operator.eq, targetName)
107
+ ).and(
108
+ (it3) => it3.compare("id", Database.Operator.eq, primaryEventId)
109
+ )
92
110
  )
93
- )).values({
111
+ ).values({
94
112
  // intentionally not retrying
95
113
  last_state_change: /* @__PURE__ */ new Date(),
96
114
  num_retries: (it) => it.raw("num_retries + 1"),
@@ -1 +1 @@
1
- {"version":3,"file":"EventsRepository.cjs","sources":["../../../../../packages/engine-actions/src/dispatch/EventsRepository.ts"],"sourcesContent":["import {\n\tClient,\n\tConnection,\n\tLiteral,\n\tLockModifier,\n\tLockType,\n\tOperator,\n\tSelectBuilder,\n\tUpdateBuilder,\n} from '@contember/database'\nimport { EventRow, HandledEvent } from './types'\nimport { Actions } from '@contember/schema'\nimport { eventsToProcessSpecification, eventsToProcessStateSpecification } from '../model/EventsToProcessSpecification'\n\n\nconst ACK_TIMEOUT_MS = 1_000 * 60 * 10 // 10 minutes\nconst DEFAULT_REPEAT_INTERVAL_MS = 5_000 // 5 seconds\nconst DEFAULT_MAX_ATTEMPTS = 10\nconst DEFAULT_BATCH_SIZE = 1\n\nexport class EventsRepository {\n\n\tpublic async fetchBatch(actions: Actions.Schema, db: Client): Promise<FetchBatchResult> {\n\t\tconst primaryEvent = (await this.fetchInternal(db, 1))[0]\n\t\tif (!primaryEvent) {\n\t\t\treturn { ok: false, backoffMs: await this.fetchBackOff(db) }\n\t\t}\n\t\tconst target = actions.targets[primaryEvent.target]\n\t\tif (!target) {\n\t\t\tawait this.markFailedOnUnknownTarget(db, primaryEvent.target, primaryEvent.id)\n\t\t\treturn await this.fetchBatch(actions, db)\n\t\t}\n\t\tconst batchSize = (target.batchSize ?? DEFAULT_BATCH_SIZE) - 1\n\t\tconst batch = batchSize > 0 ? await this.fetchInternal(db, batchSize) : []\n\t\treturn { ok: true, events: [primaryEvent, ...batch], target }\n\t}\n\n\n\tprivate async fetchBackOff(db: Client): Promise<number | undefined> {\n\t\tconst result = await SelectBuilder.create<{ ms: number }>()\n\t\t\t.from('actions_event')\n\t\t\t.match(eventsToProcessStateSpecification)\n\t\t\t.select(it => it.raw('ceil(extract(epoch from visible_at - now()) * 1000)'), 'ms')\n\t\t\t.orderBy('visible_at', 'asc')\n\t\t\t.limit(1)\n\t\t\t.getResult(db)\n\n\t\treturn result.length ? Math.max(0, result[0].ms) : undefined\n\t}\n\n\n\tprivate async fetchInternal(db: Client, limit: number, targetName?: string): Promise<EventRow[]> {\n\t\tconst visibleAt = new Date()\n\t\tvisibleAt.setTime(visibleAt.getTime() + ACK_TIMEOUT_MS)\n\t\treturn await UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.with('events', qb => qb\n\t\t\t\t.select(it => it.raw('*'))\n\t\t\t\t.from('actions_event')\n\t\t\t\t.match(eventsToProcessSpecification)\n\t\t\t\t.where(targetName ? { target: targetName } : {})\n\t\t\t\t.limit(limit)\n\t\t\t\t.lock(LockType.forNoKeyUpdate, LockModifier.skipLocked),\n\t\t\t)\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'processing',\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tvisible_at: visibleAt,\n\t\t\t})\n\t\t\t.from(it => it.from('events').where(it => it.columnsEq(['events', 'id'], ['actions_event', 'id'])))\n\t\t\t.returning<EventRow>(new Literal('*'))\n\t\t\t.execute(db)\n\t}\n\n\tpublic async persistProcessed(db: Client, events: HandledEvent[]): Promise<[number, number]> {\n\t\treturn await db.transaction(async trx => {\n\t\t\tawait trx.query(Connection.REPEATABLE_READ)\n\t\t\tconst succeed = events.filter(it => it.result.ok)\n\t\t\tawait this.markSucceed(trx, succeed.map(it => it.row))\n\n\t\t\tfor (const event of events) {\n\t\t\t\tif (!event.result.ok) {\n\t\t\t\t\tawait this.markFailed(trx, event)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn [succeed.length, events.length - succeed.length]\n\t\t})\n\t}\n\n\tpublic async requeue(db: Client, events: EventRow[]): Promise<void> {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: it => it.raw('CASE WHEN num_retries = 0 THEN ? ELSE ? END', 'created', 'retrying'),\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tvisible_at: new Date(),\n\t\t\t})\n\t\t\t.where(it => it.in('id', events.map(it => it.id)))\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markSucceed(db: Client, rows: EventRow[]): Promise<void> {\n\t\tconst now = new Date()\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'succeed',\n\t\t\t\tnum_retries: it => it.raw('num_retries + 1'),\n\t\t\t\tresolved_at: now,\n\t\t\t\tlast_state_change: now,\n\t\t\t})\n\t\t\t.where(it => it.in('id', rows.map(it => it.id)))\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markFailed(db: Client, event: HandledEvent): Promise<void> {\n\t\tconst numRetries = event.row.num_retries\n\t\tconst now = new Date()\n\t\tconst nextAttempt = new Date()\n\t\tnextAttempt.setTime(nextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries))\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tlast_state_change: now,\n\t\t\t\tnum_retries: event.row.num_retries + 1,\n\t\t\t\tlog: JSON.stringify([...event.row.log, event.result]) as any,\n\t\t\t\t...(numRetries < (event.target?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS) ? {\n\t\t\t\t\tstate: 'retrying',\n\t\t\t\t\tvisible_at: nextAttempt,\n\t\t\t\t} : {\n\t\t\t\t\tstate: 'failed',\n\t\t\t\t}),\n\t\t\t})\n\t\t\t.where({ id: event.row.id })\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markFailedOnUnknownTarget(db: Client, targetName: string, primaryEventId: string) {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.where(it => it.or(it => it\n\t\t\t\t.and(it => it\n\t\t\t\t\t.in('state', ['retrying', 'created', 'processing'])\n\t\t\t\t\t.compare('visible_at', Operator.lte, 'now')\n\t\t\t\t\t.compare('target', Operator.eq, targetName),\n\t\t\t\t)\n\t\t\t\t.and(it => it\n\t\t\t\t\t.compare('id', Operator.eq, primaryEventId),\n\t\t\t\t),\n\t\t\t))\n\t\t\t.values<EventRow>({\n\t\t\t\t// intentionally not retrying\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tnum_retries: it => it.raw('num_retries + 1'),\n\t\t\t\tlog: it => it.raw('log || ?::jsonb', { ok: false, errorMessage: `Event target ${targetName} not found, stopping.` }),\n\t\t\t\tstate: 'failed',\n\t\t\t\tresolved_at: new Date(),\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nexport type FetchBatchResult =\n\t| { ok: true; events: EventRow[]; target: Actions.AnyTarget }\n\t| { ok: false; backoffMs?: number }\n"],"names":["SelectBuilder","eventsToProcessStateSpecification","UpdateBuilder","eventsToProcessSpecification","LockType","LockModifier","it","Literal","Connection","Operator"],"mappings":"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"}
1
+ {"version":3,"file":"EventsRepository.cjs","sources":["../../../../../packages/engine-actions/src/dispatch/EventsRepository.ts"],"sourcesContent":["import { Client, Connection, Literal, LockModifier, LockType, Operator, SelectBuilder, UpdateBuilder } from '@contember/database'\nimport { EventRow, HandledEvent } from './types'\nimport { Actions } from '@contember/schema'\nimport { eventsToProcessSpecification, eventsToProcessStateSpecification } from '../model/EventsToProcessSpecification'\nimport { notify } from '../utils/notifyChannel'\n\nconst ACK_TIMEOUT_MS = 1_000 * 60 * 10 // 10 minutes\nconst DEFAULT_REPEAT_INTERVAL_MS = 5_000 // 5 seconds\nconst DEFAULT_MAX_ATTEMPTS = 10\nconst DEFAULT_BATCH_SIZE = 1\n\nexport class EventsRepository {\n\tpublic async fetchBatch(actions: Actions.Schema, db: Client): Promise<FetchBatchResult> {\n\t\tconst primaryEvent = (await this.fetchInternal(db, 1))[0]\n\t\tif (!primaryEvent) {\n\t\t\treturn { ok: false, backoffMs: await this.fetchBackOff(db) }\n\t\t}\n\t\tconst target = actions.targets[primaryEvent.target]\n\t\tif (!target) {\n\t\t\tawait this.markFailedOnUnknownTarget(db, primaryEvent.target, primaryEvent.id)\n\t\t\treturn await this.fetchBatch(actions, db)\n\t\t}\n\t\tconst batchSize = (target.batchSize ?? DEFAULT_BATCH_SIZE) - 1\n\t\tconst batch = batchSize > 0 ? await this.fetchInternal(db, batchSize) : []\n\t\treturn { ok: true, events: [primaryEvent, ...batch], target }\n\t}\n\n\tprivate async fetchBackOff(db: Client): Promise<number | undefined> {\n\t\tconst result = await SelectBuilder.create<{ ms: number }>()\n\t\t\t.from('actions_event')\n\t\t\t.match(eventsToProcessStateSpecification)\n\t\t\t.select(it => it.raw('ceil(extract(epoch from visible_at - now()) * 1000)'), 'ms')\n\t\t\t.orderBy('visible_at', 'asc')\n\t\t\t.limit(1)\n\t\t\t.getResult(db)\n\n\t\treturn result.length ? Math.max(0, result[0].ms) : undefined\n\t}\n\n\tprivate async fetchInternal(db: Client, limit: number, targetName?: string): Promise<EventRow[]> {\n\t\tconst visibleAt = new Date()\n\t\tvisibleAt.setTime(visibleAt.getTime() + ACK_TIMEOUT_MS)\n\t\treturn await UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.with('events', qb =>\n\t\t\t\tqb\n\t\t\t\t\t.select(it => it.raw('*'))\n\t\t\t\t\t.from('actions_event')\n\t\t\t\t\t.match(eventsToProcessSpecification)\n\t\t\t\t\t.where(targetName ? { target: targetName } : {})\n\t\t\t\t\t.limit(limit)\n\t\t\t\t\t.lock(LockType.forNoKeyUpdate, LockModifier.skipLocked))\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'processing',\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tvisible_at: visibleAt,\n\t\t\t})\n\t\t\t.from(it => it.from('events').where(it => it.columnsEq(['events', 'id'], ['actions_event', 'id'])))\n\t\t\t.returning<EventRow>(new Literal('*'))\n\t\t\t.execute(db)\n\t}\n\n\tpublic async persistProcessed(db: Client, events: HandledEvent[]): Promise<[number, number]> {\n\t\treturn await db.transaction(async trx => {\n\t\t\tawait trx.query(Connection.REPEATABLE_READ)\n\t\t\tconst succeed = events.filter(it => it.result.ok)\n\t\t\tawait this.markSucceed(trx, succeed.map(it => it.row))\n\n\t\t\tfor (const event of events) {\n\t\t\t\tif (!event.result.ok) {\n\t\t\t\t\tawait this.markFailed(trx, event)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn [succeed.length, events.length - succeed.length]\n\t\t})\n\t}\n\n\tpublic async requeue(db: Client, events: string[]): Promise<void> {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: it =>\n\t\t\t\t\tit.raw(\n\t\t\t\t\t\t`\n\t\t\t\t\tCASE \n\t\t\t\t\tWHEN num_retries = 0 THEN \n\t\t\t\t\t\t?::__SCHEMA__.actions_trigger_state \n\t\t\t\t\tELSE \n\t\t\t\t\t?::__SCHEMA__.actions_trigger_state END\n\t\t\t\t`,\n\t\t\t\t\t\t'created',\n\t\t\t\t\t\t'retrying',\n\t\t\t\t\t),\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tvisible_at: new Date(),\n\t\t\t})\n\t\t\t.where(it => it.in('id', events))\n\t\t\t.execute(db)\n\t}\n\n\tpublic async markStopped(db: Client, events: string[]): Promise<void> {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'stopped',\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tresolved_at: new Date(),\n\t\t\t})\n\t\t\t.where(it => it.in('id', events))\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markSucceed(db: Client, rows: EventRow[]): Promise<void> {\n\t\tconst now = new Date()\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'succeed',\n\t\t\t\tnum_retries: it => it.raw('num_retries + 1'),\n\t\t\t\tresolved_at: now,\n\t\t\t\tlast_state_change: now,\n\t\t\t})\n\t\t\t.where(it => it.in('id', rows.map(it => it.id)))\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markFailed(db: Client, event: HandledEvent): Promise<void> {\n\t\tconst numRetries = event.row.num_retries + 1\n\t\tconst now = new Date()\n\t\tconst nextAttempt = new Date()\n\t\tnextAttempt.setTime(\n\t\t\tnextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries),\n\t\t)\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tlast_state_change: now,\n\t\t\t\tnum_retries: numRetries,\n\t\t\t\tlog: JSON.stringify([...event.row.log, event.result]) as any,\n\t\t\t\t...(numRetries < (event.target?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS)\n\t\t\t\t\t? {\n\t\t\t\t\t\tstate: 'retrying',\n\t\t\t\t\t\tvisible_at: nextAttempt,\n\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\tstate: 'failed',\n\t\t\t\t\t}),\n\t\t\t})\n\t\t\t.where({ id: event.row.id })\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markFailedOnUnknownTarget(db: Client, targetName: string, primaryEventId: string) {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.where(it =>\n\t\t\t\tit.or(it =>\n\t\t\t\t\tit\n\t\t\t\t\t\t.and(it =>\n\t\t\t\t\t\t\tit\n\t\t\t\t\t\t\t\t.in('state', ['retrying', 'created', 'processing'])\n\t\t\t\t\t\t\t\t.compare('visible_at', Operator.lte, 'now')\n\t\t\t\t\t\t\t\t.compare('target', Operator.eq, targetName)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.and(it =>\n\t\t\t\t\t\t\tit\n\t\t\t\t\t\t\t\t.compare('id', Operator.eq, primaryEventId)\n\t\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)\n\t\t\t.values<EventRow>({\n\t\t\t\t// intentionally not retrying\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tnum_retries: it => it.raw('num_retries + 1'),\n\t\t\t\tlog: it => it.raw('log || ?::jsonb', { ok: false, errorMessage: `Event target ${targetName} not found, stopping.` }),\n\t\t\t\tstate: 'failed',\n\t\t\t\tresolved_at: new Date(),\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nexport type FetchBatchResult =\n\t| { ok: true; events: EventRow[]; target: Actions.AnyTarget }\n\t| { ok: false; backoffMs?: number }\n"],"names":["SelectBuilder","eventsToProcessStateSpecification","UpdateBuilder","eventsToProcessSpecification","LockType","LockModifier","it","Literal","Connection","Operator"],"mappings":"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"}
@@ -26,10 +26,7 @@ class EventsRepository {
26
26
  async fetchInternal(db, limit, targetName) {
27
27
  const visibleAt = /* @__PURE__ */ new Date();
28
28
  visibleAt.setTime(visibleAt.getTime() + ACK_TIMEOUT_MS);
29
- return await UpdateBuilder$1.create().table("actions_event").with(
30
- "events",
31
- (qb) => qb.select((it) => it.raw("*")).from("actions_event").match(eventsToProcessSpecification).where(targetName ? { target: targetName } : {}).limit(limit).lock(LockType.forNoKeyUpdate, LockModifier.skipLocked)
32
- ).values({
29
+ return await UpdateBuilder$1.create().table("actions_event").with("events", (qb) => qb.select((it) => it.raw("*")).from("actions_event").match(eventsToProcessSpecification).where(targetName ? { target: targetName } : {}).limit(limit).lock(LockType.forNoKeyUpdate, LockModifier.skipLocked)).values({
33
30
  state: "processing",
34
31
  last_state_change: /* @__PURE__ */ new Date(),
35
32
  visible_at: visibleAt
@@ -50,10 +47,27 @@ class EventsRepository {
50
47
  }
51
48
  async requeue(db, events) {
52
49
  await UpdateBuilder$1.create().table("actions_event").values({
53
- state: (it) => it.raw("CASE WHEN num_retries = 0 THEN ? ELSE ? END", "created", "retrying"),
50
+ state: (it) => it.raw(
51
+ `
52
+ CASE
53
+ WHEN num_retries = 0 THEN
54
+ ?::__SCHEMA__.actions_trigger_state
55
+ ELSE
56
+ ?::__SCHEMA__.actions_trigger_state END
57
+ `,
58
+ "created",
59
+ "retrying"
60
+ ),
54
61
  last_state_change: /* @__PURE__ */ new Date(),
55
62
  visible_at: /* @__PURE__ */ new Date()
56
- }).where((it) => it.in("id", events.map((it2) => it2.id))).execute(db);
63
+ }).where((it) => it.in("id", events)).execute(db);
64
+ }
65
+ async markStopped(db, events) {
66
+ await UpdateBuilder$1.create().table("actions_event").values({
67
+ state: "stopped",
68
+ last_state_change: /* @__PURE__ */ new Date(),
69
+ resolved_at: /* @__PURE__ */ new Date()
70
+ }).where((it) => it.in("id", events)).execute(db);
57
71
  }
58
72
  async markSucceed(db, rows) {
59
73
  const now = /* @__PURE__ */ new Date();
@@ -65,13 +79,15 @@ class EventsRepository {
65
79
  }).where((it) => it.in("id", rows.map((it2) => it2.id))).execute(db);
66
80
  }
67
81
  async markFailed(db, event) {
68
- const numRetries = event.row.num_retries;
82
+ const numRetries = event.row.num_retries + 1;
69
83
  const now = /* @__PURE__ */ new Date();
70
84
  const nextAttempt = /* @__PURE__ */ new Date();
71
- nextAttempt.setTime(nextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries));
85
+ nextAttempt.setTime(
86
+ nextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries)
87
+ );
72
88
  await UpdateBuilder$1.create().table("actions_event").values({
73
89
  last_state_change: now,
74
- num_retries: event.row.num_retries + 1,
90
+ num_retries: numRetries,
75
91
  log: JSON.stringify([...event.row.log, event.result]),
76
92
  ...numRetries < (event.target?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS) ? {
77
93
  state: "retrying",
@@ -82,13 +98,15 @@ class EventsRepository {
82
98
  }).where({ id: event.row.id }).execute(db);
83
99
  }
84
100
  async markFailedOnUnknownTarget(db, targetName, primaryEventId) {
85
- await UpdateBuilder$1.create().table("actions_event").where((it) => it.or(
86
- (it2) => it2.and(
87
- (it3) => it3.in("state", ["retrying", "created", "processing"]).compare("visible_at", Operator.lte, "now").compare("target", Operator.eq, targetName)
88
- ).and(
89
- (it3) => it3.compare("id", Operator.eq, primaryEventId)
101
+ await UpdateBuilder$1.create().table("actions_event").where(
102
+ (it) => it.or(
103
+ (it2) => it2.and(
104
+ (it3) => it3.in("state", ["retrying", "created", "processing"]).compare("visible_at", Operator.lte, "now").compare("target", Operator.eq, targetName)
105
+ ).and(
106
+ (it3) => it3.compare("id", Operator.eq, primaryEventId)
107
+ )
90
108
  )
91
- )).values({
109
+ ).values({
92
110
  // intentionally not retrying
93
111
  last_state_change: /* @__PURE__ */ new Date(),
94
112
  num_retries: (it) => it.raw("num_retries + 1"),
@@ -1 +1 @@
1
- {"version":3,"file":"EventsRepository.js","sources":["../../../../../packages/engine-actions/src/dispatch/EventsRepository.ts"],"sourcesContent":["import {\n\tClient,\n\tConnection,\n\tLiteral,\n\tLockModifier,\n\tLockType,\n\tOperator,\n\tSelectBuilder,\n\tUpdateBuilder,\n} from '@contember/database'\nimport { EventRow, HandledEvent } from './types'\nimport { Actions } from '@contember/schema'\nimport { eventsToProcessSpecification, eventsToProcessStateSpecification } from '../model/EventsToProcessSpecification'\n\n\nconst ACK_TIMEOUT_MS = 1_000 * 60 * 10 // 10 minutes\nconst DEFAULT_REPEAT_INTERVAL_MS = 5_000 // 5 seconds\nconst DEFAULT_MAX_ATTEMPTS = 10\nconst DEFAULT_BATCH_SIZE = 1\n\nexport class EventsRepository {\n\n\tpublic async fetchBatch(actions: Actions.Schema, db: Client): Promise<FetchBatchResult> {\n\t\tconst primaryEvent = (await this.fetchInternal(db, 1))[0]\n\t\tif (!primaryEvent) {\n\t\t\treturn { ok: false, backoffMs: await this.fetchBackOff(db) }\n\t\t}\n\t\tconst target = actions.targets[primaryEvent.target]\n\t\tif (!target) {\n\t\t\tawait this.markFailedOnUnknownTarget(db, primaryEvent.target, primaryEvent.id)\n\t\t\treturn await this.fetchBatch(actions, db)\n\t\t}\n\t\tconst batchSize = (target.batchSize ?? DEFAULT_BATCH_SIZE) - 1\n\t\tconst batch = batchSize > 0 ? await this.fetchInternal(db, batchSize) : []\n\t\treturn { ok: true, events: [primaryEvent, ...batch], target }\n\t}\n\n\n\tprivate async fetchBackOff(db: Client): Promise<number | undefined> {\n\t\tconst result = await SelectBuilder.create<{ ms: number }>()\n\t\t\t.from('actions_event')\n\t\t\t.match(eventsToProcessStateSpecification)\n\t\t\t.select(it => it.raw('ceil(extract(epoch from visible_at - now()) * 1000)'), 'ms')\n\t\t\t.orderBy('visible_at', 'asc')\n\t\t\t.limit(1)\n\t\t\t.getResult(db)\n\n\t\treturn result.length ? Math.max(0, result[0].ms) : undefined\n\t}\n\n\n\tprivate async fetchInternal(db: Client, limit: number, targetName?: string): Promise<EventRow[]> {\n\t\tconst visibleAt = new Date()\n\t\tvisibleAt.setTime(visibleAt.getTime() + ACK_TIMEOUT_MS)\n\t\treturn await UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.with('events', qb => qb\n\t\t\t\t.select(it => it.raw('*'))\n\t\t\t\t.from('actions_event')\n\t\t\t\t.match(eventsToProcessSpecification)\n\t\t\t\t.where(targetName ? { target: targetName } : {})\n\t\t\t\t.limit(limit)\n\t\t\t\t.lock(LockType.forNoKeyUpdate, LockModifier.skipLocked),\n\t\t\t)\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'processing',\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tvisible_at: visibleAt,\n\t\t\t})\n\t\t\t.from(it => it.from('events').where(it => it.columnsEq(['events', 'id'], ['actions_event', 'id'])))\n\t\t\t.returning<EventRow>(new Literal('*'))\n\t\t\t.execute(db)\n\t}\n\n\tpublic async persistProcessed(db: Client, events: HandledEvent[]): Promise<[number, number]> {\n\t\treturn await db.transaction(async trx => {\n\t\t\tawait trx.query(Connection.REPEATABLE_READ)\n\t\t\tconst succeed = events.filter(it => it.result.ok)\n\t\t\tawait this.markSucceed(trx, succeed.map(it => it.row))\n\n\t\t\tfor (const event of events) {\n\t\t\t\tif (!event.result.ok) {\n\t\t\t\t\tawait this.markFailed(trx, event)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn [succeed.length, events.length - succeed.length]\n\t\t})\n\t}\n\n\tpublic async requeue(db: Client, events: EventRow[]): Promise<void> {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: it => it.raw('CASE WHEN num_retries = 0 THEN ? ELSE ? END', 'created', 'retrying'),\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tvisible_at: new Date(),\n\t\t\t})\n\t\t\t.where(it => it.in('id', events.map(it => it.id)))\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markSucceed(db: Client, rows: EventRow[]): Promise<void> {\n\t\tconst now = new Date()\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'succeed',\n\t\t\t\tnum_retries: it => it.raw('num_retries + 1'),\n\t\t\t\tresolved_at: now,\n\t\t\t\tlast_state_change: now,\n\t\t\t})\n\t\t\t.where(it => it.in('id', rows.map(it => it.id)))\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markFailed(db: Client, event: HandledEvent): Promise<void> {\n\t\tconst numRetries = event.row.num_retries\n\t\tconst now = new Date()\n\t\tconst nextAttempt = new Date()\n\t\tnextAttempt.setTime(nextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries))\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tlast_state_change: now,\n\t\t\t\tnum_retries: event.row.num_retries + 1,\n\t\t\t\tlog: JSON.stringify([...event.row.log, event.result]) as any,\n\t\t\t\t...(numRetries < (event.target?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS) ? {\n\t\t\t\t\tstate: 'retrying',\n\t\t\t\t\tvisible_at: nextAttempt,\n\t\t\t\t} : {\n\t\t\t\t\tstate: 'failed',\n\t\t\t\t}),\n\t\t\t})\n\t\t\t.where({ id: event.row.id })\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markFailedOnUnknownTarget(db: Client, targetName: string, primaryEventId: string) {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.where(it => it.or(it => it\n\t\t\t\t.and(it => it\n\t\t\t\t\t.in('state', ['retrying', 'created', 'processing'])\n\t\t\t\t\t.compare('visible_at', Operator.lte, 'now')\n\t\t\t\t\t.compare('target', Operator.eq, targetName),\n\t\t\t\t)\n\t\t\t\t.and(it => it\n\t\t\t\t\t.compare('id', Operator.eq, primaryEventId),\n\t\t\t\t),\n\t\t\t))\n\t\t\t.values<EventRow>({\n\t\t\t\t// intentionally not retrying\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tnum_retries: it => it.raw('num_retries + 1'),\n\t\t\t\tlog: it => it.raw('log || ?::jsonb', { ok: false, errorMessage: `Event target ${targetName} not found, stopping.` }),\n\t\t\t\tstate: 'failed',\n\t\t\t\tresolved_at: new Date(),\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nexport type FetchBatchResult =\n\t| { ok: true; events: EventRow[]; target: Actions.AnyTarget }\n\t| { ok: false; backoffMs?: number }\n"],"names":["UpdateBuilder","it"],"mappings":"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"}
1
+ {"version":3,"file":"EventsRepository.js","sources":["../../../../../packages/engine-actions/src/dispatch/EventsRepository.ts"],"sourcesContent":["import { Client, Connection, Literal, LockModifier, LockType, Operator, SelectBuilder, UpdateBuilder } from '@contember/database'\nimport { EventRow, HandledEvent } from './types'\nimport { Actions } from '@contember/schema'\nimport { eventsToProcessSpecification, eventsToProcessStateSpecification } from '../model/EventsToProcessSpecification'\nimport { notify } from '../utils/notifyChannel'\n\nconst ACK_TIMEOUT_MS = 1_000 * 60 * 10 // 10 minutes\nconst DEFAULT_REPEAT_INTERVAL_MS = 5_000 // 5 seconds\nconst DEFAULT_MAX_ATTEMPTS = 10\nconst DEFAULT_BATCH_SIZE = 1\n\nexport class EventsRepository {\n\tpublic async fetchBatch(actions: Actions.Schema, db: Client): Promise<FetchBatchResult> {\n\t\tconst primaryEvent = (await this.fetchInternal(db, 1))[0]\n\t\tif (!primaryEvent) {\n\t\t\treturn { ok: false, backoffMs: await this.fetchBackOff(db) }\n\t\t}\n\t\tconst target = actions.targets[primaryEvent.target]\n\t\tif (!target) {\n\t\t\tawait this.markFailedOnUnknownTarget(db, primaryEvent.target, primaryEvent.id)\n\t\t\treturn await this.fetchBatch(actions, db)\n\t\t}\n\t\tconst batchSize = (target.batchSize ?? DEFAULT_BATCH_SIZE) - 1\n\t\tconst batch = batchSize > 0 ? await this.fetchInternal(db, batchSize) : []\n\t\treturn { ok: true, events: [primaryEvent, ...batch], target }\n\t}\n\n\tprivate async fetchBackOff(db: Client): Promise<number | undefined> {\n\t\tconst result = await SelectBuilder.create<{ ms: number }>()\n\t\t\t.from('actions_event')\n\t\t\t.match(eventsToProcessStateSpecification)\n\t\t\t.select(it => it.raw('ceil(extract(epoch from visible_at - now()) * 1000)'), 'ms')\n\t\t\t.orderBy('visible_at', 'asc')\n\t\t\t.limit(1)\n\t\t\t.getResult(db)\n\n\t\treturn result.length ? Math.max(0, result[0].ms) : undefined\n\t}\n\n\tprivate async fetchInternal(db: Client, limit: number, targetName?: string): Promise<EventRow[]> {\n\t\tconst visibleAt = new Date()\n\t\tvisibleAt.setTime(visibleAt.getTime() + ACK_TIMEOUT_MS)\n\t\treturn await UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.with('events', qb =>\n\t\t\t\tqb\n\t\t\t\t\t.select(it => it.raw('*'))\n\t\t\t\t\t.from('actions_event')\n\t\t\t\t\t.match(eventsToProcessSpecification)\n\t\t\t\t\t.where(targetName ? { target: targetName } : {})\n\t\t\t\t\t.limit(limit)\n\t\t\t\t\t.lock(LockType.forNoKeyUpdate, LockModifier.skipLocked))\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'processing',\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tvisible_at: visibleAt,\n\t\t\t})\n\t\t\t.from(it => it.from('events').where(it => it.columnsEq(['events', 'id'], ['actions_event', 'id'])))\n\t\t\t.returning<EventRow>(new Literal('*'))\n\t\t\t.execute(db)\n\t}\n\n\tpublic async persistProcessed(db: Client, events: HandledEvent[]): Promise<[number, number]> {\n\t\treturn await db.transaction(async trx => {\n\t\t\tawait trx.query(Connection.REPEATABLE_READ)\n\t\t\tconst succeed = events.filter(it => it.result.ok)\n\t\t\tawait this.markSucceed(trx, succeed.map(it => it.row))\n\n\t\t\tfor (const event of events) {\n\t\t\t\tif (!event.result.ok) {\n\t\t\t\t\tawait this.markFailed(trx, event)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn [succeed.length, events.length - succeed.length]\n\t\t})\n\t}\n\n\tpublic async requeue(db: Client, events: string[]): Promise<void> {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: it =>\n\t\t\t\t\tit.raw(\n\t\t\t\t\t\t`\n\t\t\t\t\tCASE \n\t\t\t\t\tWHEN num_retries = 0 THEN \n\t\t\t\t\t\t?::__SCHEMA__.actions_trigger_state \n\t\t\t\t\tELSE \n\t\t\t\t\t?::__SCHEMA__.actions_trigger_state END\n\t\t\t\t`,\n\t\t\t\t\t\t'created',\n\t\t\t\t\t\t'retrying',\n\t\t\t\t\t),\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tvisible_at: new Date(),\n\t\t\t})\n\t\t\t.where(it => it.in('id', events))\n\t\t\t.execute(db)\n\t}\n\n\tpublic async markStopped(db: Client, events: string[]): Promise<void> {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'stopped',\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tresolved_at: new Date(),\n\t\t\t})\n\t\t\t.where(it => it.in('id', events))\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markSucceed(db: Client, rows: EventRow[]): Promise<void> {\n\t\tconst now = new Date()\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tstate: 'succeed',\n\t\t\t\tnum_retries: it => it.raw('num_retries + 1'),\n\t\t\t\tresolved_at: now,\n\t\t\t\tlast_state_change: now,\n\t\t\t})\n\t\t\t.where(it => it.in('id', rows.map(it => it.id)))\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markFailed(db: Client, event: HandledEvent): Promise<void> {\n\t\tconst numRetries = event.row.num_retries + 1\n\t\tconst now = new Date()\n\t\tconst nextAttempt = new Date()\n\t\tnextAttempt.setTime(\n\t\t\tnextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries),\n\t\t)\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.values<EventRow>({\n\t\t\t\tlast_state_change: now,\n\t\t\t\tnum_retries: numRetries,\n\t\t\t\tlog: JSON.stringify([...event.row.log, event.result]) as any,\n\t\t\t\t...(numRetries < (event.target?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS)\n\t\t\t\t\t? {\n\t\t\t\t\t\tstate: 'retrying',\n\t\t\t\t\t\tvisible_at: nextAttempt,\n\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\tstate: 'failed',\n\t\t\t\t\t}),\n\t\t\t})\n\t\t\t.where({ id: event.row.id })\n\t\t\t.execute(db)\n\t}\n\n\tprivate async markFailedOnUnknownTarget(db: Client, targetName: string, primaryEventId: string) {\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('actions_event')\n\t\t\t.where(it =>\n\t\t\t\tit.or(it =>\n\t\t\t\t\tit\n\t\t\t\t\t\t.and(it =>\n\t\t\t\t\t\t\tit\n\t\t\t\t\t\t\t\t.in('state', ['retrying', 'created', 'processing'])\n\t\t\t\t\t\t\t\t.compare('visible_at', Operator.lte, 'now')\n\t\t\t\t\t\t\t\t.compare('target', Operator.eq, targetName)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.and(it =>\n\t\t\t\t\t\t\tit\n\t\t\t\t\t\t\t\t.compare('id', Operator.eq, primaryEventId)\n\t\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)\n\t\t\t.values<EventRow>({\n\t\t\t\t// intentionally not retrying\n\t\t\t\tlast_state_change: new Date(),\n\t\t\t\tnum_retries: it => it.raw('num_retries + 1'),\n\t\t\t\tlog: it => it.raw('log || ?::jsonb', { ok: false, errorMessage: `Event target ${targetName} not found, stopping.` }),\n\t\t\t\tstate: 'failed',\n\t\t\t\tresolved_at: new Date(),\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nexport type FetchBatchResult =\n\t| { ok: true; events: EventRow[]; target: Actions.AnyTarget }\n\t| { ok: false; backoffMs?: number }\n"],"names":["UpdateBuilder","it"],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const engineCommon = require("@contember/engine-common");
4
+ class LazyDispatchWorker {
5
+ constructor(projectGroupContainerResolver, supervisorFactory, supervisorOptions = { startupMax: 10 }) {
6
+ this.projectGroupContainerResolver = projectGroupContainerResolver;
7
+ this.supervisorFactory = supervisorFactory;
8
+ this.supervisorOptions = supervisorOptions;
9
+ }
10
+ async run({ logger, onError }) {
11
+ const running = /* @__PURE__ */ new Map();
12
+ let aborted = false;
13
+ const unlisten = this.projectGroupContainerResolver.on("create", ({ container, slug }) => {
14
+ const groupLabel = slug ?? "<default>";
15
+ const childLogger = logger.child({ projectGroup: groupLabel });
16
+ childLogger.debug(`Starting dispatch worker for project group ${groupLabel}`);
17
+ const supervised = new engineCommon.Supervisor(
18
+ this.supervisorFactory.create(container),
19
+ this.supervisorOptions
20
+ );
21
+ const runningPromise = supervised.run({
22
+ logger: childLogger,
23
+ onError: (e) => {
24
+ if (aborted) {
25
+ return;
26
+ }
27
+ childLogger.error(e, { message: `Dispatch worker for project group ${groupLabel} crashed` });
28
+ onError(e);
29
+ }
30
+ }).catch((e) => {
31
+ if (!aborted) {
32
+ childLogger.error(e, { message: `Failed to start dispatch worker for project group ${groupLabel}` });
33
+ onError(e);
34
+ }
35
+ return void 0;
36
+ });
37
+ running.set(slug, runningPromise);
38
+ return () => {
39
+ running.delete(slug);
40
+ (async () => {
41
+ try {
42
+ const r = await runningPromise;
43
+ await r?.end();
44
+ } catch {
45
+ }
46
+ })();
47
+ };
48
+ });
49
+ return {
50
+ end: async () => {
51
+ aborted = true;
52
+ unlisten();
53
+ const all = [...running.values()];
54
+ running.clear();
55
+ await Promise.allSettled(all.map(async (p) => {
56
+ try {
57
+ const r = await p;
58
+ await r?.end();
59
+ } catch {
60
+ }
61
+ }));
62
+ }
63
+ };
64
+ }
65
+ }
66
+ exports.LazyDispatchWorker = LazyDispatchWorker;
67
+ //# sourceMappingURL=LazyDispatchWorker.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LazyDispatchWorker.cjs","sources":["../../../../../packages/engine-actions/src/dispatch/LazyDispatchWorker.ts"],"sourcesContent":["import { Runnable, RunnableArgs, Running, Supervisor, SupervisorOptions } from '@contember/engine-common'\nimport { ProjectGroupContainerResolver } from '@contember/engine-http'\nimport { DispatchWorkerSupervisorFactory } from './DispatchWorkerSupervisor'\n\nexport class LazyDispatchWorker implements Runnable {\n\tconstructor(\n\t\tprivate readonly projectGroupContainerResolver: ProjectGroupContainerResolver,\n\t\tprivate readonly supervisorFactory: DispatchWorkerSupervisorFactory,\n\t\tprivate readonly supervisorOptions: SupervisorOptions = { startupMax: 10 },\n\t) {\n\t}\n\n\tpublic async run({ logger, onError }: RunnableArgs): Promise<Running> {\n\t\tconst running = new Map<string | undefined, Promise<Running | undefined>>()\n\t\tlet aborted = false\n\n\t\tconst unlisten = this.projectGroupContainerResolver.on('create', ({ container, slug }) => {\n\t\t\tconst groupLabel = slug ?? '<default>'\n\t\t\tconst childLogger = logger.child({ projectGroup: groupLabel })\n\t\t\tchildLogger.debug(`Starting dispatch worker for project group ${groupLabel}`)\n\n\t\t\tconst supervised = new Supervisor(\n\t\t\t\tthis.supervisorFactory.create(container),\n\t\t\t\tthis.supervisorOptions,\n\t\t\t)\n\t\t\tconst runningPromise: Promise<Running | undefined> = supervised.run({\n\t\t\t\tlogger: childLogger,\n\t\t\t\tonError: e => {\n\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tchildLogger.error(e, { message: `Dispatch worker for project group ${groupLabel} crashed` })\n\t\t\t\t\tonError(e)\n\t\t\t\t},\n\t\t\t}).catch(e => {\n\t\t\t\tif (!aborted) {\n\t\t\t\t\tchildLogger.error(e, { message: `Failed to start dispatch worker for project group ${groupLabel}` })\n\t\t\t\t\tonError(e)\n\t\t\t\t}\n\t\t\t\treturn undefined\n\t\t\t})\n\t\t\trunning.set(slug, runningPromise)\n\n\t\t\treturn () => {\n\t\t\t\trunning.delete(slug)\n\t\t\t\t;(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst r = await runningPromise\n\t\t\t\t\t\tawait r?.end()\n\t\t\t\t\t} catch {\n\t\t\t\t\t}\n\t\t\t\t})()\n\t\t\t}\n\t\t})\n\n\t\treturn {\n\t\t\tend: async () => {\n\t\t\t\taborted = true\n\t\t\t\tunlisten()\n\t\t\t\tconst all = [...running.values()]\n\t\t\t\trunning.clear()\n\t\t\t\tawait Promise.allSettled(all.map(async p => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst r = await p\n\t\t\t\t\t\tawait r?.end()\n\t\t\t\t\t} catch {\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t},\n\t\t}\n\t}\n}\n"],"names":["Supervisor"],"mappings":";;;AAIO,MAAM,mBAAuC;AAAA,EACnD,YACkB,+BACA,mBACA,oBAAuC,EAAE,YAAY,MACrE;AAHgB,SAAA,gCAAA;AACA,SAAA,oBAAA;AACA,SAAA,oBAAA;AAAA,EAElB;AAAA,EAEA,MAAa,IAAI,EAAE,QAAQ,WAA2C;AACrE,UAAM,8BAAc,IAAA;AACpB,QAAI,UAAU;AAEd,UAAM,WAAW,KAAK,8BAA8B,GAAG,UAAU,CAAC,EAAE,WAAW,WAAW;AACzF,YAAM,aAAa,QAAQ;AAC3B,YAAM,cAAc,OAAO,MAAM,EAAE,cAAc,YAAY;AAC7D,kBAAY,MAAM,8CAA8C,UAAU,EAAE;AAE5E,YAAM,aAAa,IAAIA,aAAAA;AAAAA,QACtB,KAAK,kBAAkB,OAAO,SAAS;AAAA,QACvC,KAAK;AAAA,MAAA;AAEN,YAAM,iBAA+C,WAAW,IAAI;AAAA,QACnE,QAAQ;AAAA,QACR,SAAS,CAAA,MAAK;AACb,cAAI,SAAS;AACZ;AAAA,UACD;AACA,sBAAY,MAAM,GAAG,EAAE,SAAS,qCAAqC,UAAU,YAAY;AAC3F,kBAAQ,CAAC;AAAA,QACV;AAAA,MAAA,CACA,EAAE,MAAM,CAAA,MAAK;AACb,YAAI,CAAC,SAAS;AACb,sBAAY,MAAM,GAAG,EAAE,SAAS,qDAAqD,UAAU,IAAI;AACnG,kBAAQ,CAAC;AAAA,QACV;AACA,eAAO;AAAA,MACR,CAAC;AACD,cAAQ,IAAI,MAAM,cAAc;AAEhC,aAAO,MAAM;AACZ,gBAAQ,OAAO,IAAI;AAClB,SAAC,YAAY;AACb,cAAI;AACH,kBAAM,IAAI,MAAM;AAChB,kBAAM,GAAG,IAAA;AAAA,UACV,QAAQ;AAAA,UACR;AAAA,QACD,GAAA;AAAA,MACD;AAAA,IACD,CAAC;AAED,WAAO;AAAA,MACN,KAAK,YAAY;AAChB,kBAAU;AACV,iBAAA;AACA,cAAM,MAAM,CAAC,GAAG,QAAQ,QAAQ;AAChC,gBAAQ,MAAA;AACR,cAAM,QAAQ,WAAW,IAAI,IAAI,OAAM,MAAK;AAC3C,cAAI;AACH,kBAAM,IAAI,MAAM;AAChB,kBAAM,GAAG,IAAA;AAAA,UACV,QAAQ;AAAA,UACR;AAAA,QACD,CAAC,CAAC;AAAA,MACH;AAAA,IAAA;AAAA,EAEF;AACD;;"}