@relkit/providers-local 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/dist/buckets/index.d.ts +5 -0
  4. package/dist/buckets/index.d.ts.map +1 -0
  5. package/dist/buckets/index.js +5 -0
  6. package/dist/buckets/index.js.map +1 -0
  7. package/dist/buckets/keys.d.ts +7 -0
  8. package/dist/buckets/keys.d.ts.map +1 -0
  9. package/dist/buckets/keys.js +60 -0
  10. package/dist/buckets/keys.js.map +1 -0
  11. package/dist/buckets/operations.d.ts +11 -0
  12. package/dist/buckets/operations.d.ts.map +1 -0
  13. package/dist/buckets/operations.js +89 -0
  14. package/dist/buckets/operations.js.map +1 -0
  15. package/dist/buckets/pagination.d.ts +5 -0
  16. package/dist/buckets/pagination.d.ts.map +1 -0
  17. package/dist/buckets/pagination.js +34 -0
  18. package/dist/buckets/pagination.js.map +1 -0
  19. package/dist/buckets/policy.d.ts +8 -0
  20. package/dist/buckets/policy.d.ts.map +1 -0
  21. package/dist/buckets/policy.js +74 -0
  22. package/dist/buckets/policy.js.map +1 -0
  23. package/dist/buckets/provider.d.ts +4 -0
  24. package/dist/buckets/provider.d.ts.map +1 -0
  25. package/dist/buckets/provider.js +119 -0
  26. package/dist/buckets/provider.js.map +1 -0
  27. package/dist/buckets/storage.d.ts +12 -0
  28. package/dist/buckets/storage.d.ts.map +1 -0
  29. package/dist/buckets/storage.js +169 -0
  30. package/dist/buckets/storage.js.map +1 -0
  31. package/dist/buckets/types.d.ts +91 -0
  32. package/dist/buckets/types.d.ts.map +1 -0
  33. package/dist/buckets/types.js +34 -0
  34. package/dist/buckets/types.js.map +1 -0
  35. package/dist/cache/index.d.ts +8 -0
  36. package/dist/cache/index.d.ts.map +1 -0
  37. package/dist/cache/index.js +8 -0
  38. package/dist/cache/index.js.map +1 -0
  39. package/dist/cache/inspector.d.ts +4 -0
  40. package/dist/cache/inspector.d.ts.map +1 -0
  41. package/dist/cache/inspector.js +62 -0
  42. package/dist/cache/inspector.js.map +1 -0
  43. package/dist/cache/keys.d.ts +6 -0
  44. package/dist/cache/keys.d.ts.map +1 -0
  45. package/dist/cache/keys.js +34 -0
  46. package/dist/cache/keys.js.map +1 -0
  47. package/dist/cache/persistence.d.ts +5 -0
  48. package/dist/cache/persistence.d.ts.map +1 -0
  49. package/dist/cache/persistence.js +108 -0
  50. package/dist/cache/persistence.js.map +1 -0
  51. package/dist/cache/policy.d.ts +9 -0
  52. package/dist/cache/policy.d.ts.map +1 -0
  53. package/dist/cache/policy.js +64 -0
  54. package/dist/cache/policy.js.map +1 -0
  55. package/dist/cache/provider.d.ts +3 -0
  56. package/dist/cache/provider.d.ts.map +1 -0
  57. package/dist/cache/provider.js +164 -0
  58. package/dist/cache/provider.js.map +1 -0
  59. package/dist/cache/store.d.ts +44 -0
  60. package/dist/cache/store.d.ts.map +1 -0
  61. package/dist/cache/store.js +132 -0
  62. package/dist/cache/store.js.map +1 -0
  63. package/dist/cache/types.d.ts +100 -0
  64. package/dist/cache/types.d.ts.map +1 -0
  65. package/dist/cache/types.js +39 -0
  66. package/dist/cache/types.js.map +1 -0
  67. package/dist/cache/write.d.ts +5 -0
  68. package/dist/cache/write.d.ts.map +1 -0
  69. package/dist/cache/write.js +13 -0
  70. package/dist/cache/write.js.map +1 -0
  71. package/dist/events/admin-actions.d.ts +7 -0
  72. package/dist/events/admin-actions.d.ts.map +1 -0
  73. package/dist/events/admin-actions.js +28 -0
  74. package/dist/events/admin-actions.js.map +1 -0
  75. package/dist/events/admin-contracts.d.ts +132 -0
  76. package/dist/events/admin-contracts.d.ts.map +1 -0
  77. package/dist/events/admin-contracts.js +4 -0
  78. package/dist/events/admin-contracts.js.map +1 -0
  79. package/dist/events/admin-errors.d.ts +5 -0
  80. package/dist/events/admin-errors.d.ts.map +1 -0
  81. package/dist/events/admin-errors.js +9 -0
  82. package/dist/events/admin-errors.js.map +1 -0
  83. package/dist/events/admin-state.d.ts +8 -0
  84. package/dist/events/admin-state.d.ts.map +1 -0
  85. package/dist/events/admin-state.js +10 -0
  86. package/dist/events/admin-state.js.map +1 -0
  87. package/dist/events/admin-utils.d.ts +27 -0
  88. package/dist/events/admin-utils.d.ts.map +1 -0
  89. package/dist/events/admin-utils.js +153 -0
  90. package/dist/events/admin-utils.js.map +1 -0
  91. package/dist/events/admin.d.ts +22 -0
  92. package/dist/events/admin.d.ts.map +1 -0
  93. package/dist/events/admin.js +92 -0
  94. package/dist/events/admin.js.map +1 -0
  95. package/dist/events/delivery-types.d.ts +74 -0
  96. package/dist/events/delivery-types.d.ts.map +1 -0
  97. package/dist/events/delivery-types.js +9 -0
  98. package/dist/events/delivery-types.js.map +1 -0
  99. package/dist/events/delivery-utils.d.ts +17 -0
  100. package/dist/events/delivery-utils.d.ts.map +1 -0
  101. package/dist/events/delivery-utils.js +133 -0
  102. package/dist/events/delivery-utils.js.map +1 -0
  103. package/dist/events/delivery.d.ts +6 -0
  104. package/dist/events/delivery.d.ts.map +1 -0
  105. package/dist/events/delivery.js +159 -0
  106. package/dist/events/delivery.js.map +1 -0
  107. package/dist/events/ephemeral.d.ts +36 -0
  108. package/dist/events/ephemeral.d.ts.map +1 -0
  109. package/dist/events/ephemeral.js +61 -0
  110. package/dist/events/ephemeral.js.map +1 -0
  111. package/dist/events/log.d.ts +37 -0
  112. package/dist/events/log.d.ts.map +1 -0
  113. package/dist/events/log.js +121 -0
  114. package/dist/events/log.js.map +1 -0
  115. package/dist/events/provider.d.ts +9 -0
  116. package/dist/events/provider.d.ts.map +1 -0
  117. package/dist/events/provider.js +37 -0
  118. package/dist/events/provider.js.map +1 -0
  119. package/dist/events/router-inspection.d.ts +18 -0
  120. package/dist/events/router-inspection.d.ts.map +1 -0
  121. package/dist/events/router-inspection.js +110 -0
  122. package/dist/events/router-inspection.js.map +1 -0
  123. package/dist/events/router-records.d.ts +34 -0
  124. package/dist/events/router-records.d.ts.map +1 -0
  125. package/dist/events/router-records.js +98 -0
  126. package/dist/events/router-records.js.map +1 -0
  127. package/dist/events/router-types.d.ts +83 -0
  128. package/dist/events/router-types.d.ts.map +1 -0
  129. package/dist/events/router-types.js +2 -0
  130. package/dist/events/router-types.js.map +1 -0
  131. package/dist/events/router.d.ts +7 -0
  132. package/dist/events/router.d.ts.map +1 -0
  133. package/dist/events/router.js +148 -0
  134. package/dist/events/router.js.map +1 -0
  135. package/dist/factory.d.ts +26 -0
  136. package/dist/factory.d.ts.map +1 -0
  137. package/dist/factory.js +66 -0
  138. package/dist/factory.js.map +1 -0
  139. package/dist/index.d.ts +18 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +15 -0
  142. package/dist/index.js.map +1 -0
  143. package/dist/jobs/admin-contracts.d.ts +66 -0
  144. package/dist/jobs/admin-contracts.d.ts.map +1 -0
  145. package/dist/jobs/admin-contracts.js +4 -0
  146. package/dist/jobs/admin-contracts.js.map +1 -0
  147. package/dist/jobs/admin-errors.d.ts +5 -0
  148. package/dist/jobs/admin-errors.d.ts.map +1 -0
  149. package/dist/jobs/admin-errors.js +9 -0
  150. package/dist/jobs/admin-errors.js.map +1 -0
  151. package/dist/jobs/admin-utils.d.ts +29 -0
  152. package/dist/jobs/admin-utils.d.ts.map +1 -0
  153. package/dist/jobs/admin-utils.js +138 -0
  154. package/dist/jobs/admin-utils.js.map +1 -0
  155. package/dist/jobs/admin.d.ts +25 -0
  156. package/dist/jobs/admin.d.ts.map +1 -0
  157. package/dist/jobs/admin.js +89 -0
  158. package/dist/jobs/admin.js.map +1 -0
  159. package/dist/jobs/cron.d.ts +10 -0
  160. package/dist/jobs/cron.d.ts.map +1 -0
  161. package/dist/jobs/cron.js +18 -0
  162. package/dist/jobs/cron.js.map +1 -0
  163. package/dist/jobs/idempotency.d.ts +18 -0
  164. package/dist/jobs/idempotency.d.ts.map +1 -0
  165. package/dist/jobs/idempotency.js +82 -0
  166. package/dist/jobs/idempotency.js.map +1 -0
  167. package/dist/jobs/lease-utils.d.ts +9 -0
  168. package/dist/jobs/lease-utils.d.ts.map +1 -0
  169. package/dist/jobs/lease-utils.js +31 -0
  170. package/dist/jobs/lease-utils.js.map +1 -0
  171. package/dist/jobs/queue-admin.d.ts +12 -0
  172. package/dist/jobs/queue-admin.d.ts.map +1 -0
  173. package/dist/jobs/queue-admin.js +42 -0
  174. package/dist/jobs/queue-admin.js.map +1 -0
  175. package/dist/jobs/queue-entry.d.ts +8 -0
  176. package/dist/jobs/queue-entry.d.ts.map +1 -0
  177. package/dist/jobs/queue-entry.js +130 -0
  178. package/dist/jobs/queue-entry.js.map +1 -0
  179. package/dist/jobs/queue-lease.d.ts +4 -0
  180. package/dist/jobs/queue-lease.d.ts.map +1 -0
  181. package/dist/jobs/queue-lease.js +12 -0
  182. package/dist/jobs/queue-lease.js.map +1 -0
  183. package/dist/jobs/queue-operations.d.ts +16 -0
  184. package/dist/jobs/queue-operations.d.ts.map +1 -0
  185. package/dist/jobs/queue-operations.js +107 -0
  186. package/dist/jobs/queue-operations.js.map +1 -0
  187. package/dist/jobs/queue-recovery.d.ts +5 -0
  188. package/dist/jobs/queue-recovery.d.ts.map +1 -0
  189. package/dist/jobs/queue-recovery.js +22 -0
  190. package/dist/jobs/queue-recovery.js.map +1 -0
  191. package/dist/jobs/queue-utils.d.ts +101 -0
  192. package/dist/jobs/queue-utils.d.ts.map +1 -0
  193. package/dist/jobs/queue-utils.js +28 -0
  194. package/dist/jobs/queue-utils.js.map +1 -0
  195. package/dist/jobs/queue.d.ts +7 -0
  196. package/dist/jobs/queue.d.ts.map +1 -0
  197. package/dist/jobs/queue.js +70 -0
  198. package/dist/jobs/queue.js.map +1 -0
  199. package/dist/jobs/retry.d.ts +25 -0
  200. package/dist/jobs/retry.d.ts.map +1 -0
  201. package/dist/jobs/retry.js +84 -0
  202. package/dist/jobs/retry.js.map +1 -0
  203. package/dist/jobs/scheduler.d.ts +52 -0
  204. package/dist/jobs/scheduler.d.ts.map +1 -0
  205. package/dist/jobs/scheduler.js +122 -0
  206. package/dist/jobs/scheduler.js.map +1 -0
  207. package/dist/jobs/store-files.d.ts +20 -0
  208. package/dist/jobs/store-files.d.ts.map +1 -0
  209. package/dist/jobs/store-files.js +177 -0
  210. package/dist/jobs/store-files.js.map +1 -0
  211. package/dist/jobs/store.d.ts +60 -0
  212. package/dist/jobs/store.d.ts.map +1 -0
  213. package/dist/jobs/store.js +97 -0
  214. package/dist/jobs/store.js.map +1 -0
  215. package/dist/runtime-capabilities.d.ts +17 -0
  216. package/dist/runtime-capabilities.d.ts.map +1 -0
  217. package/dist/runtime-capabilities.js +32 -0
  218. package/dist/runtime-capabilities.js.map +1 -0
  219. package/dist/state.d.ts +15 -0
  220. package/dist/state.d.ts.map +1 -0
  221. package/dist/state.js +69 -0
  222. package/dist/state.js.map +1 -0
  223. package/package.json +47 -0
@@ -0,0 +1,89 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { normalizeId } from "@relkit/contracts";
3
+ import { JobAdminError } from "./admin-errors.js";
4
+ import { JOB_ADMIN_PROTOCOL, JOB_ADMIN_VERSION, } from "./admin-contracts.js";
5
+ import { afterCursor, assertMode, assertVersion, cursor, failureFor, makeRecord, matches, pageLimit, readReason, recordAction, safeError, safeId, safeReason, toStatus, validateQuery, versioned, } from "./admin-utils.js";
6
+ export * from "./admin-contracts.js";
7
+ export { JobAdminError } from "./admin-errors.js";
8
+ /** Exposes versioned local job inspection and explicitly audited mutations. */
9
+ export function createJobAdmin(queue, options = {}) {
10
+ const mode = options.environment ?? options.mode ?? "development";
11
+ assertMode(mode);
12
+ const enabled = options.enabled ?? mode !== "production";
13
+ const records = [];
14
+ const status = (instanceId) => {
15
+ const entry = queue.get(normalizeId(instanceId));
16
+ return entry === undefined ? undefined : toStatus(entry);
17
+ };
18
+ const query = (request = {}) => {
19
+ assertVersion(request);
20
+ validateQuery(request);
21
+ const entries = queue
22
+ .snapshot()
23
+ .filter((entry) => matches(entry, request))
24
+ .filter((entry) => afterCursor(entry, request.cursor));
25
+ const limit = pageLimit(request.limit);
26
+ const page = entries.slice(0, limit).map(toStatus);
27
+ const next = entries.length > limit ? entries[limit - 1] : undefined;
28
+ return versioned({
29
+ items: Object.freeze(page),
30
+ counts: queue.counts(),
31
+ ...(next === undefined ? {} : { nextCursor: cursor(next) }),
32
+ });
33
+ };
34
+ const actions = () => Object.freeze([...records]);
35
+ const run = (action, request) => applyAction(action, request, {
36
+ queue,
37
+ mode,
38
+ enabled,
39
+ now: options.now ?? Date.now,
40
+ createActionId: options.createActionId ?? randomUUID,
41
+ ...(options.onAction === undefined ? {} : { onAction: options.onAction }),
42
+ records,
43
+ });
44
+ return Object.freeze({
45
+ protocol: JOB_ADMIN_PROTOCOL,
46
+ version: JOB_ADMIN_VERSION,
47
+ status,
48
+ query,
49
+ retry: (request) => run("retry", request),
50
+ cancel: (request) => run("cancel", request),
51
+ deadLetter: (request) => run("dead-letter", request),
52
+ actions,
53
+ });
54
+ }
55
+ async function applyAction(action, input, options) {
56
+ const request = typeof input === "string" ? { instanceId: input } : input;
57
+ const instanceId = safeId(request?.instanceId);
58
+ const actionId = safeId(options.createActionId()) ?? "invalid-action";
59
+ const requestedAt = options.now();
60
+ const before = instanceId === undefined ? undefined : options.queue.get(instanceId);
61
+ try {
62
+ assertVersion(request);
63
+ const reason = readReason(request);
64
+ if (!options.enabled || options.mode === "production")
65
+ throw new JobAdminError("RELKIT_JOB_ADMIN_MUTATION_DISABLED", "Local job mutations are disabled");
66
+ if (instanceId === undefined)
67
+ throw new JobAdminError("RELKIT_JOB_ADMIN_INSTANCE_INVALID", "Job instance ID is invalid");
68
+ if (before === undefined)
69
+ throw new JobAdminError("RELKIT_JOB_ADMIN_NOT_FOUND", `Job ${instanceId} is unknown`);
70
+ if (action === "retry") {
71
+ if (before.state !== "dead-lettered")
72
+ throw new JobAdminError("RELKIT_JOB_ADMIN_STATE_INELIGIBLE", "Only dead-lettered jobs can be retried");
73
+ }
74
+ else if (before.state === "completed" || before.state === "dead-lettered") {
75
+ throw new JobAdminError("RELKIT_JOB_ADMIN_STATE_INELIGIBLE", "Job state cannot be changed by this action");
76
+ }
77
+ const after = action === "retry"
78
+ ? await options.queue.adminRetry(instanceId)
79
+ : await options.queue.adminDeadLetter(instanceId, failureFor(action));
80
+ const record = await recordAction(options, makeRecord(action, actionId, instanceId, requestedAt, "applied", options.mode, before, after, undefined, reason));
81
+ return versioned({ action, status: toStatus(after), record });
82
+ }
83
+ catch (cause) {
84
+ const error = safeError(cause);
85
+ const record = await recordAction(options, makeRecord(action, actionId, instanceId ?? "invalid", requestedAt, "rejected", options.mode, before, undefined, error.code, safeReason(request)));
86
+ throw Object.assign(error, { action: record });
87
+ }
88
+ }
89
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/jobs/admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,GAUlB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,WAAW,EACX,UAAU,EACV,aAAa,EACb,MAAM,EACN,UAAU,EACV,UAAU,EACV,OAAO,EACP,SAAS,EACT,UAAU,EACV,YAAY,EACZ,SAAS,EACT,MAAM,EACN,UAAU,EACV,QAAQ,EACR,aAAa,EACb,SAAS,GACV,MAAM,kBAAkB,CAAC;AAE1B,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAsBlD,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,KAAe,EAAE,UAA2B,EAAE;IAC3E,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,IAAI,aAAa,CAAC;IAClE,UAAU,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,KAAK,YAAY,CAAC;IACzD,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,UAAkB,EAAiC,EAAE;QACnE,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;QACjD,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,UAA2B,EAAE,EAAoB,EAAE;QAChE,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,MAAM,OAAO,GAAG,KAAK;aAClB,QAAQ,EAAE;aACV,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;aAC1C,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrE,OAAO,SAAS,CAAC;YACf,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;YAC1B,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;YACtB,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;SAC5D,CAAC,CAAC;IACL,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,GAAoC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACnF,MAAM,GAAG,GAAG,CAAC,MAAsB,EAAE,OAAkC,EAAE,EAAE,CACzE,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE;QAC3B,KAAK;QACL,IAAI;QACJ,OAAO;QACP,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG;QAC5B,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,UAAU;QACpD,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzE,OAAO;KACR,CAAC,CAAC;IACL,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,iBAAiB;QAC1B,MAAM;QACN,KAAK;QACL,KAAK,EAAE,CAAC,OAAkC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;QACpE,MAAM,EAAE,CAAC,OAAkC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC;QACtE,UAAU,EAAE,CAAC,OAAkC,EAAE,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC;QAC/E,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,MAAsB,EACtB,KAAgC,EAChC,OAQC;IAED,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC1E,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,IAAI,gBAAgB,CAAC;IACtE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACpF,IAAI,CAAC;QACH,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY;YACnD,MAAM,IAAI,aAAa,CACrB,oCAAoC,EACpC,kCAAkC,CACnC,CAAC;QACJ,IAAI,UAAU,KAAK,SAAS;YAC1B,MAAM,IAAI,aAAa,CAAC,mCAAmC,EAAE,4BAA4B,CAAC,CAAC;QAC7F,IAAI,MAAM,KAAK,SAAS;YACtB,MAAM,IAAI,aAAa,CAAC,4BAA4B,EAAE,OAAO,UAAU,aAAa,CAAC,CAAC;QACxF,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,IAAI,MAAM,CAAC,KAAK,KAAK,eAAe;gBAClC,MAAM,IAAI,aAAa,CACrB,mCAAmC,EACnC,wCAAwC,CACzC,CAAC;QACN,CAAC;aAAM,IAAI,MAAM,CAAC,KAAK,KAAK,WAAW,IAAI,MAAM,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;YAC5E,MAAM,IAAI,aAAa,CACrB,mCAAmC,EACnC,4CAA4C,CAC7C,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GACT,MAAM,KAAK,OAAO;YAChB,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC;YAC5C,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,OAAO,EACP,UAAU,CACR,MAAM,EACN,QAAQ,EACR,UAAU,EACV,WAAW,EACX,SAAS,EACT,OAAO,CAAC,IAAI,EACZ,MAAM,EACN,KAAK,EACL,SAAS,EACT,MAAM,CACP,CACF,CAAC;QACF,OAAO,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,OAAO,EACP,UAAU,CACR,MAAM,EACN,QAAQ,EACR,UAAU,IAAI,SAAS,EACvB,WAAW,EACX,UAAU,EACV,OAAO,CAAC,IAAI,EACZ,MAAM,EACN,SAAS,EACT,KAAK,CAAC,IAAI,EACV,UAAU,CAAC,OAAO,CAAC,CACpB,CACF,CAAC;QACF,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface CronScheduleOptions {
2
+ readonly timezone: string;
3
+ readonly currentDate: Date;
4
+ }
5
+ /**
6
+ * Returns the next fire time while keeping the parser and its date type
7
+ * private to the local job provider.
8
+ */
9
+ export declare function nextCronFire(expression: string, options: CronScheduleOptions): Date;
10
+ //# sourceMappingURL=cron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAOnF"}
@@ -0,0 +1,18 @@
1
+ import { CronExpressionParser } from "cron-parser";
2
+ /**
3
+ * Returns the next fire time while keeping the parser and its date type
4
+ * private to the local job provider.
5
+ */
6
+ export function nextCronFire(expression, options) {
7
+ const schedule = CronExpressionParser.parse(withSeconds(expression), {
8
+ currentDate: options.currentDate,
9
+ strict: true,
10
+ tz: options.timezone,
11
+ });
12
+ return schedule.next().toDate();
13
+ }
14
+ function withSeconds(expression) {
15
+ const trimmed = expression.trim();
16
+ return trimmed.split(/\s+/).length === 5 ? `0 ${trimmed}` : trimmed;
17
+ }
18
+ //# sourceMappingURL=cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAOnD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,OAA4B;IAC3E,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE;QACnE,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,MAAM,EAAE,IAAI;QACZ,EAAE,EAAE,OAAO,CAAC,QAAQ;KACrB,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB;IACrC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAClC,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AACtE,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { JsonValue } from "@relkit/contracts";
2
+ import { type JobIdempotencyDefinition, type JobIdempotencyRecord, type JobQueueAcceptance, type JobQueueEntry } from "./queue-utils.js";
3
+ export interface IdempotencyPreparation {
4
+ readonly record?: JobIdempotencyRecord;
5
+ readonly duplicate?: JobQueueAcceptance;
6
+ }
7
+ /** Validates the static idempotency policy supplied by a job descriptor. */
8
+ export declare function validateIdempotencyDefinition(value: unknown): JobIdempotencyDefinition;
9
+ /** Extracts and validates the non-empty string value used as a job idempotency key. */
10
+ export declare function extractIdempotencyRecord(input: JsonValue, definition: JobIdempotencyDefinition, acceptedAt: number): JobIdempotencyRecord;
11
+ /** Validates the compact durable record stored alongside its accepted job. */
12
+ export declare function assertIdempotencyRecord(value: JobIdempotencyRecord): void;
13
+ export declare function readIdempotencyRecord(value: JsonValue | undefined): JobIdempotencyRecord | undefined;
14
+ /** Finds the oldest still-retained acceptance for a key. Expired records are ignored. */
15
+ export declare function findActiveIdempotency(entries: Iterable<JobQueueEntry>, key: string, now: number): JobQueueEntry | undefined;
16
+ export declare function prepareIdempotency(input: JsonValue, definition: JobIdempotencyDefinition | undefined, entries: Iterable<JobQueueEntry>, now: number, acceptedAt: number): IdempotencyPreparation;
17
+ export declare function acceptance(entry: JobQueueEntry, duplicate: boolean): JobQueueAcceptance;
18
+ //# sourceMappingURL=idempotency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/jobs/idempotency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED,4EAA4E;AAC5E,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAQtF;AAED,uFAAuF;AACvF,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,wBAAwB,EACpC,UAAU,EAAE,MAAM,GACjB,oBAAoB,CActB;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CASzE;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,GAAG,SAAS,GAC3B,oBAAoB,GAAG,SAAS,CAMlC;AAED,yFAAyF;AACzF,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,aAAa,GAAG,SAAS,CAQ3B;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,wBAAwB,GAAG,SAAS,EAChD,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAKxB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,GAAG,kBAAkB,CAYvF"}
@@ -0,0 +1,82 @@
1
+ import { assertTime, JobQueueStateError, } from "./queue-utils.js";
2
+ /** Validates the static idempotency policy supplied by a job descriptor. */
3
+ export function validateIdempotencyDefinition(value) {
4
+ if (!isRecord(value))
5
+ throw new JobQueueStateError("Idempotency definition is invalid");
6
+ if (typeof value.key !== "string" || value.key.trim() === "")
7
+ throw new JobQueueStateError("Idempotency key field is required");
8
+ const retentionMs = value.retentionMs;
9
+ if (typeof retentionMs !== "number" || !Number.isSafeInteger(retentionMs) || retentionMs < 1)
10
+ throw new JobQueueStateError("Idempotency retention must be a positive integer");
11
+ return Object.freeze({ key: value.key.trim(), retentionMs });
12
+ }
13
+ /** Extracts and validates the non-empty string value used as a job idempotency key. */
14
+ export function extractIdempotencyRecord(input, definition, acceptedAt) {
15
+ const policy = validateIdempotencyDefinition(definition);
16
+ assertTime(acceptedAt, "accepted time");
17
+ if (input === null || typeof input !== "object" || Array.isArray(input))
18
+ throw new JobQueueStateError("Idempotency input must be an object");
19
+ const record = input;
20
+ if (!Object.prototype.hasOwnProperty.call(record, policy.key))
21
+ throw new JobQueueStateError(`Idempotency input is missing "${policy.key}"`);
22
+ const value = record[policy.key];
23
+ if (typeof value !== "string" || value.trim() === "")
24
+ throw new JobQueueStateError(`Idempotency input "${policy.key}" must be non-empty text`);
25
+ if (policy.retentionMs > Number.MAX_SAFE_INTEGER - acceptedAt)
26
+ throw new JobQueueStateError("Idempotency expiry is invalid");
27
+ return Object.freeze({ key: value.trim(), expiresAt: acceptedAt + policy.retentionMs });
28
+ }
29
+ /** Validates the compact durable record stored alongside its accepted job. */
30
+ export function assertIdempotencyRecord(value) {
31
+ if (typeof value.key !== "string" ||
32
+ value.key.trim() === "" ||
33
+ value.key !== value.key.trim() ||
34
+ !Number.isSafeInteger(value.expiresAt) ||
35
+ value.expiresAt < 1)
36
+ throw new JobQueueStateError("Job idempotency record is invalid");
37
+ }
38
+ export function readIdempotencyRecord(value) {
39
+ if (value === undefined)
40
+ return undefined;
41
+ if (!isRecord(value))
42
+ throw new JobQueueStateError("Job idempotency record is invalid");
43
+ const record = value;
44
+ assertIdempotencyRecord(record);
45
+ return record;
46
+ }
47
+ /** Finds the oldest still-retained acceptance for a key. Expired records are ignored. */
48
+ export function findActiveIdempotency(entries, key, now) {
49
+ assertTime(now, "idempotency time");
50
+ let match;
51
+ for (const entry of entries) {
52
+ if (entry.idempotency?.key !== key || entry.idempotency.expiresAt <= now)
53
+ continue;
54
+ if (match === undefined || entry.order < match.order)
55
+ match = entry;
56
+ }
57
+ return match;
58
+ }
59
+ export function prepareIdempotency(input, definition, entries, now, acceptedAt) {
60
+ if (definition === undefined)
61
+ return {};
62
+ const record = extractIdempotencyRecord(input, definition, acceptedAt);
63
+ const duplicate = findActiveIdempotency(entries, record.key, now);
64
+ return duplicate === undefined ? { record } : { duplicate: acceptance(duplicate, true) };
65
+ }
66
+ export function acceptance(entry, duplicate) {
67
+ return Object.freeze({
68
+ ...entry,
69
+ accepted: true,
70
+ duplicate,
71
+ ...(entry.idempotency === undefined
72
+ ? {}
73
+ : {
74
+ idempotencyKey: entry.idempotency.key,
75
+ idempotencyExpiresAt: entry.idempotency.expiresAt,
76
+ }),
77
+ });
78
+ }
79
+ function isRecord(value) {
80
+ return value !== null && typeof value === "object" && !Array.isArray(value);
81
+ }
82
+ //# sourceMappingURL=idempotency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/jobs/idempotency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { JobQueueEntry, JobQueueLeaseOptions, JobQueueTransitionOptions } from "./queue-utils.js";
2
+ export declare const DEFAULT_LEASE_DURATION_MS = 30000;
3
+ export declare function normalizeOwnerToken(value: string): string;
4
+ export declare function resolveLeaseExpiry(now: number, defaultDurationMs: number, options: JobQueueLeaseOptions): number;
5
+ export declare function leaseTransitionOptions(now: number, defaultDurationMs: number, options: JobQueueLeaseOptions, ownerToken: string): JobQueueTransitionOptions;
6
+ export declare function assertLeaseDuration(value: number): void;
7
+ export declare function assertLeaseOwner(entry: JobQueueEntry, ownerToken: string): void;
8
+ export declare function isLeaseExpired(entry: JobQueueEntry, now: number): boolean;
9
+ //# sourceMappingURL=lease-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease-utils.d.ts","sourceRoot":"","sources":["../../src/jobs/lease-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,oBAAoB,GAC5B,MAAM,CAKR;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,MAAM,GACjB,yBAAyB,CAK3B;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGvD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAG/E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAIzE"}
@@ -0,0 +1,31 @@
1
+ import { normalizeId } from "@relkit/contracts";
2
+ import { assertTime, JobQueueStateError } from "./queue-utils.js";
3
+ export const DEFAULT_LEASE_DURATION_MS = 30_000;
4
+ export function normalizeOwnerToken(value) {
5
+ return normalizeId(value);
6
+ }
7
+ export function resolveLeaseExpiry(now, defaultDurationMs, options) {
8
+ const expiresAt = options.leaseExpiresAt ?? now + (options.leaseDurationMs ?? defaultDurationMs);
9
+ assertTime(expiresAt, "lease expiry");
10
+ if (expiresAt <= now)
11
+ throw new JobQueueStateError("Lease expiry must be in the future");
12
+ return expiresAt;
13
+ }
14
+ export function leaseTransitionOptions(now, defaultDurationMs, options, ownerToken) {
15
+ return {
16
+ leaseExpiresAt: resolveLeaseExpiry(now, defaultDurationMs, options),
17
+ leaseOwner: ownerToken,
18
+ };
19
+ }
20
+ export function assertLeaseDuration(value) {
21
+ if (!Number.isSafeInteger(value) || value <= 0)
22
+ throw new JobQueueStateError("Lease duration is invalid");
23
+ }
24
+ export function assertLeaseOwner(entry, ownerToken) {
25
+ if (entry.leaseOwner !== ownerToken)
26
+ throw new JobQueueStateError(`Job ${entry.instanceId} is owned by another process`);
27
+ }
28
+ export function isLeaseExpired(entry, now) {
29
+ return (entry.state === "leased" && entry.leaseExpiresAt !== undefined && entry.leaseExpiresAt <= now);
30
+ }
31
+ //# sourceMappingURL=lease-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease-utils.js","sourceRoot":"","sources":["../../src/jobs/lease-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAOlE,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEhD,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,GAAW,EACX,iBAAyB,EACzB,OAA6B;IAE7B,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,IAAI,iBAAiB,CAAC,CAAC;IACjG,UAAU,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACtC,IAAI,SAAS,IAAI,GAAG;QAAE,MAAM,IAAI,kBAAkB,CAAC,oCAAoC,CAAC,CAAC;IACzF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,GAAW,EACX,iBAAyB,EACzB,OAA6B,EAC7B,UAAkB;IAElB,OAAO;QACL,cAAc,EAAE,kBAAkB,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,CAAC;QACnE,UAAU,EAAE,UAAU;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAC5C,MAAM,IAAI,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAoB,EAAE,UAAkB;IACvE,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU;QACjC,MAAM,IAAI,kBAAkB,CAAC,OAAO,KAAK,CAAC,UAAU,8BAA8B,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAoB,EAAE,GAAW;IAC9D,OAAO,CACL,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS,IAAI,KAAK,CAAC,cAAc,IAAI,GAAG,CAC9F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { JobStore } from "./store.js";
2
+ import { type JobFailureMetadata, type JobQueueAdminRetryOptions, type JobQueueEntry } from "./queue-utils.js";
3
+ export interface JobQueueAdminMutations {
4
+ readonly adminRetry: (instanceId: string, options?: JobQueueAdminRetryOptions) => Promise<JobQueueEntry>;
5
+ readonly adminDeadLetter: (instanceId: string, failure: JobFailureMetadata) => Promise<JobQueueEntry>;
6
+ }
7
+ /** Adds explicit administrative transitions without changing worker transitions. */
8
+ export declare function createJobQueueAdminMutations(store: JobStore, entries: Map<string, JobQueueEntry>, options: {
9
+ readonly clock: () => number;
10
+ readonly serialize: <T>(work: () => Promise<T>) => Promise<T>;
11
+ }): JobQueueAdminMutations;
12
+ //# sourceMappingURL=queue-admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-admin.d.ts","sourceRoot":"","sources":["../../src/jobs/queue-admin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,EAAE,CACnB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,yBAAyB,KAChC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,CACxB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,KACxB,OAAO,CAAC,aAAa,CAAC,CAAC;CAC7B;AAED,oFAAoF;AACpF,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACnC,OAAO,EAAE;IACP,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CAC/D,GACA,sBAAsB,CAsCxB"}
@@ -0,0 +1,42 @@
1
+ import { normalizeId } from "@relkit/contracts";
2
+ import { nextEntry, persist } from "./queue-entry.js";
3
+ import { recoverQueueEntries } from "./queue-recovery.js";
4
+ import { assertTime, JobQueueStateError, } from "./queue-utils.js";
5
+ /** Adds explicit administrative transitions without changing worker transitions. */
6
+ export function createJobQueueAdminMutations(store, entries, options) {
7
+ const adminRetry = (instanceId, retryOptions = {}) => options.serialize(async () => {
8
+ const time = options.clock();
9
+ assertTime(time, "admin retry time");
10
+ await recoverQueueEntries(store, entries, time, false, options.clock);
11
+ const current = getEntry(entries, instanceId);
12
+ if (current.state !== "dead-lettered")
13
+ throw new JobQueueStateError(`Job ${current.instanceId} is not dead-lettered`);
14
+ const availableAt = retryOptions.availableAt ?? time;
15
+ assertTime(availableAt, "admin retry availability time");
16
+ const next = nextEntry(current, "available", { availableAt, attempt: 0 }, options.clock);
17
+ await persist(store, next);
18
+ entries.set(current.instanceId, next);
19
+ return next;
20
+ });
21
+ const adminDeadLetter = (instanceId, failure) => options.serialize(async () => {
22
+ const time = options.clock();
23
+ assertTime(time, "admin dead-letter time");
24
+ await recoverQueueEntries(store, entries, time, false, options.clock);
25
+ const current = getEntry(entries, instanceId);
26
+ if (current.state === "completed" || current.state === "dead-lettered")
27
+ throw new JobQueueStateError(`Job ${current.instanceId} is terminal`);
28
+ const next = nextEntry(current, "dead-lettered", { failure }, options.clock);
29
+ await persist(store, next);
30
+ entries.set(current.instanceId, next);
31
+ return next;
32
+ });
33
+ return { adminRetry, adminDeadLetter };
34
+ }
35
+ function getEntry(entries, instanceId) {
36
+ const normalized = normalizeId(instanceId);
37
+ const entry = entries.get(normalized);
38
+ if (entry === undefined)
39
+ throw new JobQueueStateError(`Job ${normalized} is unknown`);
40
+ return entry;
41
+ }
42
+ //# sourceMappingURL=queue-admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-admin.js","sourceRoot":"","sources":["../../src/jobs/queue-admin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type JsonValue } from "@relkit/contracts";
2
+ import type { JobRecord, JobStore } from "./store.js";
3
+ import { type JobIdempotencyRecord, type JobQueueEntry, type JobFailureMetadata, type JobQueueState, type JobQueueTransitionOptions } from "./queue-utils.js";
4
+ export declare function persist(store: JobStore, entry: JobQueueEntry): Promise<void>;
5
+ export declare function nextEntry(current: JobQueueEntry, state: JobQueueState, options: JobQueueTransitionOptions, clock: () => number): JobQueueEntry;
6
+ export declare function makeEntry(instanceId: string, state: JobQueueState, input: JsonValue, profile: string, acceptedAt: number, order: number, attempt: number, availableAt?: number, leaseExpiresAt?: number, leaseOwner?: string, idempotency?: JobIdempotencyRecord, failure?: JobFailureMetadata): JobQueueEntry;
7
+ export declare function readEntry(record: JobRecord): JobQueueEntry | undefined;
8
+ //# sourceMappingURL=queue-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-entry.d.ts","sourceRoot":"","sources":["../../src/jobs/queue-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,yBAAyB,EAC/B,MAAM,kBAAkB,CAAC;AAE1B,wBAAsB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF;AAED,wBAAgB,SAAS,CACvB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,MAAM,MAAM,GAClB,aAAa,CA4Cf;AAED,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,MAAM,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,oBAAoB,EAClC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,aAAa,CAwBf;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,SAAS,CA2BtE"}
@@ -0,0 +1,130 @@
1
+ import { canonicalJson, deepFreeze, normalizeId } from "@relkit/contracts";
2
+ import { assertIdempotencyRecord, readIdempotencyRecord } from "./idempotency.js";
3
+ import { JOB_QUEUE_STATES, JobQueueStateError, assertTime, } from "./queue-utils.js";
4
+ export async function persist(store, entry) {
5
+ await store.append({ instanceId: entry.instanceId, kind: entry.state, data: encode(entry) });
6
+ }
7
+ export function nextEntry(current, state, options, clock) {
8
+ const attempt = options.attempt ?? current.attempt;
9
+ if (!Number.isSafeInteger(attempt) || attempt < 0)
10
+ throw new JobQueueStateError("Attempt is invalid");
11
+ if (state === "delayed" && options.availableAt === undefined)
12
+ throw new JobQueueStateError("Delayed jobs require an available time");
13
+ if (state === "leased" && options.leaseExpiresAt === undefined)
14
+ throw new JobQueueStateError("Leased jobs require an expiry");
15
+ if (state === "leased" && options.availableAt !== undefined)
16
+ throw new JobQueueStateError("Leased jobs cannot have an available time");
17
+ if ((state === "completed" || state === "dead-lettered") &&
18
+ (options.availableAt !== undefined || options.leaseExpiresAt !== undefined))
19
+ throw new JobQueueStateError("Terminal jobs cannot retain lease metadata");
20
+ const availableAt = state === "available"
21
+ ? (options.availableAt ?? clock())
22
+ : state === "delayed"
23
+ ? options.availableAt
24
+ : undefined;
25
+ const leaseExpiresAt = state === "leased" ? options.leaseExpiresAt : undefined;
26
+ const leaseOwner = state === "leased" ? optionalOwner(options.leaseOwner) : undefined;
27
+ const failure = state === "delayed" || state === "dead-lettered"
28
+ ? (options.failure ?? current.failure)
29
+ : undefined;
30
+ const idempotency = current.idempotency;
31
+ if (availableAt !== undefined)
32
+ assertTime(availableAt, "available time");
33
+ if (leaseExpiresAt !== undefined)
34
+ assertTime(leaseExpiresAt, "lease expiry");
35
+ return makeEntry(current.instanceId, state, current.input, current.profile, current.acceptedAt, current.order, attempt, availableAt, leaseExpiresAt, leaseOwner, idempotency, failure);
36
+ }
37
+ export function makeEntry(instanceId, state, input, profile, acceptedAt, order, attempt, availableAt, leaseExpiresAt, leaseOwner, idempotency, failure) {
38
+ assertTime(acceptedAt, "accepted time");
39
+ if (!Number.isSafeInteger(order) || order < 1)
40
+ throw new JobQueueStateError("Queue order is invalid");
41
+ if (!Number.isSafeInteger(attempt) || attempt < 0)
42
+ throw new JobQueueStateError("Attempt is invalid");
43
+ if (failure !== undefined)
44
+ assertFailure(failure);
45
+ if (idempotency !== undefined)
46
+ assertIdempotencyRecord(idempotency);
47
+ return deepFreeze({
48
+ instanceId: normalizeId(instanceId),
49
+ state,
50
+ input: JSON.parse(canonicalJson(input)),
51
+ profile: normalizeId(profile),
52
+ attempt,
53
+ acceptedAt,
54
+ order,
55
+ ...(availableAt === undefined ? {} : { availableAt }),
56
+ ...(leaseOwner === undefined ? {} : { leaseOwner: normalizeId(leaseOwner) }),
57
+ ...(leaseExpiresAt === undefined ? {} : { leaseExpiresAt }),
58
+ ...(idempotency === undefined ? {} : { idempotency: { ...idempotency } }),
59
+ ...(failure === undefined
60
+ ? {}
61
+ : { failure: JSON.parse(canonicalJson(failure)) }),
62
+ });
63
+ }
64
+ export function readEntry(record) {
65
+ if (!isState(record.kind))
66
+ return undefined;
67
+ if (!isRecord(record.data))
68
+ throw new JobQueueStateError(`Job ${record.instanceId} data is invalid`);
69
+ const data = record.data;
70
+ if (data.input === undefined ||
71
+ data.profile === undefined ||
72
+ data.acceptedAt === undefined ||
73
+ data.attempt === undefined ||
74
+ data.order === undefined)
75
+ throw new JobQueueStateError(`Job ${record.instanceId} data is incomplete`);
76
+ return makeEntry(record.instanceId, record.kind, data.input, normalizeId(data.profile), numberValue(data.acceptedAt, "accepted time"), numberValue(data.order, "queue order"), numberValue(data.attempt, "attempt"), optionalNumber(data.availableAt, "available time"), optionalNumber(data.leaseExpiresAt, "lease expiry"), optionalOwner(data.leaseOwner), readIdempotencyRecord(data.idempotency), optionalFailure(data.failure));
77
+ }
78
+ function encode(entry) {
79
+ return JSON.parse(canonicalJson(entry));
80
+ }
81
+ function isState(value) {
82
+ return JOB_QUEUE_STATES.includes(value);
83
+ }
84
+ function isRecord(value) {
85
+ return value !== null && typeof value === "object" && !Array.isArray(value);
86
+ }
87
+ function optionalNumber(value, label) {
88
+ return value === undefined ? undefined : numberValue(value, label);
89
+ }
90
+ function optionalOwner(value) {
91
+ return value === undefined ? undefined : normalizeId(value);
92
+ }
93
+ function optionalFailure(value) {
94
+ if (value === undefined)
95
+ return undefined;
96
+ if (!isRecord(value))
97
+ throw new JobQueueStateError("Job failure metadata is invalid");
98
+ const failure = value;
99
+ assertFailure(failure);
100
+ return failure;
101
+ }
102
+ function assertFailure(value) {
103
+ if (!isFailureKind(value.kind) ||
104
+ !isFailureOutcome(value.outcome) ||
105
+ typeof value.code !== "string" ||
106
+ value.code.trim() === "" ||
107
+ typeof value.message !== "string" ||
108
+ value.message.trim() === "")
109
+ throw new JobQueueStateError("Job failure metadata is invalid");
110
+ if (value.status !== undefined && !Number.isSafeInteger(value.status))
111
+ throw new JobQueueStateError("Job failure status is invalid");
112
+ if (value.retry !== undefined && value.retry !== "never" && value.retry !== "later")
113
+ throw new JobQueueStateError("Job failure retry classification is invalid");
114
+ if (value.afterMs !== undefined && (!Number.isSafeInteger(value.afterMs) || value.afterMs < 0))
115
+ throw new JobQueueStateError("Job failure retry delay is invalid");
116
+ if (value.data !== undefined)
117
+ canonicalJson(value.data);
118
+ }
119
+ function isFailureKind(value) {
120
+ return ["application", "provider", "cancellation", "timeout", "defect"].includes(value);
121
+ }
122
+ function isFailureOutcome(value) {
123
+ return ["declared-error", "provider-failure", "cancelled", "timeout", "defect"].includes(value);
124
+ }
125
+ function numberValue(value, label) {
126
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)
127
+ throw new JobQueueStateError(`Job ${label} is invalid`);
128
+ return value;
129
+ }
130
+ //# sourceMappingURL=queue-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-entry.js","sourceRoot":"","sources":["../../src/jobs/queue-entry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { JobStore } from "./store.js";
2
+ import type { JobQueueEntry, JobQueueLeaseOptions } from "./queue-utils.js";
3
+ export declare function acquireQueueLease(store: JobStore, entries: Map<string, JobQueueEntry>, current: JobQueueEntry, time: number, leaseOptions: JobQueueLeaseOptions, attempt: number, clock: () => number, ownerToken: string, defaultDurationMs: number): Promise<JobQueueEntry>;
4
+ //# sourceMappingURL=queue-lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-lease.d.ts","sourceRoot":"","sources":["../../src/jobs/queue-lease.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG5E,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACnC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,oBAAoB,EAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,aAAa,CAAC,CAaxB"}
@@ -0,0 +1,12 @@
1
+ import { nextEntry, persist } from "./queue-entry.js";
2
+ import { leaseTransitionOptions } from "./lease-utils.js";
3
+ export async function acquireQueueLease(store, entries, current, time, leaseOptions, attempt, clock, ownerToken, defaultDurationMs) {
4
+ const next = nextEntry(current, "leased", {
5
+ ...leaseTransitionOptions(time, defaultDurationMs, leaseOptions, ownerToken),
6
+ attempt,
7
+ }, clock);
8
+ await persist(store, next);
9
+ entries.set(current.instanceId, next);
10
+ return next;
11
+ }
12
+ //# sourceMappingURL=queue-lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-lease.js","sourceRoot":"","sources":["../../src/jobs/queue-lease.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAe,EACf,OAAmC,EACnC,OAAsB,EACtB,IAAY,EACZ,YAAkC,EAClC,OAAe,EACf,KAAmB,EACnB,UAAkB,EAClB,iBAAyB;IAEzB,MAAM,IAAI,GAAG,SAAS,CACpB,OAAO,EACP,QAAQ,EACR;QACE,GAAG,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,EAAE,YAAY,EAAE,UAAU,CAAC;QAC5E,OAAO;KACR,EACD,KAAK,CACN,CAAC;IACF,MAAM,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { JobStore } from "./store.js";
2
+ import { type JobQueueEnqueue, type JobQueueEntry, type JobQueue } from "./queue-utils.js";
3
+ import { type JobQueueAdminMutations } from "./queue-admin.js";
4
+ export interface MutableQueueState {
5
+ readonly entries: Map<string, JobQueueEntry>;
6
+ nextOrder: number;
7
+ }
8
+ export type JobQueueMutations = Pick<JobQueue, "ready" | "enqueue" | "acquire" | "renew" | "transition" | "recover" | "expire"> & JobQueueAdminMutations;
9
+ export declare function createJobQueueMutations(store: JobStore, state: MutableQueueState, options: {
10
+ readonly clock: () => number;
11
+ readonly createInstanceId?: () => string;
12
+ readonly ownerToken: string;
13
+ readonly leaseDurationMs: number;
14
+ readonly idempotency?: JobQueueEnqueue["idempotency"];
15
+ }): JobQueueMutations;
16
+ //# sourceMappingURL=queue-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-operations.d.ts","sourceRoot":"","sources":["../../src/jobs/queue-operations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,OAAO,EAGL,KAAK,eAAe,EAEpB,KAAK,aAAa,EAClB,KAAK,QAAQ,EAKd,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAgC,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE7F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,QAAQ,EACR,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,QAAQ,CAChF,GACC,sBAAsB,CAAC;AAEzB,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE;IACP,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;CACvD,GACA,iBAAiB,CA+JnB"}