alepha 0.20.5 → 0.20.7

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 (367) hide show
  1. package/AGENTS.md +0 -1
  2. package/CLAUDE.md +0 -1
  3. package/assets/agents-template.md +0 -1
  4. package/dist/api/audits/index.browser.js +1 -0
  5. package/dist/api/audits/index.browser.js.map +1 -1
  6. package/dist/api/audits/index.d.ts +701 -654
  7. package/dist/api/audits/index.d.ts.map +1 -1
  8. package/dist/api/audits/index.js +24 -1
  9. package/dist/api/audits/index.js.map +1 -1
  10. package/dist/api/files/index.browser.js +1 -0
  11. package/dist/api/files/index.browser.js.map +1 -1
  12. package/dist/api/files/index.d.ts +193 -166
  13. package/dist/api/files/index.d.ts.map +1 -1
  14. package/dist/api/files/index.js +52 -0
  15. package/dist/api/files/index.js.map +1 -1
  16. package/dist/api/jobs/index.browser.js +40 -14
  17. package/dist/api/jobs/index.browser.js.map +1 -1
  18. package/dist/api/jobs/index.d.ts +639 -333
  19. package/dist/api/jobs/index.d.ts.map +1 -1
  20. package/dist/api/jobs/index.js +495 -162
  21. package/dist/api/jobs/index.js.map +1 -1
  22. package/dist/api/keys/index.d.ts +222 -188
  23. package/dist/api/keys/index.d.ts.map +1 -1
  24. package/dist/api/keys/index.js +54 -0
  25. package/dist/api/keys/index.js.map +1 -1
  26. package/dist/api/notifications/index.d.ts +265 -236
  27. package/dist/api/notifications/index.d.ts.map +1 -1
  28. package/dist/api/notifications/index.js +55 -13
  29. package/dist/api/notifications/index.js.map +1 -1
  30. package/dist/api/organizations/index.d.ts +100 -97
  31. package/dist/api/organizations/index.d.ts.map +1 -1
  32. package/dist/api/organizations/index.js.map +1 -1
  33. package/dist/api/parameters/index.d.ts +332 -314
  34. package/dist/api/parameters/index.d.ts.map +1 -1
  35. package/dist/api/parameters/index.js +37 -0
  36. package/dist/api/parameters/index.js.map +1 -1
  37. package/dist/api/payments/index.d.ts +431 -376
  38. package/dist/api/payments/index.d.ts.map +1 -1
  39. package/dist/api/payments/index.js +202 -87
  40. package/dist/api/payments/index.js.map +1 -1
  41. package/dist/api/subscriptions/index.d.ts +1695 -0
  42. package/dist/api/subscriptions/index.d.ts.map +1 -0
  43. package/dist/api/subscriptions/index.js +1919 -0
  44. package/dist/api/subscriptions/index.js.map +1 -0
  45. package/dist/api/users/index.d.ts +1001 -844
  46. package/dist/api/users/index.d.ts.map +1 -1
  47. package/dist/api/users/index.js +237 -28
  48. package/dist/api/users/index.js.map +1 -1
  49. package/dist/api/verifications/index.d.ts +123 -122
  50. package/dist/api/verifications/index.d.ts.map +1 -1
  51. package/dist/api/verifications/index.js.map +1 -1
  52. package/dist/batch/index.js.map +1 -1
  53. package/dist/bucket/index.d.ts +21 -2
  54. package/dist/bucket/index.d.ts.map +1 -1
  55. package/dist/bucket/index.js +47 -0
  56. package/dist/bucket/index.js.map +1 -1
  57. package/dist/bucket/index.workerd.js +24 -0
  58. package/dist/bucket/index.workerd.js.map +1 -1
  59. package/dist/cache/core/index.d.ts +134 -7
  60. package/dist/cache/core/index.d.ts.map +1 -1
  61. package/dist/cache/core/index.js +181 -15
  62. package/dist/cache/core/index.js.map +1 -1
  63. package/dist/cache/core/index.workerd.js +181 -15
  64. package/dist/cache/core/index.workerd.js.map +1 -1
  65. package/dist/cache/database/index.d.ts +156 -0
  66. package/dist/cache/database/index.d.ts.map +1 -0
  67. package/dist/cache/database/index.js +266 -0
  68. package/dist/cache/database/index.js.map +1 -0
  69. package/dist/cache/redis/index.d.ts +3 -2
  70. package/dist/cache/redis/index.d.ts.map +1 -1
  71. package/dist/cache/redis/index.js.map +1 -1
  72. package/dist/captcha/index.js.map +1 -1
  73. package/dist/cli/config/index.js.map +1 -1
  74. package/dist/cli/core/index.d.ts +142 -128
  75. package/dist/cli/core/index.d.ts.map +1 -1
  76. package/dist/cli/core/index.js +160 -13
  77. package/dist/cli/core/index.js.map +1 -1
  78. package/dist/cli/devtools/index.d.ts +3 -2
  79. package/dist/cli/devtools/index.d.ts.map +1 -1
  80. package/dist/cli/devtools/index.js.map +1 -1
  81. package/dist/cli/platform/index.d.ts +346 -290
  82. package/dist/cli/platform/index.d.ts.map +1 -1
  83. package/dist/cli/platform/index.js +106 -7
  84. package/dist/cli/platform/index.js.map +1 -1
  85. package/dist/cli/vendor/index.d.ts +12 -11
  86. package/dist/cli/vendor/index.d.ts.map +1 -1
  87. package/dist/cli/vendor/index.js.map +1 -1
  88. package/dist/command/index.d.ts +6 -5
  89. package/dist/command/index.d.ts.map +1 -1
  90. package/dist/command/index.js.map +1 -1
  91. package/dist/core/index.browser.js +1 -1
  92. package/dist/core/index.browser.js.map +1 -1
  93. package/dist/core/index.d.ts +119 -118
  94. package/dist/core/index.d.ts.map +1 -1
  95. package/dist/core/index.js +1 -1
  96. package/dist/core/index.js.map +1 -1
  97. package/dist/core/index.native.js +1 -1
  98. package/dist/core/index.native.js.map +1 -1
  99. package/dist/core/index.workerd.js +1 -1
  100. package/dist/core/index.workerd.js.map +1 -1
  101. package/dist/crypto/index.browser.js.map +1 -1
  102. package/dist/crypto/index.d.ts +3 -2
  103. package/dist/crypto/index.d.ts.map +1 -1
  104. package/dist/crypto/index.js.map +1 -1
  105. package/dist/datetime/index.js.map +1 -1
  106. package/dist/email/brevo/index.js.map +1 -1
  107. package/dist/email/core/index.d.ts +3 -2
  108. package/dist/email/core/index.d.ts.map +1 -1
  109. package/dist/email/core/index.js.map +1 -1
  110. package/dist/email/core/index.workerd.js.map +1 -1
  111. package/dist/email/smtp/index.d.ts +7 -6
  112. package/dist/email/smtp/index.d.ts.map +1 -1
  113. package/dist/email/smtp/index.js.map +1 -1
  114. package/dist/fake/index.js.map +1 -1
  115. package/dist/lock/core/index.d.ts +5 -4
  116. package/dist/lock/core/index.d.ts.map +1 -1
  117. package/dist/lock/core/index.js.map +1 -1
  118. package/dist/lock/redis/index.js.map +1 -1
  119. package/dist/logger/index.d.ts +10 -9
  120. package/dist/logger/index.d.ts.map +1 -1
  121. package/dist/logger/index.js.map +1 -1
  122. package/dist/mcp/index.d.ts +9 -8
  123. package/dist/mcp/index.d.ts.map +1 -1
  124. package/dist/mcp/index.js +1 -1
  125. package/dist/mcp/index.js.map +1 -1
  126. package/dist/orm/core/index.browser.js +9 -3
  127. package/dist/orm/core/index.browser.js.map +1 -1
  128. package/dist/orm/core/index.bun.js +31 -10
  129. package/dist/orm/core/index.bun.js.map +1 -1
  130. package/dist/orm/core/index.d.ts +33 -14
  131. package/dist/orm/core/index.d.ts.map +1 -1
  132. package/dist/orm/core/index.js +31 -10
  133. package/dist/orm/core/index.js.map +1 -1
  134. package/dist/orm/postgres/index.bun.js.map +1 -1
  135. package/dist/orm/postgres/index.d.ts +6 -5
  136. package/dist/orm/postgres/index.d.ts.map +1 -1
  137. package/dist/orm/postgres/index.js.map +1 -1
  138. package/dist/queue/core/index.d.ts +5 -4
  139. package/dist/queue/core/index.d.ts.map +1 -1
  140. package/dist/queue/core/index.js.map +1 -1
  141. package/dist/queue/core/index.workerd.js.map +1 -1
  142. package/dist/queue/redis/index.d.ts +3 -2
  143. package/dist/queue/redis/index.d.ts.map +1 -1
  144. package/dist/queue/redis/index.js.map +1 -1
  145. package/dist/react/auth/index.browser.js.map +1 -1
  146. package/dist/react/auth/index.js.map +1 -1
  147. package/dist/react/core/index.js.map +1 -1
  148. package/dist/react/form/index.d.ts +5 -0
  149. package/dist/react/form/index.d.ts.map +1 -1
  150. package/dist/react/form/index.js +8 -4
  151. package/dist/react/form/index.js.map +1 -1
  152. package/dist/react/head/index.browser.js.map +1 -1
  153. package/dist/react/head/index.js.map +1 -1
  154. package/dist/react/i18n/index.d.ts +2 -1
  155. package/dist/react/i18n/index.d.ts.map +1 -1
  156. package/dist/react/i18n/index.js.map +1 -1
  157. package/dist/react/intro/index.js.map +1 -1
  158. package/dist/react/router/index.browser.js.map +1 -1
  159. package/dist/react/router/index.d.ts +206 -205
  160. package/dist/react/router/index.d.ts.map +1 -1
  161. package/dist/react/router/index.js.map +1 -1
  162. package/dist/react/testing/index.js.map +1 -1
  163. package/dist/react/ui/index.d.ts +11 -11
  164. package/dist/react/ui/index.d.ts.map +1 -1
  165. package/dist/react/ui/index.js.map +1 -1
  166. package/dist/redis/index.bun.js.map +1 -1
  167. package/dist/redis/index.js.map +1 -1
  168. package/dist/retry/index.js.map +1 -1
  169. package/dist/router/index.js.map +1 -1
  170. package/dist/scheduler/index.d.ts +25 -2
  171. package/dist/scheduler/index.d.ts.map +1 -1
  172. package/dist/scheduler/index.js +12 -0
  173. package/dist/scheduler/index.js.map +1 -1
  174. package/dist/scheduler/index.workerd.js +12 -0
  175. package/dist/scheduler/index.workerd.js.map +1 -1
  176. package/dist/security/index.browser.js +29 -1
  177. package/dist/security/index.browser.js.map +1 -1
  178. package/dist/security/index.d.ts +82 -35
  179. package/dist/security/index.d.ts.map +1 -1
  180. package/dist/security/index.js +56 -3
  181. package/dist/security/index.js.map +1 -1
  182. package/dist/server/auth/index.d.ts +163 -158
  183. package/dist/server/auth/index.d.ts.map +1 -1
  184. package/dist/server/auth/index.js +16 -4
  185. package/dist/server/auth/index.js.map +1 -1
  186. package/dist/server/cookies/index.browser.js.map +1 -1
  187. package/dist/server/cookies/index.js.map +1 -1
  188. package/dist/server/core/index.browser.js.map +1 -1
  189. package/dist/server/core/index.d.ts +35 -34
  190. package/dist/server/core/index.d.ts.map +1 -1
  191. package/dist/server/core/index.js.map +1 -1
  192. package/dist/server/cors/index.d.ts +7 -6
  193. package/dist/server/cors/index.d.ts.map +1 -1
  194. package/dist/server/cors/index.js.map +1 -1
  195. package/dist/server/etag/index.js.map +1 -1
  196. package/dist/server/health/index.d.ts +16 -15
  197. package/dist/server/health/index.d.ts.map +1 -1
  198. package/dist/server/health/index.js.map +1 -1
  199. package/dist/server/links/index.browser.js.map +1 -1
  200. package/dist/server/links/index.d.ts +51 -50
  201. package/dist/server/links/index.d.ts.map +1 -1
  202. package/dist/server/links/index.js.map +1 -1
  203. package/dist/server/metrics/index.js.map +1 -1
  204. package/dist/server/proxy/index.js.map +1 -1
  205. package/dist/server/rate-limit/index.d.ts +6 -5
  206. package/dist/server/rate-limit/index.d.ts.map +1 -1
  207. package/dist/server/rate-limit/index.js.map +1 -1
  208. package/dist/server/static/index.js.map +1 -1
  209. package/dist/server/swagger/index.d.ts +2 -1
  210. package/dist/server/swagger/index.d.ts.map +1 -1
  211. package/dist/server/swagger/index.js.map +1 -1
  212. package/dist/sms/index.js.map +1 -1
  213. package/dist/system/index.browser.js.map +1 -1
  214. package/dist/system/index.js.map +1 -1
  215. package/dist/system/index.workerd.js.map +1 -1
  216. package/dist/topic/core/index.js.map +1 -1
  217. package/dist/topic/redis/index.d.ts +3 -2
  218. package/dist/topic/redis/index.d.ts.map +1 -1
  219. package/dist/topic/redis/index.js.map +1 -1
  220. package/package.json +33 -39
  221. package/src/api/audits/controllers/AdminAuditController.ts +29 -0
  222. package/src/api/audits/entities/audits.ts +1 -0
  223. package/src/api/files/controllers/FileController.ts +24 -0
  224. package/src/api/files/entities/files.ts +1 -0
  225. package/src/api/files/services/FileService.ts +41 -0
  226. package/src/api/jobs/__tests__/$job.spec.ts +501 -24
  227. package/src/api/jobs/entities/jobExecutionEntity.ts +4 -3
  228. package/src/api/jobs/index.ts +47 -10
  229. package/src/api/jobs/primitives/$job.ts +22 -9
  230. package/src/api/jobs/providers/DirectJobDispatcher.ts +71 -0
  231. package/src/api/jobs/providers/JobDispatcher.ts +49 -0
  232. package/src/api/jobs/providers/JobProvider.ts +385 -147
  233. package/src/api/jobs/providers/JobQueueProvider.ts +43 -18
  234. package/src/api/jobs/schemas/jobConfigAtom.ts +9 -3
  235. package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +11 -0
  236. package/src/api/jobs/schemas/jobRegistrationSchema.ts +4 -2
  237. package/src/api/jobs/services/JobService.ts +21 -11
  238. package/src/api/keys/controllers/AdminApiKeyController.ts +23 -0
  239. package/src/api/keys/entities/apiKeyEntity.ts +1 -0
  240. package/src/api/keys/services/ApiKeyService.ts +42 -0
  241. package/src/api/notifications/__tests__/AlephaApiNotifications.spec.ts +63 -0
  242. package/src/api/notifications/controllers/AdminNotificationController.ts +48 -1
  243. package/src/api/notifications/index.ts +13 -3
  244. package/src/api/notifications/jobs/NotificationJobs.ts +0 -6
  245. package/src/api/parameters/controllers/AdminParameterController.ts +26 -0
  246. package/src/api/parameters/services/ParameterProvider.ts +18 -0
  247. package/src/api/payments/controllers/MockCheckoutController.ts +146 -0
  248. package/src/api/payments/index.ts +3 -0
  249. package/src/api/payments/providers/MemoryPaymentProvider.ts +9 -4
  250. package/src/api/payments/providers/PaymentProvider.ts +25 -9
  251. package/src/api/payments/services/PaymentService.ts +3 -0
  252. package/src/api/subscriptions/__tests__/BillingService.spec.ts +218 -0
  253. package/src/api/subscriptions/__tests__/SubscriptionService.spec.ts +278 -0
  254. package/src/api/subscriptions/controllers/AdminSubscriptionController.ts +212 -0
  255. package/src/api/subscriptions/controllers/SubscriptionController.ts +189 -0
  256. package/src/api/subscriptions/entities/subscriptionEvents.ts +54 -0
  257. package/src/api/subscriptions/entities/subscriptions.ts +68 -0
  258. package/src/api/subscriptions/index.ts +133 -0
  259. package/src/api/subscriptions/jobs/SubscriptionJobs.ts +382 -0
  260. package/src/api/subscriptions/middleware/$requireLimit.ts +50 -0
  261. package/src/api/subscriptions/middleware/$requirePlan.ts +49 -0
  262. package/src/api/subscriptions/notifications/SubscriptionNotifications.ts +110 -0
  263. package/src/api/subscriptions/schemas/cancelSubscriptionSchema.ts +8 -0
  264. package/src/api/subscriptions/schemas/changePlanSchema.ts +9 -0
  265. package/src/api/subscriptions/schemas/createSubscriptionSchema.ts +11 -0
  266. package/src/api/subscriptions/schemas/entitlementsSchema.ts +21 -0
  267. package/src/api/subscriptions/schemas/mrrSchema.ts +13 -0
  268. package/src/api/subscriptions/schemas/planDefinitionSchema.ts +71 -0
  269. package/src/api/subscriptions/schemas/planResourceSchema.ts +25 -0
  270. package/src/api/subscriptions/schemas/subscriptionEventResourceSchema.ts +8 -0
  271. package/src/api/subscriptions/schemas/subscriptionQuerySchema.ts +19 -0
  272. package/src/api/subscriptions/schemas/subscriptionResourceSchema.ts +6 -0
  273. package/src/api/subscriptions/schemas/subscriptionSettingsSchema.ts +32 -0
  274. package/src/api/subscriptions/schemas/subscriptionStatsSchema.ts +23 -0
  275. package/src/api/subscriptions/services/BillingService.ts +437 -0
  276. package/src/api/subscriptions/services/SubscriptionConfig.ts +56 -0
  277. package/src/api/subscriptions/services/SubscriptionService.ts +867 -0
  278. package/src/api/subscriptions/services/UsageService.ts +118 -0
  279. package/src/api/users/__tests__/Registration-emailMode.spec.ts +203 -0
  280. package/src/api/users/__tests__/UsernameSlugger.spec.ts +138 -0
  281. package/src/api/users/atoms/realmAuthSettingsAtom.ts +41 -3
  282. package/src/api/users/controllers/AdminSessionController.ts +29 -0
  283. package/src/api/users/controllers/AdminUserController.ts +32 -0
  284. package/src/api/users/index.ts +3 -0
  285. package/src/api/users/services/CredentialService.ts +5 -0
  286. package/src/api/users/services/RegistrationService.ts +49 -1
  287. package/src/api/users/services/SessionCrudService.ts +16 -0
  288. package/src/api/users/services/SessionService.ts +17 -59
  289. package/src/api/users/services/UsernameSlugger.ts +195 -0
  290. package/src/bucket/primitives/$bucket.ts +21 -0
  291. package/src/bucket/providers/CloudflareR2Provider.ts +15 -0
  292. package/src/bucket/providers/FileStorageProvider.ts +9 -0
  293. package/src/bucket/providers/LocalFileStorageProvider.ts +14 -0
  294. package/src/bucket/providers/MemoryFileStorageProvider.ts +9 -0
  295. package/src/bucket/providers/NodeS3BucketProvider.ts +35 -0
  296. package/src/cache/core/__tests__/$cache.memory.spec.ts +450 -0
  297. package/src/cache/core/__tests__/$cache.swr.spec.ts +394 -0
  298. package/src/cache/core/index.ts +16 -0
  299. package/src/cache/core/primitives/$cache.ts +367 -24
  300. package/src/cache/database/__tests__/DatabaseCacheProvider.behavior.spec.ts +203 -0
  301. package/src/cache/database/__tests__/DatabaseCacheProvider.spec.ts +110 -0
  302. package/src/cache/database/entities/cacheEntries.ts +55 -0
  303. package/src/cache/database/index.ts +36 -0
  304. package/src/cache/database/providers/DatabaseCacheProvider.ts +348 -0
  305. package/src/cli/core/services/ProjectScaffolder.ts +0 -2
  306. package/src/cli/core/tasks/BuildCloudflareTask.ts +33 -3
  307. package/src/cli/core/tasks/BuildSitemapTask.ts +7 -0
  308. package/src/cli/core/tasks/BuildVercelTask.ts +82 -3
  309. package/src/cli/core/templates/agentMd.ts +39 -4
  310. package/src/cli/core/templates/biomeJson.ts +25 -1
  311. package/src/cli/core/templates/saasAdminLayoutTsx.ts +2 -2
  312. package/src/cli/platform/__tests__/CloudflareAdapter.spec.ts +117 -0
  313. package/src/cli/platform/__tests__/detectResources.spec.ts +96 -0
  314. package/src/cli/platform/adapters/CloudflareAdapter.ts +104 -7
  315. package/src/cli/platform/atoms/platformOptions.ts +13 -0
  316. package/src/cli/platform/commands/platform.ts +7 -1
  317. package/src/cli/platform/schemas/platform.ts +1 -0
  318. package/src/cli/platform/services/CloudflareApi.ts +61 -0
  319. package/src/cli/platform/services/PlatformOrchestrator.ts +9 -4
  320. package/src/core/__tests__/$module.spec.ts +2 -2
  321. package/src/core/primitives/$module.ts +4 -4
  322. package/src/mcp/providers/McpServerProvider.ts +1 -1
  323. package/src/orm/core/providers/DatabaseTypeProvider.ts +9 -3
  324. package/src/orm/core/providers/drivers/DatabaseProvider.ts +1 -1
  325. package/src/orm/core/schemas/insertSchema.ts +10 -2
  326. package/src/orm/core/services/Repository.ts +27 -7
  327. package/src/react/form/hooks/useFormState.ts +8 -1
  328. package/src/react/form/index.ts +10 -1
  329. package/src/react/form/services/FormModel.ts +9 -3
  330. package/src/scheduler/index.ts +14 -0
  331. package/src/scheduler/providers/CronProvider.ts +13 -0
  332. package/src/security/atoms/currentTenantAtom.ts +34 -0
  333. package/src/security/index.browser.ts +1 -0
  334. package/src/security/index.ts +12 -1
  335. package/src/security/primitives/$issuer.ts +17 -1
  336. package/src/security/providers/SecurityProvider.ts +37 -0
  337. package/src/server/auth/__tests__/validateRedirectUri.spec.ts +78 -0
  338. package/src/server/auth/providers/ServerAuthProvider.ts +21 -5
  339. package/tsconfig.base.json +2 -1
  340. package/dist/react/websocket/index.d.ts +0 -117
  341. package/dist/react/websocket/index.d.ts.map +0 -1
  342. package/dist/react/websocket/index.js +0 -108
  343. package/dist/react/websocket/index.js.map +0 -1
  344. package/dist/websocket/index.browser.js +0 -844
  345. package/dist/websocket/index.browser.js.map +0 -1
  346. package/dist/websocket/index.d.ts +0 -876
  347. package/dist/websocket/index.d.ts.map +0 -1
  348. package/dist/websocket/index.js +0 -1175
  349. package/dist/websocket/index.js.map +0 -1
  350. package/src/react/websocket/hooks/useRoom.tsx +0 -251
  351. package/src/react/websocket/index.ts +0 -7
  352. package/src/websocket/__tests__/$channel.spec.ts +0 -30
  353. package/src/websocket/__tests__/$websocket-new.spec.ts +0 -195
  354. package/src/websocket/__tests__/RoomManager.spec.ts +0 -146
  355. package/src/websocket/__tests__/websocket-integration.spec.ts +0 -951
  356. package/src/websocket/errors/WebSocketError.ts +0 -34
  357. package/src/websocket/index.browser.ts +0 -25
  358. package/src/websocket/index.shared.ts +0 -8
  359. package/src/websocket/index.ts +0 -85
  360. package/src/websocket/interfaces/WebSocketInterfaces.ts +0 -252
  361. package/src/websocket/primitives/$channel.ts +0 -131
  362. package/src/websocket/primitives/$websocket.ts +0 -107
  363. package/src/websocket/providers/NodeWebSocketServerProvider.ts +0 -617
  364. package/src/websocket/providers/WebSocketServerProvider.ts +0 -56
  365. package/src/websocket/services/RoomManager.ts +0 -160
  366. package/src/websocket/services/WebSocketClient.ts +0 -642
  367. package/src/websocket/services/WebSocketTopicService.ts +0 -108
@@ -1,5 +1,6 @@
1
1
  import * as _$alepha from "alepha";
2
2
  import { Alepha, AlephaError, Async, KIND, PipelinePrimitive, PipelinePrimitiveOptions, Static, TNull, TObject, TOptional, TSchema, TUnion } from "alepha";
3
+ import { LockProvider } from "alepha/lock";
3
4
  import * as _$alepha_queue0 from "alepha/queue";
4
5
  import { CronProvider } from "alepha/scheduler";
5
6
  import * as _$alepha_server0 from "alepha/server";
@@ -7,6 +8,7 @@ import * as _$alepha_logger0 from "alepha/logger";
7
8
  import { LogEntry } from "alepha/logger";
8
9
  import * as _$alepha_orm0 from "alepha/orm";
9
10
  import { DateTime, DateTimeProvider, DurationLike } from "alepha/datetime";
11
+ import * as _$typebox from "typebox";
10
12
  import { BuildExtraConfigColumns, SQL } from "drizzle-orm";
11
13
  import { PgColumnBuilderBase, PgSequenceOptions, PgTableExtraConfigValue, UpdateDeleteAction } from "drizzle-orm/pg-core";
12
14
  //#region ../../src/orm/core/schemas/insertSchema.d.ts
@@ -23,6 +25,8 @@ type TObjectInsert<T extends TObject> = TObject<{ [K in keyof T["properties"] as
23
25
  [PG_GENERATED]: any;
24
26
  } ? never : K]: T["properties"][K] extends {
25
27
  [PG_DEFAULT]: any;
28
+ } | {
29
+ [PG_ORGANIZATION]: any;
26
30
  } | {
27
31
  "~optional": true;
28
32
  } ? TOptional<T["properties"][K]> : T["properties"][K] }>;
@@ -298,8 +302,8 @@ type PgAttr<T extends TSchema, TAttr extends PgSymbolKeys> = T & { [K in TAttr]:
298
302
  * - `d1://BINDING_NAME` — Cloudflare D1
299
303
  * - `hyperdrive://BINDING_NAME` — Cloudflare Hyperdrive
300
304
  */
301
- declare const databaseEnvSchema: _$alepha.TObject<{
302
- DATABASE_URL: _$alepha.TOptional<_$alepha.TString>;
305
+ declare const databaseEnvSchema: _$typebox.TObject<{
306
+ DATABASE_URL: _$typebox.TOptional<_$typebox.TString>;
303
307
  /**
304
308
  * Enable or disable push-based schema synchronization (drizzle-kit push).
305
309
  *
@@ -307,12 +311,63 @@ declare const databaseEnvSchema: _$alepha.TObject<{
307
311
  * Set to `false` in development to skip automatic schema sync
308
312
  * (e.g. when managing migrations manually).
309
313
  */
310
- DATABASE_SYNC: _$alepha.TOptional<_$alepha.TBoolean>;
314
+ DATABASE_SYNC: _$typebox.TOptional<_$typebox.TBoolean>;
311
315
  }>;
312
316
  declare module "alepha" {
313
317
  interface Env extends Partial<Static<typeof databaseEnvSchema>> {}
314
318
  } //# sourceMappingURL=databaseEnvSchema.d.ts.map
315
319
  //#endregion
320
+ //#region ../../src/api/jobs/entities/jobExecutionEntity.d.ts
321
+ /**
322
+ * Job execution record.
323
+ *
324
+ * Stores durable state for queue-mode jobs (outbox pattern) and error records
325
+ * for cron-mode jobs. Successful executions are trimmed by the sweep to keep
326
+ * the last N rows per job (configurable via `jobConfig.keepLastSuccess`).
327
+ *
328
+ * Status transitions:
329
+ * - queue push → pending (or `scheduled` if `delay`/`scheduledAt` was given)
330
+ * - worker claim → running
331
+ * - success → ok (or row deleted, depending on `record` and `keepLastSuccess`)
332
+ * - terminal failure → error
333
+ * - retryable failure → scheduled (with scheduledAt = now; sweep picks it up)
334
+ * - delay → scheduled (with scheduledAt = now + delay)
335
+ * - sweep picks due ones → pending
336
+ * - cancel → cancelled
337
+ */
338
+ declare const jobExecutionEntity: _$alepha_orm0.EntityPrimitive<_$typebox.TObject<{
339
+ id: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_PRIMARY_KEY>, typeof _$alepha_orm0.PG_DEFAULT>;
340
+ createdAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_CREATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
341
+ updatedAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_UPDATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
342
+ jobName: _$typebox.TString;
343
+ key: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TNull, _$typebox.TString]>>;
344
+ status: _$alepha_orm0.PgAttr<_$typebox.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof _$alepha_orm0.PG_DEFAULT>;
345
+ priority: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
346
+ attempt: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
347
+ maxAttempts: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
348
+ payload: _$typebox.TOptional<_$typebox.TRecord<"^.*$", _$typebox.TAny>>;
349
+ scheduledAt: _$typebox.TOptional<_$typebox.TString>;
350
+ startedAt: _$typebox.TOptional<_$typebox.TString>;
351
+ completedAt: _$typebox.TOptional<_$typebox.TString>;
352
+ error: _$typebox.TOptional<_$typebox.TString>;
353
+ logs: _$typebox.TOptional<_$typebox.TArray<_$typebox.TObject<{
354
+ level: _$typebox.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
355
+ message: _$typebox.TString;
356
+ service: _$typebox.TString;
357
+ module: _$typebox.TString;
358
+ context: _$typebox.TOptional<_$typebox.TString>;
359
+ app: _$typebox.TOptional<_$typebox.TString>;
360
+ data: _$typebox.TOptional<_$typebox.TAny>;
361
+ timestamp: _$typebox.TNumber;
362
+ }>>>;
363
+ triggeredBy: _$typebox.TOptional<_$typebox.TString>;
364
+ triggeredByName: _$typebox.TOptional<_$typebox.TString>;
365
+ cancelledBy: _$typebox.TOptional<_$typebox.TString>;
366
+ cancelledByName: _$typebox.TOptional<_$typebox.TString>;
367
+ }>>;
368
+ type JobExecutionEntity = Static<typeof jobExecutionEntity.schema>;
369
+ type JobStatus = "pending" | "running" | "scheduled" | "ok" | "error" | "cancelled";
370
+ //#endregion
316
371
  //#region ../../src/api/jobs/primitives/$job.d.ts
317
372
  /**
318
373
  * Job primitive for defining scheduled (cron) or queued (push) tasks.
@@ -333,15 +388,8 @@ interface JobHandlerArgs<T extends TSchema = TSchema> {
333
388
  signal: AbortSignal;
334
389
  executionId: string;
335
390
  }
336
- interface JobRetryBackoff {
337
- initial: DurationLike;
338
- factor?: number;
339
- max?: DurationLike;
340
- jitter?: boolean;
341
- }
342
391
  interface JobRetryOptions {
343
392
  retries: number;
344
- backoff?: DurationLike | JobRetryBackoff;
345
393
  when?: (error: Error) => boolean;
346
394
  }
347
395
  type JobPriority = "critical" | "high" | "normal" | "low";
@@ -366,10 +414,30 @@ interface JobPrimitiveOptions<T extends TSchema = TSchema> extends PipelinePrimi
366
414
  */
367
415
  cron?: string;
368
416
  /**
369
- * Retry policy for queue-mode jobs.
417
+ * Retry policy for queue-mode and direct-mode jobs.
370
418
  * Cron-mode jobs do not retry — the next tick re-runs.
419
+ *
420
+ * Retries are picked up by the reconciliation sweep, so retry granularity
421
+ * is bounded by `sweepCron` (default 5 minutes). The first retry may run
422
+ * earlier than 5 minutes if the sweep tick happens sooner.
371
423
  */
372
424
  retry?: JobRetryOptions;
425
+ /**
426
+ * **Cron-mode only.** Whether to acquire a distributed lock around the
427
+ * cron tick so that only one instance of a multi-replica deployment runs
428
+ * the handler per tick.
429
+ *
430
+ * Has **no effect** on queue-mode and direct-mode jobs — those rely on
431
+ * the outbox `claim()` UPDATE-guard to serialize work instead, which is
432
+ * always on.
433
+ *
434
+ * To get cross-instance coordination on Docker / Node deployments,
435
+ * register a real `LockProvider` (e.g. `alepha/lock/redis`). The default
436
+ * `MemoryLockProvider` is per-process only.
437
+ *
438
+ * @default true
439
+ */
440
+ lock?: boolean;
373
441
  /**
374
442
  * Max execution time per attempt. Handler receives an `AbortSignal`.
375
443
  */
@@ -433,6 +501,52 @@ declare class JobPrimitive<T extends TSchema = TSchema> extends PipelinePrimitiv
433
501
  trigger(context?: JobTriggerContext<T>): Promise<void>;
434
502
  }
435
503
  //#endregion
504
+ //#region ../../src/api/jobs/providers/JobDispatcher.d.ts
505
+ /**
506
+ * Abstract dispatcher for queued/direct job executions.
507
+ *
508
+ * The default implementation, {@link DirectJobDispatcher}, runs the handler
509
+ * in-process after the caller's `push()` returns — fast and dependency-free.
510
+ *
511
+ * `AlephaApiJobsQueue` substitutes this with `JobQueueProvider`, which
512
+ * publishes the executionId to `AlephaQueue` so a worker pool can consume
513
+ * the work asynchronously.
514
+ *
515
+ * Substitute via DI:
516
+ * ```ts
517
+ * Alepha.create()
518
+ * .with({ provide: JobDispatcher, use: MyCustomDispatcher })
519
+ * .with(AlephaApiJobs);
520
+ * ```
521
+ *
522
+ * The `kind` getter is read by the `JobProvider.effectiveMode` accessor
523
+ * and by the admin UI so users can see which dispatcher is currently active.
524
+ */
525
+ declare abstract class JobDispatcher {
526
+ /**
527
+ * Identifier for this dispatcher's effective mode. Reported to the admin
528
+ * UI so operators can see whether `$job` is running in `queue` or
529
+ * `direct` mode.
530
+ */
531
+ abstract readonly kind: "queue" | "direct";
532
+ /**
533
+ * Hand off a single execution. The caller's `push()` awaits this so the
534
+ * caller can be sure the dispatch has at least been initiated. Long-running
535
+ * work must NOT be awaited here (use background scheduling instead) — this
536
+ * call should return as quickly as possible.
537
+ */
538
+ abstract dispatch(jobName: string, executionId: string): Promise<void>;
539
+ /**
540
+ * Optional batch dispatch. The default implementation loops, but
541
+ * dispatchers backed by a real queue should override this to use the
542
+ * provider's batch send (e.g. Cloudflare Queues `sendBatch`).
543
+ */
544
+ dispatchMany(items: Array<{
545
+ jobName: string;
546
+ executionId: string;
547
+ }>): Promise<void>;
548
+ }
549
+ //#endregion
436
550
  //#region ../../src/api/jobs/providers/JobProvider.d.ts
437
551
  declare const PRIORITY_MAP: Record<JobPriority, number>;
438
552
  declare const PRIORITY_REVERSE: Record<number, JobPriority>;
@@ -460,34 +574,59 @@ interface CancelContext {
460
574
  cancelledBy?: string;
461
575
  cancelledByName?: string;
462
576
  }
577
+ /**
578
+ * The declared shape of the job (set at registration time).
579
+ *
580
+ * **Important** — this `kind` is the *declared* form. The *effective*
581
+ * runtime mode (cron / queue / direct) is exposed by
582
+ * `JobProvider.effectiveMode(name)` and the `JobRegistration.type` field on
583
+ * the admin schema. Don't conflate the two: a `queue` kind can run as
584
+ * `direct` at runtime when no queue dispatcher is loaded.
585
+ */
463
586
  interface JobRuntimeRegistration {
464
587
  name: string;
465
588
  options: JobPrimitiveOptions;
466
- type: "cron" | "queue";
589
+ kind: "cron" | "queue";
467
590
  }
591
+ type JobEffectiveMode = "cron" | "queue" | "direct";
468
592
  /**
469
- * Coordinates cron (scheduler) and queue (push) jobs with a durable outbox
470
- * table and a single reconciliation sweep.
593
+ * Coordinates cron and push jobs with a durable outbox table and a single
594
+ * reconciliation sweep. The actual delivery channel (queue / direct) is
595
+ * abstracted behind {@link JobDispatcher}, substituted by DI:
596
+ *
597
+ * - **DirectJobDispatcher** (default, registered by `AlephaApiJobs`) —
598
+ * runs the handler in-process right after `push()` returns.
599
+ * - **QueueJobDispatcher** (registered by `AlephaApiJobsQueue`) — sends
600
+ * the executionId through `AlephaQueue` so a pool of workers can pick
601
+ * it up.
471
602
  *
472
- * Queue-mode flow:
473
- * push() → INSERT row (pending) + queue.send({ executionId })
474
- * worker → SELECT row → UPDATE running → handler → DELETE (ok) / UPDATE (error)
603
+ * Push flow:
604
+ * push() → INSERT row (pending) dispatcher.dispatch(jobName, id)
605
+ * worker → claim → UPDATE running → handler → DELETE/UPDATE on success
606
+ * → UPDATE error / scheduled (retry) on failure
475
607
  *
476
- * Cron-mode flow:
477
- * scheduler tick → handler runs inline INSERT row only on error
608
+ * Cron flow:
609
+ * scheduler tick → acquire lockexecuteInline (no retry)
610
+ * → enqueue + dispatch (retry declared)
478
611
  *
479
- * Sweep responsibilities (every `sweepInterval`):
612
+ * Sweep responsibilities (every `sweepCron`):
480
613
  * - re-enqueue pending rows older than `staleThreshold`
481
- * - fail running rows older than `max(timeout*2, runTimeout)`
482
- * - move `scheduled` rows with `scheduledAt <= now` to pending + enqueue
483
- * - trim per-job history beyond `keepLastSuccess` / `keepLastError`
614
+ * - mark crashed running rows as failed and apply retry policy
615
+ * - move `scheduled` rows with `scheduledAt <= now` to pending + dispatch
616
+ *
617
+ * Trim runs on its own cron (`trimCron`, default hourly):
618
+ * - per-job history trimmed beyond `keepLastSuccess` / `keepLastError`
619
+ * - decoupled from sweep because trim cost scales with job count, not
620
+ * retry latency — running it every sweep is wasted work for most apps.
484
621
  */
485
622
  declare class JobProvider {
486
623
  protected readonly alepha: Alepha;
487
624
  protected readonly dt: DateTimeProvider;
488
625
  protected readonly cronProvider: CronProvider;
626
+ protected readonly lockProvider: LockProvider;
489
627
  protected readonly config: Readonly<{
490
- sweepInterval: number;
628
+ sweepCron: string;
629
+ trimCron: string;
491
630
  staleThreshold: number;
492
631
  runTimeout: number;
493
632
  keepLastSuccess: number;
@@ -495,36 +634,45 @@ declare class JobProvider {
495
634
  logMaxEntries: number;
496
635
  drainTimeout: number;
497
636
  }>;
637
+ /**
638
+ * Resolved at first use (after the container is fully wired) — picks
639
+ * the queue dispatcher when `AlephaApiJobsQueue` was loaded, otherwise
640
+ * the direct dispatcher. Lazy because both dispatchers inject
641
+ * `JobProvider` themselves; resolving them at field-init time would
642
+ * create a circular construction.
643
+ */
644
+ protected dispatcherRef?: JobDispatcher;
645
+ get dispatcher(): JobDispatcher;
498
646
  protected readonly log: _$alepha_logger0.Logger;
499
- protected readonly executions: _$alepha_orm0.Repository<_$alepha.TObject<{
500
- id: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_PRIMARY_KEY>, typeof _$alepha_orm0.PG_DEFAULT>;
501
- createdAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_CREATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
502
- updatedAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_UPDATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
503
- jobName: _$alepha.TString;
504
- key: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TNull, _$alepha.TString]>>;
505
- status: _$alepha_orm0.PgAttr<_$alepha.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof _$alepha_orm0.PG_DEFAULT>;
506
- priority: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
507
- attempt: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
508
- maxAttempts: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
509
- payload: _$alepha.TOptional<_$alepha.TRecord<"^.*$", _$alepha.TAny>>;
510
- scheduledAt: _$alepha.TOptional<_$alepha.TString>;
511
- startedAt: _$alepha.TOptional<_$alepha.TString>;
512
- completedAt: _$alepha.TOptional<_$alepha.TString>;
513
- error: _$alepha.TOptional<_$alepha.TString>;
514
- logs: _$alepha.TOptional<_$alepha.TArray<_$alepha.TObject<{
515
- level: _$alepha.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
516
- message: _$alepha.TString;
517
- service: _$alepha.TString;
518
- module: _$alepha.TString;
519
- context: _$alepha.TOptional<_$alepha.TString>;
520
- app: _$alepha.TOptional<_$alepha.TString>;
521
- data: _$alepha.TOptional<_$alepha.TAny>;
522
- timestamp: _$alepha.TNumber;
647
+ protected readonly executions: _$alepha_orm0.Repository<_$typebox.TObject<{
648
+ id: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_PRIMARY_KEY>, typeof _$alepha_orm0.PG_DEFAULT>;
649
+ createdAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_CREATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
650
+ updatedAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_UPDATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
651
+ jobName: _$typebox.TString;
652
+ key: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TNull, _$typebox.TString]>>;
653
+ status: _$alepha_orm0.PgAttr<_$typebox.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof _$alepha_orm0.PG_DEFAULT>;
654
+ priority: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
655
+ attempt: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
656
+ maxAttempts: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
657
+ payload: _$typebox.TOptional<_$typebox.TRecord<"^.*$", _$typebox.TAny>>;
658
+ scheduledAt: _$typebox.TOptional<_$typebox.TString>;
659
+ startedAt: _$typebox.TOptional<_$typebox.TString>;
660
+ completedAt: _$typebox.TOptional<_$typebox.TString>;
661
+ error: _$typebox.TOptional<_$typebox.TString>;
662
+ logs: _$typebox.TOptional<_$typebox.TArray<_$typebox.TObject<{
663
+ level: _$typebox.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
664
+ message: _$typebox.TString;
665
+ service: _$typebox.TString;
666
+ module: _$typebox.TString;
667
+ context: _$typebox.TOptional<_$typebox.TString>;
668
+ app: _$typebox.TOptional<_$typebox.TString>;
669
+ data: _$typebox.TOptional<_$typebox.TAny>;
670
+ timestamp: _$typebox.TNumber;
523
671
  }>>>;
524
- triggeredBy: _$alepha.TOptional<_$alepha.TString>;
525
- triggeredByName: _$alepha.TOptional<_$alepha.TString>;
526
- cancelledBy: _$alepha.TOptional<_$alepha.TString>;
527
- cancelledByName: _$alepha.TOptional<_$alepha.TString>;
672
+ triggeredBy: _$typebox.TOptional<_$typebox.TString>;
673
+ triggeredByName: _$typebox.TOptional<_$typebox.TString>;
674
+ cancelledBy: _$typebox.TOptional<_$typebox.TString>;
675
+ cancelledByName: _$typebox.TOptional<_$typebox.TString>;
528
676
  }>>;
529
677
  protected readonly jobs: Map<string, JobRuntimeRegistration>;
530
678
  protected readonly inFlight: Set<Promise<void>>;
@@ -540,14 +688,75 @@ declare class JobProvider {
540
688
  timestamp: number;
541
689
  }[]>;
542
690
  protected stopping: boolean;
543
- /**
544
- * Set by `JobQueueProvider` when `AlephaApiJobsQueue` is loaded.
545
- * When null, queue-mode jobs cannot be pushed.
546
- */
547
- queueDispatch: ((jobName: string, executionId: string) => Promise<void>) | null;
548
691
  registerJob(name: string, options: JobPrimitiveOptions): void;
549
692
  getRegisteredJobs(): Map<string, JobRuntimeRegistration>;
693
+ /**
694
+ * Resolves what *actually* runs at dispatch time. Cron jobs are always
695
+ * "cron"; non-cron jobs delegate to the active `JobDispatcher` (queue
696
+ * vs. direct), which is determined by which modules the app loaded.
697
+ */
698
+ effectiveMode(name: string): JobEffectiveMode;
550
699
  protected runCron(name: string): Promise<void>;
700
+ /**
701
+ * Cron-mode runner that respects the per-job distributed lock.
702
+ * Used by both the scheduled tick and manual `trigger()` calls so that an
703
+ * admin-triggered run on one instance can't race a scheduled run on another.
704
+ *
705
+ * **Two paths depending on `retry`:**
706
+ *
707
+ * - **No `retry`** — runs the handler inline. No DB row on success;
708
+ * error row only on failure. The "next tick" is the implicit retry.
709
+ * - **`retry` declared** — enqueues a synthetic execution row and hands
710
+ * it to the dispatcher. The handler then runs through the same path
711
+ * as a queue/direct push (claim, retry-on-fail, sweep recovery). Use
712
+ * this when a single failed tick must not block work for the whole
713
+ * `cron` interval (e.g. once-daily jobs).
714
+ */
715
+ protected runCronLocked(registration: JobRuntimeRegistration, ctx: {
716
+ triggeredBy?: string;
717
+ triggeredByName?: string;
718
+ }): Promise<void>;
719
+ /**
720
+ * Materialize a cron tick into the outbox so it goes through the normal
721
+ * retry/sweep path. Used when the user opts into `retry` on a cron job —
722
+ * a transient failure no longer means "wait for the next cron tick", it
723
+ * means "the sweep will retry within `sweepCron`".
724
+ */
725
+ protected enqueueCronExecution(registration: JobRuntimeRegistration, ctx: {
726
+ triggeredBy?: string;
727
+ triggeredByName?: string;
728
+ }): Promise<void>;
729
+ /**
730
+ * Acquire a per-job NX lock keyed by `cron-job:<name>` so that a single
731
+ * tick across all replicas runs exactly one execution. Auto-expires after
732
+ * `2 * timeout` (or 5 minutes if no per-job timeout) so a crashed worker
733
+ * cannot permanently block the cron from firing.
734
+ *
735
+ * **Caveat — same-process double-fire is not prevented.** The lock value
736
+ * is a per-process holder id, so two concurrent ticks on the same process
737
+ * (e.g. a scheduled tick overlapping an admin `trigger()` call) will both
738
+ * see "we own it". This is acceptable for the multi-replica use case the
739
+ * lock targets; a process that overlaps its own cron handler should set a
740
+ * smaller `timeout` or use idempotent handler logic. A future fix can add
741
+ * a per-process Set guard before reaching the LockProvider.
742
+ */
743
+ protected acquireCronLock(registration: JobRuntimeRegistration): Promise<boolean>;
744
+ /**
745
+ * Update only when the row is still in one of the expected statuses.
746
+ * Logs and returns silently when the guard rejects — this happens when a
747
+ * concurrent operation (most often `cancel()`) has already moved the row
748
+ * into a terminal state. We must not overwrite that.
749
+ */
750
+ protected guardedUpdate(executionId: string, expectedStatuses: JobStatus[], patch: Parameters<typeof this.executions.updateById>[1], label: string): Promise<void>;
751
+ protected releaseCronLock(registration: JobRuntimeRegistration): Promise<void>;
752
+ protected cronLockKey(jobName: string): string;
753
+ /**
754
+ * Stable per-process id used as the lock value — survives multiple ticks.
755
+ * Lazy so that Cloudflare Workers (which forbid random in global scope)
756
+ * stay happy.
757
+ */
758
+ protected lockHolderIdValue?: string;
759
+ protected get lockHolderId(): string;
551
760
  /**
552
761
  * Execute a cron handler inline. Records a row only on error (or always,
553
762
  * when `record: 'all'`). No DB writes on the happy path by default.
@@ -576,17 +785,65 @@ declare class JobProvider {
576
785
  */
577
786
  protected scheduleOptimisticDispatch(jobName: string, executionId: string, scheduledAt: string): void;
578
787
  pushMany(name: string, items: Array<PushManyItem>): Promise<string[]>;
579
- protected dispatchToQueue(jobName: string, executionId: string): Promise<void>;
788
+ /**
789
+ * Hand a single execution to the active `JobDispatcher`. Whether that
790
+ * results in a queue send or in-process execution depends on which
791
+ * dispatcher is wired (see {@link JobDispatcher}).
792
+ */
793
+ protected dispatch(jobName: string, executionId: string): Promise<void>;
794
+ /**
795
+ * Batched variant. Used by `pushMany` so a backing queue can do a single
796
+ * batch network call (e.g. Cloudflare Queues `sendBatch`).
797
+ */
798
+ protected dispatchMany(items: Array<{
799
+ jobName: string;
800
+ executionId: string;
801
+ }>): Promise<void>;
580
802
  trigger(name: string, context?: JobTriggerContext): Promise<void>;
581
803
  cancel(executionId: string, context?: CancelContext): Promise<void>;
582
804
  processExecution(jobName: string, executionId: string): Promise<void>;
583
805
  protected processQueueExecution(registration: JobRuntimeRegistration, executionId: string): Promise<void>;
584
- protected claim(executionId: string): Promise<boolean>;
806
+ /**
807
+ * Transition pending → running and return the post-update row.
808
+ * Two round-trips: read current attempt, then guarded UPDATE … RETURNING.
809
+ * Returns null when the row is gone or already claimed by another worker.
810
+ * The returned row replaces a separate post-claim findById, so the dispatch
811
+ * path is 2 queries instead of 3.
812
+ */
813
+ protected claim(executionId: string): Promise<{
814
+ key?: string | null | undefined;
815
+ error?: string | undefined;
816
+ payload?: Record<string, any> | undefined;
817
+ scheduledAt?: string | undefined;
818
+ startedAt?: string | undefined;
819
+ completedAt?: string | undefined;
820
+ logs?: {
821
+ context?: string | undefined;
822
+ app?: string | undefined;
823
+ data?: any;
824
+ level: "SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR";
825
+ message: string;
826
+ service: string;
827
+ module: string;
828
+ timestamp: number;
829
+ }[] | undefined;
830
+ triggeredBy?: string | undefined;
831
+ triggeredByName?: string | undefined;
832
+ cancelledBy?: string | undefined;
833
+ cancelledByName?: string | undefined;
834
+ jobName: string;
835
+ id: string;
836
+ createdAt: string;
837
+ updatedAt: string;
838
+ status: "pending" | "running" | "scheduled" | "ok" | "error" | "cancelled";
839
+ priority: number;
840
+ attempt: number;
841
+ maxAttempts: number;
842
+ } | null>;
585
843
  protected handleFailure(executionId: string, registration: JobRuntimeRegistration, currentAttempt: number, error: Error, contextId: string): Promise<void>;
586
- protected computeBackoff(retry: JobRetryOptions, attempt: number): string;
587
844
  protected snapshotLogs(contextId: string): LogEntry[] | undefined;
588
845
  protected sweep(): Promise<void>;
589
- protected dispatchToQueueSafe(jobName: string, executionId: string): Promise<void>;
846
+ protected dispatchSafe(jobName: string, executionId: string): Promise<void>;
590
847
  /**
591
848
  * Move a row from `scheduled` → `pending` and dispatch it.
592
849
  * Used by the optimistic retry/delay timer. If the sweep has already moved
@@ -601,28 +858,74 @@ declare class JobProvider {
601
858
  }
602
859
  //#endregion
603
860
  //#region ../../src/api/jobs/schemas/jobExecutionQuerySchema.d.ts
604
- declare const jobExecutionQuerySchema: _$alepha.TObject<{
605
- status: _$alepha.TOptional<_$alepha.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">>;
606
- limit: _$alepha.TOptional<_$alepha.TInteger>;
861
+ declare const jobExecutionQuerySchema: _$typebox.TObject<{
862
+ status: _$typebox.TOptional<_$typebox.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">>;
863
+ limit: _$typebox.TOptional<_$typebox.TInteger>;
607
864
  }>;
608
865
  type JobExecutionQuery = Static<typeof jobExecutionQuerySchema>;
609
866
  //#endregion
867
+ //#region ../../src/api/jobs/schemas/jobExecutionResourceSchema.d.ts
868
+ /**
869
+ * Public-facing schema for a job execution row.
870
+ *
871
+ * Diverges from the raw entity in two places, both for API ergonomics:
872
+ *
873
+ * - `priority` is exposed as the **string enum** (`critical`/`high`/...)
874
+ * instead of the numeric value used internally for SQL ordering. The
875
+ * `JobService` is responsible for the int → string transform.
876
+ * - `can` derives the available admin actions from the row's status.
877
+ */
878
+ declare const jobExecutionResourceSchema: _$typebox.TObject<{
879
+ id: PgAttr<PgAttr<_$typebox.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
880
+ createdAt: PgAttr<PgAttr<_$typebox.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
881
+ updatedAt: PgAttr<PgAttr<_$typebox.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
882
+ jobName: _$typebox.TString;
883
+ key: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TNull, _$typebox.TString]>>;
884
+ status: PgAttr<_$typebox.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof PG_DEFAULT>;
885
+ priority: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
886
+ attempt: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
887
+ maxAttempts: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
888
+ payload: _$typebox.TOptional<_$typebox.TRecord<"^.*$", _$typebox.TAny>>;
889
+ scheduledAt: _$typebox.TOptional<_$typebox.TString>;
890
+ startedAt: _$typebox.TOptional<_$typebox.TString>;
891
+ completedAt: _$typebox.TOptional<_$typebox.TString>;
892
+ error: _$typebox.TOptional<_$typebox.TString>;
893
+ logs: _$typebox.TOptional<_$typebox.TArray<_$typebox.TObject<{
894
+ level: _$typebox.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
895
+ message: _$typebox.TString;
896
+ service: _$typebox.TString;
897
+ module: _$typebox.TString;
898
+ context: _$typebox.TOptional<_$typebox.TString>;
899
+ app: _$typebox.TOptional<_$typebox.TString>;
900
+ data: _$typebox.TOptional<_$typebox.TAny>;
901
+ timestamp: _$typebox.TNumber;
902
+ }>>>;
903
+ triggeredBy: _$typebox.TOptional<_$typebox.TString>;
904
+ triggeredByName: _$typebox.TOptional<_$typebox.TString>;
905
+ cancelledBy: _$typebox.TOptional<_$typebox.TString>;
906
+ cancelledByName: _$typebox.TOptional<_$typebox.TString>;
907
+ can: _$typebox.TObject<{
908
+ retry: _$typebox.TBoolean;
909
+ cancel: _$typebox.TBoolean;
910
+ }>;
911
+ }>;
912
+ type JobExecutionResource = Static<typeof jobExecutionResourceSchema>;
913
+ //#endregion
610
914
  //#region ../../src/api/jobs/schemas/jobRegistrationSchema.d.ts
611
- declare const jobRegistrationSchema: _$alepha.TObject<{
612
- name: _$alepha.TString;
613
- description: _$alepha.TOptional<_$alepha.TString>;
614
- type: _$alepha.TUnsafe<"cron" | "queue">;
615
- priority: _$alepha.TUnsafe<"critical" | "high" | "normal" | "low">;
616
- cron: _$alepha.TOptional<_$alepha.TString>;
617
- timeout: _$alepha.TOptional<_$alepha.TString>;
618
- retry: _$alepha.TOptional<_$alepha.TObject<{
619
- retries: _$alepha.TInteger;
620
- hasBackoff: _$alepha.TBoolean;
915
+ declare const jobRegistrationSchema: _$typebox.TObject<{
916
+ name: _$typebox.TString;
917
+ description: _$typebox.TOptional<_$typebox.TString>;
918
+ type: _$typebox.TUnsafe<"queue" | "direct" | "cron">;
919
+ priority: _$typebox.TUnsafe<"critical" | "high" | "normal" | "low">;
920
+ cron: _$typebox.TOptional<_$typebox.TString>;
921
+ timeout: _$typebox.TOptional<_$typebox.TString>;
922
+ retry: _$typebox.TOptional<_$typebox.TObject<{
923
+ retries: _$typebox.TInteger;
621
924
  }>>;
622
- recent: _$alepha.TObject<{
623
- ok: _$alepha.TInteger;
624
- error: _$alepha.TInteger;
625
- lastRun: _$alepha.TOptional<_$alepha.TString>;
925
+ recent: _$typebox.TObject<{
926
+ ok: _$typebox.TInteger;
927
+ error: _$typebox.TInteger;
928
+ lastRun: _$typebox.TOptional<_$typebox.TString>;
626
929
  }>;
627
930
  }>;
628
931
  type JobRegistration = Static<typeof jobRegistrationSchema>;
@@ -640,40 +943,50 @@ declare class JobService {
640
943
  protected readonly alepha: Alepha;
641
944
  protected readonly log: _$alepha_logger0.Logger;
642
945
  protected readonly jobProvider: JobProvider;
643
- protected readonly executions: _$alepha_orm0.Repository<_$alepha.TObject<{
644
- id: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_PRIMARY_KEY>, typeof _$alepha_orm0.PG_DEFAULT>;
645
- createdAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_CREATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
646
- updatedAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_UPDATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
647
- jobName: _$alepha.TString;
648
- key: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TNull, _$alepha.TString]>>;
649
- status: _$alepha_orm0.PgAttr<_$alepha.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof _$alepha_orm0.PG_DEFAULT>;
650
- priority: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
651
- attempt: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
652
- maxAttempts: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
653
- payload: _$alepha.TOptional<_$alepha.TRecord<"^.*$", _$alepha.TAny>>;
654
- scheduledAt: _$alepha.TOptional<_$alepha.TString>;
655
- startedAt: _$alepha.TOptional<_$alepha.TString>;
656
- completedAt: _$alepha.TOptional<_$alepha.TString>;
657
- error: _$alepha.TOptional<_$alepha.TString>;
658
- logs: _$alepha.TOptional<_$alepha.TArray<_$alepha.TObject<{
659
- level: _$alepha.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
660
- message: _$alepha.TString;
661
- service: _$alepha.TString;
662
- module: _$alepha.TString;
663
- context: _$alepha.TOptional<_$alepha.TString>;
664
- app: _$alepha.TOptional<_$alepha.TString>;
665
- data: _$alepha.TOptional<_$alepha.TAny>;
666
- timestamp: _$alepha.TNumber;
946
+ protected readonly executions: _$alepha_orm0.Repository<_$typebox.TObject<{
947
+ id: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_PRIMARY_KEY>, typeof _$alepha_orm0.PG_DEFAULT>;
948
+ createdAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_CREATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
949
+ updatedAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$typebox.TString, typeof _$alepha_orm0.PG_UPDATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
950
+ jobName: _$typebox.TString;
951
+ key: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TNull, _$typebox.TString]>>;
952
+ status: _$alepha_orm0.PgAttr<_$typebox.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof _$alepha_orm0.PG_DEFAULT>;
953
+ priority: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
954
+ attempt: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
955
+ maxAttempts: _$alepha_orm0.PgAttr<_$typebox.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
956
+ payload: _$typebox.TOptional<_$typebox.TRecord<"^.*$", _$typebox.TAny>>;
957
+ scheduledAt: _$typebox.TOptional<_$typebox.TString>;
958
+ startedAt: _$typebox.TOptional<_$typebox.TString>;
959
+ completedAt: _$typebox.TOptional<_$typebox.TString>;
960
+ error: _$typebox.TOptional<_$typebox.TString>;
961
+ logs: _$typebox.TOptional<_$typebox.TArray<_$typebox.TObject<{
962
+ level: _$typebox.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
963
+ message: _$typebox.TString;
964
+ service: _$typebox.TString;
965
+ module: _$typebox.TString;
966
+ context: _$typebox.TOptional<_$typebox.TString>;
967
+ app: _$typebox.TOptional<_$typebox.TString>;
968
+ data: _$typebox.TOptional<_$typebox.TAny>;
969
+ timestamp: _$typebox.TNumber;
667
970
  }>>>;
668
- triggeredBy: _$alepha.TOptional<_$alepha.TString>;
669
- triggeredByName: _$alepha.TOptional<_$alepha.TString>;
670
- cancelledBy: _$alepha.TOptional<_$alepha.TString>;
671
- cancelledByName: _$alepha.TOptional<_$alepha.TString>;
971
+ triggeredBy: _$typebox.TOptional<_$typebox.TString>;
972
+ triggeredByName: _$typebox.TOptional<_$typebox.TString>;
973
+ cancelledBy: _$typebox.TOptional<_$typebox.TString>;
974
+ cancelledByName: _$typebox.TOptional<_$typebox.TString>;
672
975
  }>>;
673
976
  protected computeCan(status: string): {
674
977
  retry: boolean;
675
978
  cancel: boolean;
676
979
  };
980
+ /**
981
+ * Convert the int-priority storage column into the public enum string.
982
+ * The cast through `unknown` skips TypeScript's structural check between
983
+ * the entity-level row (`priority: number`) and the resource schema
984
+ * (`priority: enum`); the runtime values are correct.
985
+ */
986
+ protected toResource<T extends {
987
+ priority: number;
988
+ status: string;
989
+ }>(row: T): JobExecutionResource;
677
990
  /**
678
991
  * List every registered job with recent ok/error counts and lastRun.
679
992
  * One aggregate query covers all jobs.
@@ -683,10 +996,6 @@ declare class JobService {
683
996
  * Recent executions for a single job, ORDER BY startedAt DESC.
684
997
  */
685
998
  getExecutions(jobName: string, query?: JobExecutionQuery): Promise<{
686
- can: {
687
- retry: boolean;
688
- cancel: boolean;
689
- };
690
999
  key?: string | null | undefined;
691
1000
  error?: string | undefined;
692
1001
  payload?: Record<string, any> | undefined;
@@ -707,23 +1016,23 @@ declare class JobService {
707
1016
  triggeredByName?: string | undefined;
708
1017
  cancelledBy?: string | undefined;
709
1018
  cancelledByName?: string | undefined;
1019
+ jobName: string;
710
1020
  id: string;
711
1021
  createdAt: string;
712
1022
  updatedAt: string;
713
- jobName: string;
714
1023
  status: "pending" | "running" | "scheduled" | "ok" | "error" | "cancelled";
715
1024
  priority: number;
716
1025
  attempt: number;
717
1026
  maxAttempts: number;
1027
+ can: {
1028
+ retry: boolean;
1029
+ cancel: boolean;
1030
+ };
718
1031
  }[]>;
719
1032
  /**
720
1033
  * Full execution detail (includes captured logs).
721
1034
  */
722
1035
  getExecution(id: string): Promise<{
723
- can: {
724
- retry: boolean;
725
- cancel: boolean;
726
- };
727
1036
  key?: string | null | undefined;
728
1037
  error?: string | undefined;
729
1038
  payload?: Record<string, any> | undefined;
@@ -744,14 +1053,18 @@ declare class JobService {
744
1053
  triggeredByName?: string | undefined;
745
1054
  cancelledBy?: string | undefined;
746
1055
  cancelledByName?: string | undefined;
1056
+ jobName: string;
747
1057
  id: string;
748
1058
  createdAt: string;
749
1059
  updatedAt: string;
750
- jobName: string;
751
1060
  status: "pending" | "running" | "scheduled" | "ok" | "error" | "cancelled";
752
1061
  priority: number;
753
1062
  attempt: number;
754
1063
  maxAttempts: number;
1064
+ can: {
1065
+ retry: boolean;
1066
+ cancel: boolean;
1067
+ };
755
1068
  }>;
756
1069
  /**
757
1070
  * Manual trigger (cron jobs) or push-with-payload (queue jobs).
@@ -785,220 +1098,218 @@ declare class AdminJobController {
785
1098
  protected readonly group: string;
786
1099
  protected readonly jobService: JobService;
787
1100
  readonly listJobs: _$alepha_server0.ActionPrimitiveFn<{
788
- response: _$alepha.TArray<_$alepha.TObject<{
789
- name: _$alepha.TString;
790
- description: _$alepha.TOptional<_$alepha.TString>;
791
- type: _$alepha.TUnsafe<"cron" | "queue">;
792
- priority: _$alepha.TUnsafe<"critical" | "high" | "normal" | "low">;
793
- cron: _$alepha.TOptional<_$alepha.TString>;
794
- timeout: _$alepha.TOptional<_$alepha.TString>;
795
- retry: _$alepha.TOptional<_$alepha.TObject<{
796
- retries: _$alepha.TInteger;
797
- hasBackoff: _$alepha.TBoolean;
1101
+ response: _$typebox.TArray<_$typebox.TObject<{
1102
+ name: _$typebox.TString;
1103
+ description: _$typebox.TOptional<_$typebox.TString>;
1104
+ type: _$typebox.TUnsafe<"queue" | "direct" | "cron">;
1105
+ priority: _$typebox.TUnsafe<"critical" | "high" | "normal" | "low">;
1106
+ cron: _$typebox.TOptional<_$typebox.TString>;
1107
+ timeout: _$typebox.TOptional<_$typebox.TString>;
1108
+ retry: _$typebox.TOptional<_$typebox.TObject<{
1109
+ retries: _$typebox.TInteger;
798
1110
  }>>;
799
- recent: _$alepha.TObject<{
800
- ok: _$alepha.TInteger;
801
- error: _$alepha.TInteger;
802
- lastRun: _$alepha.TOptional<_$alepha.TString>;
1111
+ recent: _$typebox.TObject<{
1112
+ ok: _$typebox.TInteger;
1113
+ error: _$typebox.TInteger;
1114
+ lastRun: _$typebox.TOptional<_$typebox.TString>;
803
1115
  }>;
804
1116
  }>>;
805
1117
  }>;
806
1118
  readonly listExecutions: _$alepha_server0.ActionPrimitiveFn<{
807
- params: _$alepha.TObject<{
808
- name: _$alepha.TString;
1119
+ params: _$typebox.TObject<{
1120
+ name: _$typebox.TString;
809
1121
  }>;
810
- query: _$alepha.TObject<{
811
- status: _$alepha.TOptional<_$alepha.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">>;
812
- limit: _$alepha.TOptional<_$alepha.TInteger>;
1122
+ query: _$typebox.TObject<{
1123
+ status: _$typebox.TOptional<_$typebox.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">>;
1124
+ limit: _$typebox.TOptional<_$typebox.TInteger>;
813
1125
  }>;
814
- response: _$alepha.TArray<_$alepha.TObject<{
815
- id: PgAttr<PgAttr<_$alepha.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
816
- createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
817
- updatedAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
818
- jobName: _$alepha.TString;
819
- key: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TNull, _$alepha.TString]>>;
820
- status: PgAttr<_$alepha.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof PG_DEFAULT>;
821
- priority: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
822
- attempt: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
823
- maxAttempts: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
824
- payload: _$alepha.TOptional<_$alepha.TRecord<"^.*$", _$alepha.TAny>>;
825
- scheduledAt: _$alepha.TOptional<_$alepha.TString>;
826
- startedAt: _$alepha.TOptional<_$alepha.TString>;
827
- completedAt: _$alepha.TOptional<_$alepha.TString>;
828
- error: _$alepha.TOptional<_$alepha.TString>;
829
- logs: _$alepha.TOptional<_$alepha.TArray<_$alepha.TObject<{
830
- level: _$alepha.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
831
- message: _$alepha.TString;
832
- service: _$alepha.TString;
833
- module: _$alepha.TString;
834
- context: _$alepha.TOptional<_$alepha.TString>;
835
- app: _$alepha.TOptional<_$alepha.TString>;
836
- data: _$alepha.TOptional<_$alepha.TAny>;
837
- timestamp: _$alepha.TNumber;
1126
+ response: _$typebox.TArray<_$typebox.TObject<{
1127
+ id: PgAttr<PgAttr<_$typebox.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
1128
+ createdAt: PgAttr<PgAttr<_$typebox.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
1129
+ updatedAt: PgAttr<PgAttr<_$typebox.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
1130
+ jobName: _$typebox.TString;
1131
+ key: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TNull, _$typebox.TString]>>;
1132
+ status: PgAttr<_$typebox.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof PG_DEFAULT>;
1133
+ priority: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
1134
+ attempt: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
1135
+ maxAttempts: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
1136
+ payload: _$typebox.TOptional<_$typebox.TRecord<"^.*$", _$typebox.TAny>>;
1137
+ scheduledAt: _$typebox.TOptional<_$typebox.TString>;
1138
+ startedAt: _$typebox.TOptional<_$typebox.TString>;
1139
+ completedAt: _$typebox.TOptional<_$typebox.TString>;
1140
+ error: _$typebox.TOptional<_$typebox.TString>;
1141
+ logs: _$typebox.TOptional<_$typebox.TArray<_$typebox.TObject<{
1142
+ level: _$typebox.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
1143
+ message: _$typebox.TString;
1144
+ service: _$typebox.TString;
1145
+ module: _$typebox.TString;
1146
+ context: _$typebox.TOptional<_$typebox.TString>;
1147
+ app: _$typebox.TOptional<_$typebox.TString>;
1148
+ data: _$typebox.TOptional<_$typebox.TAny>;
1149
+ timestamp: _$typebox.TNumber;
838
1150
  }>>>;
839
- triggeredBy: _$alepha.TOptional<_$alepha.TString>;
840
- triggeredByName: _$alepha.TOptional<_$alepha.TString>;
841
- cancelledBy: _$alepha.TOptional<_$alepha.TString>;
842
- cancelledByName: _$alepha.TOptional<_$alepha.TString>;
843
- can: _$alepha.TObject<{
844
- retry: _$alepha.TBoolean;
845
- cancel: _$alepha.TBoolean;
1151
+ triggeredBy: _$typebox.TOptional<_$typebox.TString>;
1152
+ triggeredByName: _$typebox.TOptional<_$typebox.TString>;
1153
+ cancelledBy: _$typebox.TOptional<_$typebox.TString>;
1154
+ cancelledByName: _$typebox.TOptional<_$typebox.TString>;
1155
+ can: _$typebox.TObject<{
1156
+ retry: _$typebox.TBoolean;
1157
+ cancel: _$typebox.TBoolean;
846
1158
  }>;
847
1159
  }>>;
848
1160
  }>;
849
1161
  readonly getExecution: _$alepha_server0.ActionPrimitiveFn<{
850
- params: _$alepha.TObject<{
851
- id: _$alepha.TString;
1162
+ params: _$typebox.TObject<{
1163
+ id: _$typebox.TString;
852
1164
  }>;
853
- response: _$alepha.TObject<{
854
- id: PgAttr<PgAttr<_$alepha.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
855
- createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
856
- updatedAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
857
- jobName: _$alepha.TString;
858
- key: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TNull, _$alepha.TString]>>;
859
- status: PgAttr<_$alepha.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof PG_DEFAULT>;
860
- priority: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
861
- attempt: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
862
- maxAttempts: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
863
- payload: _$alepha.TOptional<_$alepha.TRecord<"^.*$", _$alepha.TAny>>;
864
- scheduledAt: _$alepha.TOptional<_$alepha.TString>;
865
- startedAt: _$alepha.TOptional<_$alepha.TString>;
866
- completedAt: _$alepha.TOptional<_$alepha.TString>;
867
- error: _$alepha.TOptional<_$alepha.TString>;
868
- logs: _$alepha.TOptional<_$alepha.TArray<_$alepha.TObject<{
869
- level: _$alepha.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
870
- message: _$alepha.TString;
871
- service: _$alepha.TString;
872
- module: _$alepha.TString;
873
- context: _$alepha.TOptional<_$alepha.TString>;
874
- app: _$alepha.TOptional<_$alepha.TString>;
875
- data: _$alepha.TOptional<_$alepha.TAny>;
876
- timestamp: _$alepha.TNumber;
1165
+ response: _$typebox.TObject<{
1166
+ id: PgAttr<PgAttr<_$typebox.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
1167
+ createdAt: PgAttr<PgAttr<_$typebox.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
1168
+ updatedAt: PgAttr<PgAttr<_$typebox.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
1169
+ jobName: _$typebox.TString;
1170
+ key: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TNull, _$typebox.TString]>>;
1171
+ status: PgAttr<_$typebox.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof PG_DEFAULT>;
1172
+ priority: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
1173
+ attempt: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
1174
+ maxAttempts: PgAttr<_$typebox.TInteger, typeof PG_DEFAULT>;
1175
+ payload: _$typebox.TOptional<_$typebox.TRecord<"^.*$", _$typebox.TAny>>;
1176
+ scheduledAt: _$typebox.TOptional<_$typebox.TString>;
1177
+ startedAt: _$typebox.TOptional<_$typebox.TString>;
1178
+ completedAt: _$typebox.TOptional<_$typebox.TString>;
1179
+ error: _$typebox.TOptional<_$typebox.TString>;
1180
+ logs: _$typebox.TOptional<_$typebox.TArray<_$typebox.TObject<{
1181
+ level: _$typebox.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
1182
+ message: _$typebox.TString;
1183
+ service: _$typebox.TString;
1184
+ module: _$typebox.TString;
1185
+ context: _$typebox.TOptional<_$typebox.TString>;
1186
+ app: _$typebox.TOptional<_$typebox.TString>;
1187
+ data: _$typebox.TOptional<_$typebox.TAny>;
1188
+ timestamp: _$typebox.TNumber;
877
1189
  }>>>;
878
- triggeredBy: _$alepha.TOptional<_$alepha.TString>;
879
- triggeredByName: _$alepha.TOptional<_$alepha.TString>;
880
- cancelledBy: _$alepha.TOptional<_$alepha.TString>;
881
- cancelledByName: _$alepha.TOptional<_$alepha.TString>;
882
- can: _$alepha.TObject<{
883
- retry: _$alepha.TBoolean;
884
- cancel: _$alepha.TBoolean;
1190
+ triggeredBy: _$typebox.TOptional<_$typebox.TString>;
1191
+ triggeredByName: _$typebox.TOptional<_$typebox.TString>;
1192
+ cancelledBy: _$typebox.TOptional<_$typebox.TString>;
1193
+ cancelledByName: _$typebox.TOptional<_$typebox.TString>;
1194
+ can: _$typebox.TObject<{
1195
+ retry: _$typebox.TBoolean;
1196
+ cancel: _$typebox.TBoolean;
885
1197
  }>;
886
1198
  }>;
887
1199
  }>;
888
1200
  readonly triggerJob: _$alepha_server0.ActionPrimitiveFn<{
889
- params: _$alepha.TObject<{
890
- name: _$alepha.TString;
1201
+ params: _$typebox.TObject<{
1202
+ name: _$typebox.TString;
891
1203
  }>;
892
- body: _$alepha.TObject<{
893
- payload: _$alepha.TOptional<_$alepha.TRecord<"^.*$", _$alepha.TAny>>;
1204
+ body: _$typebox.TObject<{
1205
+ payload: _$typebox.TOptional<_$typebox.TRecord<"^.*$", _$typebox.TAny>>;
894
1206
  }>;
895
- response: _$alepha.TObject<{
896
- ok: _$alepha.TBoolean;
897
- id: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TString, _$alepha.TInteger]>>;
898
- count: _$alepha.TOptional<_$alepha.TNumber>;
1207
+ response: _$typebox.TObject<{
1208
+ ok: _$typebox.TBoolean;
1209
+ id: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TString, _$typebox.TInteger]>>;
1210
+ count: _$typebox.TOptional<_$typebox.TNumber>;
899
1211
  }>;
900
1212
  }>;
901
1213
  readonly retryExecution: _$alepha_server0.ActionPrimitiveFn<{
902
- params: _$alepha.TObject<{
903
- id: _$alepha.TString;
1214
+ params: _$typebox.TObject<{
1215
+ id: _$typebox.TString;
904
1216
  }>;
905
- response: _$alepha.TObject<{
906
- ok: _$alepha.TBoolean;
907
- id: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TString, _$alepha.TInteger]>>;
908
- count: _$alepha.TOptional<_$alepha.TNumber>;
1217
+ response: _$typebox.TObject<{
1218
+ ok: _$typebox.TBoolean;
1219
+ id: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TString, _$typebox.TInteger]>>;
1220
+ count: _$typebox.TOptional<_$typebox.TNumber>;
909
1221
  }>;
910
1222
  }>;
911
1223
  readonly cancelExecution: _$alepha_server0.ActionPrimitiveFn<{
912
- params: _$alepha.TObject<{
913
- id: _$alepha.TString;
1224
+ params: _$typebox.TObject<{
1225
+ id: _$typebox.TString;
914
1226
  }>;
915
- response: _$alepha.TObject<{
916
- ok: _$alepha.TBoolean;
917
- id: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TString, _$alepha.TInteger]>>;
918
- count: _$alepha.TOptional<_$alepha.TNumber>;
1227
+ response: _$typebox.TObject<{
1228
+ ok: _$typebox.TBoolean;
1229
+ id: _$typebox.TOptional<_$typebox.TUnion<[_$typebox.TString, _$typebox.TInteger]>>;
1230
+ count: _$typebox.TOptional<_$typebox.TNumber>;
919
1231
  }>;
920
1232
  }>;
921
1233
  }
922
1234
  //#endregion
923
- //#region ../../src/api/jobs/entities/jobExecutionEntity.d.ts
1235
+ //#region ../../src/api/jobs/providers/DirectJobDispatcher.d.ts
924
1236
  /**
925
- * Job execution record.
1237
+ * Default `JobDispatcher` for environments without `AlephaApiJobsQueue`.
926
1238
  *
927
- * Stores durable state for queue-mode jobs (outbox pattern) and error records
928
- * for cron-mode jobs. Successful executions are trimmed by the sweep to keep
929
- * the last N rows per job (configurable via `jobConfig.keepLastSuccess`).
1239
+ * Runs `JobProvider.processExecution` in the background the caller's
1240
+ * `push()` returns immediately while the handler continues to completion
1241
+ * in the same process. The DB outbox row is the durability guarantee:
1242
+ * if the process dies before the handler finishes, the next sweep tick
1243
+ * picks the row up and re-dispatches.
930
1244
  *
931
- * Status transitions:
932
- * - queue push → pending
933
- * - worker claim → running
934
- * - success → ok
935
- * - terminal failure → error
936
- * - retry → scheduled (with scheduledAt = now + backoff)
937
- * - delay → scheduled (with scheduledAt = now + delay)
938
- * - sweep picks due ones → pending
939
- * - cancel → cancelled
1245
+ * **Cloudflare Workers** — when an `executionCtx.waitUntil` is available
1246
+ * in the alepha store at `cloudflare.waitUntil`, the dispatch wraps the
1247
+ * background promise with `waitUntil` so the runtime keeps the isolate
1248
+ * alive past the HTTP response. Without this, the handler would be
1249
+ * terminated when the response is returned and only the next sweep
1250
+ * (every 5 min by default) would re-dispatch.
1251
+ *
1252
+ * **Vercel / single-Node** on long-running runtimes the event loop
1253
+ * keeps the promise alive naturally; no special wiring is required.
940
1254
  */
941
- declare const jobExecutionEntity: _$alepha_orm0.EntityPrimitive<_$alepha.TObject<{
942
- id: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_PRIMARY_KEY>, typeof _$alepha_orm0.PG_DEFAULT>;
943
- createdAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_CREATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
944
- updatedAt: _$alepha_orm0.PgAttr<_$alepha_orm0.PgAttr<_$alepha.TString, typeof _$alepha_orm0.PG_UPDATED_AT>, typeof _$alepha_orm0.PG_DEFAULT>;
945
- jobName: _$alepha.TString;
946
- key: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TNull, _$alepha.TString]>>;
947
- status: _$alepha_orm0.PgAttr<_$alepha.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof _$alepha_orm0.PG_DEFAULT>;
948
- priority: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
949
- attempt: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
950
- maxAttempts: _$alepha_orm0.PgAttr<_$alepha.TInteger, typeof _$alepha_orm0.PG_DEFAULT>;
951
- payload: _$alepha.TOptional<_$alepha.TRecord<"^.*$", _$alepha.TAny>>;
952
- scheduledAt: _$alepha.TOptional<_$alepha.TString>;
953
- startedAt: _$alepha.TOptional<_$alepha.TString>;
954
- completedAt: _$alepha.TOptional<_$alepha.TString>;
955
- error: _$alepha.TOptional<_$alepha.TString>;
956
- logs: _$alepha.TOptional<_$alepha.TArray<_$alepha.TObject<{
957
- level: _$alepha.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
958
- message: _$alepha.TString;
959
- service: _$alepha.TString;
960
- module: _$alepha.TString;
961
- context: _$alepha.TOptional<_$alepha.TString>;
962
- app: _$alepha.TOptional<_$alepha.TString>;
963
- data: _$alepha.TOptional<_$alepha.TAny>;
964
- timestamp: _$alepha.TNumber;
965
- }>>>;
966
- triggeredBy: _$alepha.TOptional<_$alepha.TString>;
967
- triggeredByName: _$alepha.TOptional<_$alepha.TString>;
968
- cancelledBy: _$alepha.TOptional<_$alepha.TString>;
969
- cancelledByName: _$alepha.TOptional<_$alepha.TString>;
970
- }>>;
971
- type JobExecutionEntity = Static<typeof jobExecutionEntity.schema>;
972
- type JobStatus = "pending" | "running" | "scheduled" | "ok" | "error" | "cancelled";
1255
+ declare class DirectJobDispatcher extends JobDispatcher {
1256
+ readonly kind: "direct";
1257
+ protected readonly alepha: Alepha;
1258
+ protected readonly log: _$alepha_logger0.Logger;
1259
+ protected jobProviderRef?: JobProvider;
1260
+ protected getJobProvider(): JobProvider;
1261
+ dispatch(jobName: string, executionId: string): Promise<void>;
1262
+ }
973
1263
  //#endregion
974
1264
  //#region ../../src/api/jobs/providers/JobQueueProvider.d.ts
975
1265
  /**
976
- * Plumbs outbox-style dispatch through `AlephaQueue`.
1266
+ * Queue-backed `JobDispatcher` registered by `AlephaApiJobsQueue`.
1267
+ *
1268
+ * Extends {@link JobDispatcher} and substitutes the default
1269
+ * `DirectJobDispatcher` so that `$job.push()` is delivered through
1270
+ * `AlephaQueue` (e.g. Cloudflare Queues, Redis, in-memory) instead of
1271
+ * being processed in-process.
977
1272
  *
978
- * Registered only when the app imports `AlephaApiJobsQueue`. Sets
979
- * `JobProvider.queueDispatch` eagerly at instantiation so queue-mode jobs
980
- * can dispatch regardless of start-hook ordering.
1273
+ * The class is also kept as a `JobQueueProvider` export name for backwards
1274
+ * compatibility it has always been the queue path's entry point.
981
1275
  */
982
- declare class JobQueueProvider {
983
- protected readonly jobProvider: JobProvider;
984
- protected readonly queue: _$alepha_queue0.QueuePrimitive<_$alepha.TObject<{
985
- jobName: _$alepha.TString;
986
- executionId: _$alepha.TString;
1276
+ declare class JobQueueProvider extends JobDispatcher {
1277
+ readonly kind: "queue";
1278
+ protected readonly alepha: Alepha;
1279
+ protected jobProviderRef?: JobProvider;
1280
+ protected getJobProvider(): JobProvider;
1281
+ protected readonly queue: _$alepha_queue0.QueuePrimitive<_$typebox.TObject<{
1282
+ jobName: _$typebox.TString;
1283
+ executionId: _$typebox.TString;
987
1284
  }>>;
988
- constructor();
989
- protected wireDispatcher(): void;
1285
+ dispatch(jobName: string, executionId: string): Promise<void>;
1286
+ /**
1287
+ * Fan-out to a single variadic `queue.push(...payloads)` call so the
1288
+ * underlying queue provider can batch the network round-trips when it
1289
+ * supports it (Cloudflare Queues, Redis pipelines).
1290
+ */
1291
+ dispatchMany(items: Array<{
1292
+ jobName: string;
1293
+ executionId: string;
1294
+ }>): Promise<void>;
1295
+ /**
1296
+ * Backwards-compatible alias for {@link dispatch}. Older code paths called
1297
+ * `JobQueueProvider.push(jobName, executionId)` directly; new code should
1298
+ * go through the `JobDispatcher.dispatch` API.
1299
+ */
990
1300
  push(jobName: string, executionId: string): Promise<void>;
991
1301
  }
992
1302
  //#endregion
993
1303
  //#region ../../src/api/jobs/schemas/jobConfigAtom.d.ts
994
- declare const jobConfig: _$alepha.Atom<_$alepha.TObject<{
995
- sweepInterval: _$alepha.TInteger;
996
- staleThreshold: _$alepha.TInteger;
997
- runTimeout: _$alepha.TInteger;
998
- keepLastSuccess: _$alepha.TInteger;
999
- keepLastError: _$alepha.TInteger;
1000
- logMaxEntries: _$alepha.TInteger;
1001
- drainTimeout: _$alepha.TInteger;
1304
+ declare const jobConfig: _$alepha.Atom<_$typebox.TObject<{
1305
+ sweepCron: _$typebox.TString;
1306
+ trimCron: _$typebox.TString;
1307
+ staleThreshold: _$typebox.TInteger;
1308
+ runTimeout: _$typebox.TInteger;
1309
+ keepLastSuccess: _$typebox.TInteger;
1310
+ keepLastError: _$typebox.TInteger;
1311
+ logMaxEntries: _$typebox.TInteger;
1312
+ drainTimeout: _$typebox.TInteger;
1002
1313
  }>, "alepha.jobs">;
1003
1314
  type JobConfig = Static<typeof jobConfig.schema>;
1004
1315
  declare module "alepha" {
@@ -1007,46 +1318,9 @@ declare module "alepha" {
1007
1318
  }
1008
1319
  } //# sourceMappingURL=jobConfigAtom.d.ts.map
1009
1320
  //#endregion
1010
- //#region ../../src/api/jobs/schemas/jobExecutionResourceSchema.d.ts
1011
- declare const jobExecutionResourceSchema: _$alepha.TObject<{
1012
- id: PgAttr<PgAttr<_$alepha.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
1013
- createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
1014
- updatedAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
1015
- jobName: _$alepha.TString;
1016
- key: _$alepha.TOptional<_$alepha.TUnion<[_$alepha.TNull, _$alepha.TString]>>;
1017
- status: PgAttr<_$alepha.TUnsafe<"pending" | "running" | "scheduled" | "ok" | "error" | "cancelled">, typeof PG_DEFAULT>;
1018
- priority: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
1019
- attempt: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
1020
- maxAttempts: PgAttr<_$alepha.TInteger, typeof PG_DEFAULT>;
1021
- payload: _$alepha.TOptional<_$alepha.TRecord<"^.*$", _$alepha.TAny>>;
1022
- scheduledAt: _$alepha.TOptional<_$alepha.TString>;
1023
- startedAt: _$alepha.TOptional<_$alepha.TString>;
1024
- completedAt: _$alepha.TOptional<_$alepha.TString>;
1025
- error: _$alepha.TOptional<_$alepha.TString>;
1026
- logs: _$alepha.TOptional<_$alepha.TArray<_$alepha.TObject<{
1027
- level: _$alepha.TUnsafe<"SILENT" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR">;
1028
- message: _$alepha.TString;
1029
- service: _$alepha.TString;
1030
- module: _$alepha.TString;
1031
- context: _$alepha.TOptional<_$alepha.TString>;
1032
- app: _$alepha.TOptional<_$alepha.TString>;
1033
- data: _$alepha.TOptional<_$alepha.TAny>;
1034
- timestamp: _$alepha.TNumber;
1035
- }>>>;
1036
- triggeredBy: _$alepha.TOptional<_$alepha.TString>;
1037
- triggeredByName: _$alepha.TOptional<_$alepha.TString>;
1038
- cancelledBy: _$alepha.TOptional<_$alepha.TString>;
1039
- cancelledByName: _$alepha.TOptional<_$alepha.TString>;
1040
- can: _$alepha.TObject<{
1041
- retry: _$alepha.TBoolean;
1042
- cancel: _$alepha.TBoolean;
1043
- }>;
1044
- }>;
1045
- type JobExecutionResource = Static<typeof jobExecutionResourceSchema>;
1046
- //#endregion
1047
1321
  //#region ../../src/api/jobs/schemas/triggerJobSchema.d.ts
1048
- declare const triggerJobSchema: _$alepha.TObject<{
1049
- payload: _$alepha.TOptional<_$alepha.TRecord<"^.*$", _$alepha.TAny>>;
1322
+ declare const triggerJobSchema: _$typebox.TObject<{
1323
+ payload: _$typebox.TOptional<_$typebox.TRecord<"^.*$", _$typebox.TAny>>;
1050
1324
  }>;
1051
1325
  type TriggerJob = Static<typeof triggerJobSchema>;
1052
1326
  //#endregion
@@ -1080,27 +1354,59 @@ declare module "alepha" {
1080
1354
  /**
1081
1355
  * Job execution framework — cron and durable queue work with a single primitive.
1082
1356
  *
1083
- * A `$job` is either **cron-only** (declares `cron`) or **queue-only** (declares `schema`).
1084
- * Cron jobs run inline on their schedule and only record errors by default.
1085
- * Queue jobs use the outbox pattern: push commits to DB first, then notifies via queue.
1357
+ * A `$job` is either **cron-only** (declares `cron`) or **payload-only** (declares `schema`).
1358
+ *
1359
+ * **Three runtime modes:**
1360
+ *
1361
+ * - **cron** — fires on a schedule. Cron-mode jobs are protected by a
1362
+ * distributed lock by default (`lock: true`), so multi-replica Docker
1363
+ * deployments only run the handler once per tick. Override with
1364
+ * `lock: false` if you genuinely want every replica to fire.
1365
+ * - **queue** — push-driven, dispatched through the queue infrastructure
1366
+ * (`AlephaQueue`, e.g. Cloudflare Queues, Redis). Real-time delivery,
1367
+ * ideal for high-volume systems. Requires `AlephaApiJobsQueue`.
1368
+ * - **direct** — push-driven, processed in-process right after the caller
1369
+ * awaits the push. The DB outbox row is the durability guarantee — if
1370
+ * the process dies, the reconciliation sweep re-dispatches. Default
1371
+ * when `AlephaApiJobsQueue` is *not* loaded. Best for cheap deployments
1372
+ * (Cloudflare Workers, single-instance Node) where standing up a queue
1373
+ * is overkill.
1374
+ *
1375
+ * **Retries** are sweep-driven across all modes (no exponential backoff).
1376
+ * Granularity is bounded by `sweepCron` (default 5 min). The first retry
1377
+ * may land anywhere from a few seconds to ~5 min later depending on when
1378
+ * the next sweep tick fires. Cron jobs that declare `retry` go through
1379
+ * the same sweep path — a transient failure no longer means waiting for
1380
+ * the next cron tick (useful for once-daily jobs).
1381
+ *
1382
+ * **Runtime support for cron triggers**
1086
1383
  *
1087
- * **This module provides cron support only.** To enable queue-mode jobs, also
1088
- * import {@link AlephaApiJobsQueue} it brings in the queue layer and infrastructure
1089
- * binding (e.g. Cloudflare Queues). Cron-only deployments (Vercel, CF-without-Queues)
1090
- * do not need `AlephaApiJobsQueue`.
1384
+ * - **Long-running Node / Docker** `CronProvider` runs an in-process
1385
+ * timer loop. Multi-replica deployments serialize ticks via the cron
1386
+ * lock (see `$job.lock`).
1387
+ * - **Cloudflare Workers** — the build emits cron expressions into
1388
+ * `wrangler.jsonc`; Cloudflare invokes the worker on schedule and the
1389
+ * `cloudflare:scheduled` hook routes the event to the matching jobs.
1390
+ * - **Vercel** — the build emits cron entries into
1391
+ * `.vercel/output/config.json` mapped to `/_alepha/cron/:name`; the
1392
+ * serverless handler emits `serverless:cron` and `CronProvider` runs
1393
+ * the matching job. Set `CRON_SECRET` to require authenticated calls.
1091
1394
  *
1092
1395
  * @module alepha.api.jobs
1093
1396
  */
1094
1397
  declare const AlephaApiJobs: _$alepha.Service<_$alepha.Module>;
1095
1398
  /**
1096
1399
  * Queue support for `$job`. Import alongside {@link AlephaApiJobs} when your
1097
- * app declares queue-mode jobs (any `$job` with a `schema`).
1400
+ * app declares queue-mode jobs (any `$job` with a `schema`) and you want a
1401
+ * real queue (e.g. Cloudflare Queues, Redis) instead of in-process direct
1402
+ * execution.
1098
1403
  *
1099
- * Adds `JobQueueProvider` which plumbs the outbox dispatch through `AlephaQueue`.
1404
+ * Adds `JobQueueProvider` to the container. `JobProvider` detects its
1405
+ * presence at start-up and routes dispatches through it.
1100
1406
  *
1101
1407
  * @module alepha.api.jobs.queue
1102
1408
  */
1103
1409
  declare const AlephaApiJobsQueue: _$alepha.Service<_$alepha.Module>;
1104
1410
  //#endregion
1105
- export { $job, AdminJobController, AlephaApiJobs, AlephaApiJobsQueue, CancelContext, JobConfig, JobExecutionEntity, JobExecutionQuery, JobExecutionResource, JobHandlerArgs, JobPrimitive, JobPrimitiveOptions, JobPriority, JobProvider, JobQueueProvider, JobRegistration, JobRetryBackoff, JobRetryOptions, JobService, JobStatus, JobTriggerContext, PRIORITY_MAP, PRIORITY_REVERSE, PushManyItem, PushOptions, TriggerJob, jobConfig, jobExecutionEntity, jobExecutionQuerySchema, jobExecutionResourceSchema, jobRegistrationSchema, triggerJobSchema };
1411
+ export { $job, AdminJobController, AlephaApiJobs, AlephaApiJobsQueue, CancelContext, DirectJobDispatcher, JobConfig, JobDispatcher, JobEffectiveMode, JobExecutionEntity, JobExecutionQuery, JobExecutionResource, JobHandlerArgs, JobPrimitive, JobPrimitiveOptions, JobPriority, JobProvider, JobQueueProvider, JobRegistration, JobRetryOptions, JobService, JobStatus, JobTriggerContext, PRIORITY_MAP, PRIORITY_REVERSE, PushManyItem, PushOptions, TriggerJob, jobConfig, jobExecutionEntity, jobExecutionQuerySchema, jobExecutionResourceSchema, jobRegistrationSchema, triggerJobSchema };
1106
1412
  //# sourceMappingURL=index.d.ts.map