@durable-effect/jobs 0.0.1-next.1

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 (199) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +490 -0
  3. package/dist/client/client.d.ts +34 -0
  4. package/dist/client/client.d.ts.map +1 -0
  5. package/dist/client/client.js +427 -0
  6. package/dist/client/client.js.map +1 -0
  7. package/dist/client/index.d.ts +4 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +4 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/client/response.d.ts +99 -0
  12. package/dist/client/response.d.ts.map +1 -0
  13. package/dist/client/response.js +92 -0
  14. package/dist/client/response.js.map +1 -0
  15. package/dist/client/types.d.ts +242 -0
  16. package/dist/client/types.d.ts.map +1 -0
  17. package/dist/client/types.js +3 -0
  18. package/dist/client/types.js.map +1 -0
  19. package/dist/definitions/continuous.d.ts +110 -0
  20. package/dist/definitions/continuous.d.ts.map +1 -0
  21. package/dist/definitions/continuous.js +79 -0
  22. package/dist/definitions/continuous.js.map +1 -0
  23. package/dist/definitions/debounce.d.ts +67 -0
  24. package/dist/definitions/debounce.d.ts.map +1 -0
  25. package/dist/definitions/debounce.js +28 -0
  26. package/dist/definitions/debounce.js.map +1 -0
  27. package/dist/definitions/index.d.ts +4 -0
  28. package/dist/definitions/index.d.ts.map +1 -0
  29. package/dist/definitions/index.js +5 -0
  30. package/dist/definitions/index.js.map +1 -0
  31. package/dist/definitions/task.d.ts +234 -0
  32. package/dist/definitions/task.d.ts.map +1 -0
  33. package/dist/definitions/task.js +106 -0
  34. package/dist/definitions/task.js.map +1 -0
  35. package/dist/engine/engine.d.ts +60 -0
  36. package/dist/engine/engine.d.ts.map +1 -0
  37. package/dist/engine/engine.js +89 -0
  38. package/dist/engine/engine.js.map +1 -0
  39. package/dist/engine/index.d.ts +3 -0
  40. package/dist/engine/index.d.ts.map +1 -0
  41. package/dist/engine/index.js +3 -0
  42. package/dist/engine/index.js.map +1 -0
  43. package/dist/engine/types.d.ts +53 -0
  44. package/dist/engine/types.d.ts.map +1 -0
  45. package/dist/engine/types.js +3 -0
  46. package/dist/engine/types.js.map +1 -0
  47. package/dist/errors.d.ts +119 -0
  48. package/dist/errors.d.ts.map +1 -0
  49. package/dist/errors.js +80 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/factory.d.ts +97 -0
  52. package/dist/factory.d.ts.map +1 -0
  53. package/dist/factory.js +94 -0
  54. package/dist/factory.js.map +1 -0
  55. package/dist/handlers/continuous/context.d.ts +25 -0
  56. package/dist/handlers/continuous/context.d.ts.map +1 -0
  57. package/dist/handlers/continuous/context.js +38 -0
  58. package/dist/handlers/continuous/context.js.map +1 -0
  59. package/dist/handlers/continuous/executor.d.ts +10 -0
  60. package/dist/handlers/continuous/executor.d.ts.map +1 -0
  61. package/dist/handlers/continuous/executor.js +83 -0
  62. package/dist/handlers/continuous/executor.js.map +1 -0
  63. package/dist/handlers/continuous/handler.d.ts +14 -0
  64. package/dist/handlers/continuous/handler.d.ts.map +1 -0
  65. package/dist/handlers/continuous/handler.js +283 -0
  66. package/dist/handlers/continuous/handler.js.map +1 -0
  67. package/dist/handlers/continuous/index.d.ts +4 -0
  68. package/dist/handlers/continuous/index.d.ts.map +1 -0
  69. package/dist/handlers/continuous/index.js +4 -0
  70. package/dist/handlers/continuous/index.js.map +1 -0
  71. package/dist/handlers/continuous/types.d.ts +36 -0
  72. package/dist/handlers/continuous/types.d.ts.map +1 -0
  73. package/dist/handlers/continuous/types.js +3 -0
  74. package/dist/handlers/continuous/types.js.map +1 -0
  75. package/dist/handlers/debounce/handler.d.ts +14 -0
  76. package/dist/handlers/debounce/handler.d.ts.map +1 -0
  77. package/dist/handlers/debounce/handler.js +261 -0
  78. package/dist/handlers/debounce/handler.js.map +1 -0
  79. package/dist/handlers/debounce/index.d.ts +3 -0
  80. package/dist/handlers/debounce/index.d.ts.map +1 -0
  81. package/dist/handlers/debounce/index.js +3 -0
  82. package/dist/handlers/debounce/index.js.map +1 -0
  83. package/dist/handlers/debounce/types.d.ts +10 -0
  84. package/dist/handlers/debounce/types.d.ts.map +1 -0
  85. package/dist/handlers/debounce/types.js +3 -0
  86. package/dist/handlers/debounce/types.js.map +1 -0
  87. package/dist/handlers/index.d.ts +14 -0
  88. package/dist/handlers/index.d.ts.map +1 -0
  89. package/dist/handlers/index.js +25 -0
  90. package/dist/handlers/index.js.map +1 -0
  91. package/dist/handlers/task/context.d.ts +35 -0
  92. package/dist/handlers/task/context.d.ts.map +1 -0
  93. package/dist/handlers/task/context.js +156 -0
  94. package/dist/handlers/task/context.js.map +1 -0
  95. package/dist/handlers/task/handler.d.ts +13 -0
  96. package/dist/handlers/task/handler.d.ts.map +1 -0
  97. package/dist/handlers/task/handler.js +280 -0
  98. package/dist/handlers/task/handler.js.map +1 -0
  99. package/dist/handlers/task/index.d.ts +3 -0
  100. package/dist/handlers/task/index.d.ts.map +1 -0
  101. package/dist/handlers/task/index.js +2 -0
  102. package/dist/handlers/task/index.js.map +1 -0
  103. package/dist/handlers/task/types.d.ts +10 -0
  104. package/dist/handlers/task/types.d.ts.map +1 -0
  105. package/dist/handlers/task/types.js +3 -0
  106. package/dist/handlers/task/types.js.map +1 -0
  107. package/dist/index.d.ts +28 -0
  108. package/dist/index.d.ts.map +1 -0
  109. package/dist/index.js +79 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/registry/index.d.ts +5 -0
  112. package/dist/registry/index.d.ts.map +1 -0
  113. package/dist/registry/index.js +4 -0
  114. package/dist/registry/index.js.map +1 -0
  115. package/dist/registry/registry.d.ts +74 -0
  116. package/dist/registry/registry.d.ts.map +1 -0
  117. package/dist/registry/registry.js +159 -0
  118. package/dist/registry/registry.js.map +1 -0
  119. package/dist/registry/typed.d.ts +146 -0
  120. package/dist/registry/typed.d.ts.map +1 -0
  121. package/dist/registry/typed.js +29 -0
  122. package/dist/registry/typed.js.map +1 -0
  123. package/dist/registry/types.d.ts +497 -0
  124. package/dist/registry/types.d.ts.map +1 -0
  125. package/dist/registry/types.js +3 -0
  126. package/dist/registry/types.js.map +1 -0
  127. package/dist/retry/errors.d.ts +31 -0
  128. package/dist/retry/errors.d.ts.map +1 -0
  129. package/dist/retry/errors.js +22 -0
  130. package/dist/retry/errors.js.map +1 -0
  131. package/dist/retry/executor.d.ts +53 -0
  132. package/dist/retry/executor.d.ts.map +1 -0
  133. package/dist/retry/executor.js +112 -0
  134. package/dist/retry/executor.js.map +1 -0
  135. package/dist/retry/index.d.ts +4 -0
  136. package/dist/retry/index.d.ts.map +1 -0
  137. package/dist/retry/index.js +4 -0
  138. package/dist/retry/index.js.map +1 -0
  139. package/dist/retry/types.d.ts +29 -0
  140. package/dist/retry/types.d.ts.map +1 -0
  141. package/dist/retry/types.js +3 -0
  142. package/dist/retry/types.js.map +1 -0
  143. package/dist/runtime/dispatcher.d.ts +39 -0
  144. package/dist/runtime/dispatcher.d.ts.map +1 -0
  145. package/dist/runtime/dispatcher.js +76 -0
  146. package/dist/runtime/dispatcher.js.map +1 -0
  147. package/dist/runtime/index.d.ts +4 -0
  148. package/dist/runtime/index.d.ts.map +1 -0
  149. package/dist/runtime/index.js +6 -0
  150. package/dist/runtime/index.js.map +1 -0
  151. package/dist/runtime/runtime.d.ts +88 -0
  152. package/dist/runtime/runtime.d.ts.map +1 -0
  153. package/dist/runtime/runtime.js +116 -0
  154. package/dist/runtime/runtime.js.map +1 -0
  155. package/dist/runtime/types.d.ts +182 -0
  156. package/dist/runtime/types.d.ts.map +1 -0
  157. package/dist/runtime/types.js +3 -0
  158. package/dist/runtime/types.js.map +1 -0
  159. package/dist/services/alarm.d.ts +37 -0
  160. package/dist/services/alarm.d.ts.map +1 -0
  161. package/dist/services/alarm.js +39 -0
  162. package/dist/services/alarm.js.map +1 -0
  163. package/dist/services/cleanup.d.ts +27 -0
  164. package/dist/services/cleanup.d.ts.map +1 -0
  165. package/dist/services/cleanup.js +25 -0
  166. package/dist/services/cleanup.js.map +1 -0
  167. package/dist/services/entity-state.d.ts +49 -0
  168. package/dist/services/entity-state.d.ts.map +1 -0
  169. package/dist/services/entity-state.js +72 -0
  170. package/dist/services/entity-state.js.map +1 -0
  171. package/dist/services/execution.d.ts +70 -0
  172. package/dist/services/execution.d.ts.map +1 -0
  173. package/dist/services/execution.js +159 -0
  174. package/dist/services/execution.js.map +1 -0
  175. package/dist/services/execution_test.d.ts +13 -0
  176. package/dist/services/execution_test.d.ts.map +1 -0
  177. package/dist/services/execution_test.js +11 -0
  178. package/dist/services/execution_test.js.map +1 -0
  179. package/dist/services/idempotency.d.ts +36 -0
  180. package/dist/services/idempotency.d.ts.map +1 -0
  181. package/dist/services/idempotency.js +48 -0
  182. package/dist/services/idempotency.js.map +1 -0
  183. package/dist/services/index.d.ts +19 -0
  184. package/dist/services/index.d.ts.map +1 -0
  185. package/dist/services/index.js +33 -0
  186. package/dist/services/index.js.map +1 -0
  187. package/dist/services/metadata.d.ts +64 -0
  188. package/dist/services/metadata.d.ts.map +1 -0
  189. package/dist/services/metadata.js +56 -0
  190. package/dist/services/metadata.js.map +1 -0
  191. package/dist/services/registry.d.ts +19 -0
  192. package/dist/services/registry.d.ts.map +1 -0
  193. package/dist/services/registry.js +17 -0
  194. package/dist/services/registry.js.map +1 -0
  195. package/dist/storage-keys.d.ts +38 -0
  196. package/dist/storage-keys.d.ts.map +1 -0
  197. package/dist/storage-keys.js +47 -0
  198. package/dist/storage-keys.js.map +1 -0
  199. package/package.json +35 -0
@@ -0,0 +1,53 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { StorageAdapter, RuntimeAdapter, type StorageError } from "@durable-effect/core";
3
+ import { AlarmService } from "../services/alarm";
4
+ import type { JobRetryConfig } from "./types";
5
+ import { RetryExhaustedSignal, RetryScheduledSignal } from "./errors";
6
+ /**
7
+ * RetryExecutor handles retry logic for job executions.
8
+ *
9
+ * Key responsibilities:
10
+ * - Track retry attempts via durable storage
11
+ * - Calculate retry delays using configured backoff
12
+ * - Schedule retry alarms
13
+ * - Signal when retries are exhausted
14
+ *
15
+ * Important: TerminateSignal bypasses retry logic entirely.
16
+ * All other errors from user code are considered retryable.
17
+ */
18
+ export interface RetryExecutorI {
19
+ /**
20
+ * Execute an effect with retry logic.
21
+ *
22
+ * - On success: resets retry state and returns result
23
+ * - On TerminateSignal: bypasses retry, propagates signal
24
+ * - On failure with retries remaining: schedules retry, fails with RetryScheduledSignal
25
+ * - On failure with retries exhausted: resets retry state, fails with RetryExhaustedSignal
26
+ */
27
+ readonly executeWithRetry: <A, E, R>(effect: Effect.Effect<A, E, R>, config: JobRetryConfig, context: {
28
+ jobType: "continuous" | "debounce" | "task" | "workerPool";
29
+ jobName: string;
30
+ }) => Effect.Effect<A, E | RetryExhaustedSignal | RetryScheduledSignal, R>;
31
+ /**
32
+ * Check if we're currently in a retry sequence.
33
+ */
34
+ readonly isRetrying: () => Effect.Effect<boolean, StorageError>;
35
+ /**
36
+ * Get current attempt number (1 = first attempt).
37
+ */
38
+ readonly getAttempt: () => Effect.Effect<number, StorageError>;
39
+ /**
40
+ * Reset retry state (called after success or exhaustion).
41
+ */
42
+ readonly reset: () => Effect.Effect<void, StorageError>;
43
+ /**
44
+ * Get the scheduled retry timestamp, if any.
45
+ */
46
+ readonly getScheduledAt: () => Effect.Effect<number | undefined, StorageError>;
47
+ }
48
+ declare const RetryExecutor_base: Context.TagClass<RetryExecutor, "@durable-effect/jobs/RetryExecutor", RetryExecutorI>;
49
+ export declare class RetryExecutor extends RetryExecutor_base {
50
+ }
51
+ export declare const RetryExecutorLayer: Layer.Layer<RetryExecutor, never, RuntimeAdapter | StorageAdapter | AlarmService>;
52
+ export {};
53
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/retry/executor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAY,MAAM,QAAQ,CAAC;AAC1D,OAAO,EACL,cAAc,EACd,cAAc,EAGd,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAOtE;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;OAOG;IACH,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE;QACP,OAAO,EAAE,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;QAC3D,OAAO,EAAE,MAAM,CAAC;KACjB,KACE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,oBAAoB,GAAG,oBAAoB,EAAE,CAAC,CAAC,CAAC;IAE1E;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAEhE;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAE/D;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAExD;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,YAAY,CAAC,CAAC;CAChF;;AAMD,qBAAa,aAAc,SAAQ,kBAED;CAAG;AAMrC,eAAO,MAAM,kBAAkB,mFAkJ9B,CAAC"}
@@ -0,0 +1,112 @@
1
+ // packages/jobs/src/retry/executor.ts
2
+ import { Context, Effect, Layer, Duration } from "effect";
3
+ import { StorageAdapter, RuntimeAdapter, resolveDelay, addJitter, } from "@durable-effect/core";
4
+ import { AlarmService } from "../services/alarm";
5
+ import { KEYS } from "../storage-keys";
6
+ import { RetryExhaustedSignal, RetryScheduledSignal } from "./errors";
7
+ import { TerminateSignal } from "../errors";
8
+ // =============================================================================
9
+ // Service Tag
10
+ // =============================================================================
11
+ export class RetryExecutor extends Context.Tag("@durable-effect/jobs/RetryExecutor")() {
12
+ }
13
+ // =============================================================================
14
+ // Implementation
15
+ // =============================================================================
16
+ export const RetryExecutorLayer = Layer.effect(RetryExecutor, Effect.gen(function* () {
17
+ const storage = yield* StorageAdapter;
18
+ const runtime = yield* RuntimeAdapter;
19
+ const alarm = yield* AlarmService;
20
+ // Storage helpers
21
+ const getAttempt = () => storage.get(KEYS.RETRY.ATTEMPT).pipe(Effect.map((a) => a ?? 1));
22
+ const setAttempt = (attempt) => storage.put(KEYS.RETRY.ATTEMPT, attempt);
23
+ const getStartedAt = () => storage.get(KEYS.RETRY.STARTED_AT);
24
+ const setStartedAt = (timestamp) => storage.put(KEYS.RETRY.STARTED_AT, timestamp);
25
+ const setLastError = (error) => storage.put(KEYS.RETRY.LAST_ERROR, error);
26
+ const getScheduledAt = () => storage.get(KEYS.RETRY.SCHEDULED_AT);
27
+ const setScheduledAt = (timestamp) => storage.put(KEYS.RETRY.SCHEDULED_AT, timestamp);
28
+ const reset = () => Effect.gen(function* () {
29
+ yield* storage.delete(KEYS.RETRY.ATTEMPT);
30
+ yield* storage.delete(KEYS.RETRY.STARTED_AT);
31
+ yield* storage.delete(KEYS.RETRY.LAST_ERROR);
32
+ yield* storage.delete(KEYS.RETRY.SCHEDULED_AT);
33
+ });
34
+ return {
35
+ executeWithRetry: (effect, config, context) => Effect.gen(function* () {
36
+ const attempt = yield* getAttempt();
37
+ const now = yield* runtime.now();
38
+ // Initialize started_at on first attempt
39
+ if (attempt === 1) {
40
+ yield* setStartedAt(now);
41
+ }
42
+ // Check max duration before executing
43
+ if (config.maxDuration !== undefined) {
44
+ const startedAt = yield* getStartedAt();
45
+ if (startedAt !== undefined) {
46
+ const elapsed = now - startedAt;
47
+ const duration = Duration.decode(config.maxDuration);
48
+ const maxMs = Duration.toMillis(duration);
49
+ if (elapsed >= maxMs) {
50
+ // Duration exceeded - signal exhaustion
51
+ yield* reset();
52
+ return yield* Effect.fail(new RetryExhaustedSignal({
53
+ ...context,
54
+ instanceId: runtime.instanceId,
55
+ attempts: attempt,
56
+ lastError: new Error("Max duration exceeded"),
57
+ totalDurationMs: elapsed,
58
+ reason: "max_duration_exceeded",
59
+ }));
60
+ }
61
+ }
62
+ }
63
+ // Execute the effect, but let TerminateSignal bypass retry
64
+ const result = yield* effect.pipe(Effect.map((a) => ({ _tag: "Success", value: a })), Effect.catchAll((e) => {
65
+ // TerminateSignal bypasses retry entirely
66
+ if (e instanceof TerminateSignal) {
67
+ return Effect.fail(e);
68
+ }
69
+ // Regular errors go through retry logic
70
+ return Effect.succeed({ _tag: "Failure", error: e });
71
+ }));
72
+ if (result._tag === "Success") {
73
+ // Success - reset retry state
74
+ yield* reset();
75
+ return result.value;
76
+ }
77
+ // Failure - all errors are retryable (removed isRetryable check)
78
+ const error = result.error;
79
+ // Check if attempts exhausted
80
+ if (attempt >= config.maxAttempts) {
81
+ // Exhausted - signal it (handler will call onRetryExhausted or terminate)
82
+ const startedAt = (yield* getStartedAt()) ?? now;
83
+ yield* reset();
84
+ return yield* Effect.fail(new RetryExhaustedSignal({
85
+ ...context,
86
+ instanceId: runtime.instanceId,
87
+ attempts: attempt,
88
+ lastError: error,
89
+ totalDurationMs: now - startedAt,
90
+ reason: "max_attempts_exceeded",
91
+ }));
92
+ }
93
+ // Schedule retry
94
+ yield* setLastError(error);
95
+ yield* setAttempt(attempt + 1);
96
+ const baseDelay = resolveDelay(config.delay, attempt);
97
+ const delayMs = config.jitter !== false ? addJitter(baseDelay) : baseDelay;
98
+ const resumeAt = now + delayMs;
99
+ yield* alarm.schedule(resumeAt);
100
+ yield* setScheduledAt(resumeAt);
101
+ // Return a signal that the handler will catch
102
+ return yield* Effect.fail(new RetryScheduledSignal({ resumeAt, attempt: attempt + 1 }));
103
+ }).pipe(
104
+ // Map storage/scheduler errors to defects (they shouldn't happen)
105
+ Effect.catchTag("StorageError", (e) => Effect.die(e)), Effect.catchTag("SchedulerError", (e) => Effect.die(e))),
106
+ isRetrying: () => getAttempt().pipe(Effect.map((a) => a > 1)),
107
+ getAttempt,
108
+ reset,
109
+ getScheduledAt,
110
+ };
111
+ }));
112
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/retry/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type { JobRetryConfig, RetryExhaustedInfo } from "./types";
2
+ export { RetryExhaustedSignal, RetryScheduledSignal } from "./errors";
3
+ export { RetryExecutor, RetryExecutorLayer, type RetryExecutorI, } from "./executor";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/retry/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACtE,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ // packages/jobs/src/retry/index.ts
2
+ export { RetryExhaustedSignal, RetryScheduledSignal } from "./errors";
3
+ export { RetryExecutor, RetryExecutorLayer, } from "./executor";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/retry/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAGnC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACtE,OAAO,EACL,aAAa,EACb,kBAAkB,GAEnB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { BaseRetryConfig } from "@durable-effect/core";
2
+ /**
3
+ * Information provided when all retry attempts are exhausted.
4
+ *
5
+ * This is passed to the RetryExhaustedSignal and can be used by
6
+ * the job's onRetryExhausted handler.
7
+ */
8
+ export interface RetryExhaustedInfo {
9
+ readonly jobType: "continuous" | "debounce" | "task" | "workerPool";
10
+ readonly jobName: string;
11
+ readonly instanceId: string;
12
+ readonly attempts: number;
13
+ readonly lastError: unknown;
14
+ readonly totalDurationMs: number;
15
+ }
16
+ /**
17
+ * Retry configuration for job execute handlers.
18
+ *
19
+ * Simplified configuration focused only on retry timing.
20
+ * All errors from execute are retryable - use onRetryExhausted
21
+ * at the job definition level for custom exhaustion handling.
22
+ *
23
+ * When retries are exhausted:
24
+ * - If onRetryExhausted is defined on the job: it's called with the typed error
25
+ * - If not defined: the job is terminated (state purged) by default
26
+ */
27
+ export interface JobRetryConfig extends BaseRetryConfig {
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/retry/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,cAAe,SAAQ,eAAe;CAMtD"}
@@ -0,0 +1,3 @@
1
+ // packages/jobs/src/retry/types.ts
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/retry/types.ts"],"names":[],"mappings":"AAAA,mCAAmC"}
@@ -0,0 +1,39 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { MetadataService } from "../services/metadata";
3
+ import { ContinuousHandler } from "../handlers/continuous";
4
+ import { DebounceHandler } from "../handlers/debounce";
5
+ import { TaskHandler } from "../handlers/task";
6
+ import { type JobError } from "../errors";
7
+ import type { JobRequest, JobResponse } from "./types";
8
+ /**
9
+ * Dispatcher routes requests to job handlers.
10
+ *
11
+ * This is the central routing hub for all job operations:
12
+ * - handle(request): Routes to the appropriate handler based on request.type
13
+ * - handleAlarm(): Reads metadata to determine type, then routes to handler
14
+ */
15
+ export interface DispatcherServiceI {
16
+ /**
17
+ * Handle a job request.
18
+ * Routes to the appropriate handler based on request.type.
19
+ */
20
+ readonly handle: (request: JobRequest) => Effect.Effect<JobResponse, JobError, any>;
21
+ /**
22
+ * Handle an alarm.
23
+ * Reads metadata to determine which job type to route to.
24
+ */
25
+ readonly handleAlarm: () => Effect.Effect<void, JobError, any>;
26
+ }
27
+ declare const Dispatcher_base: Context.TagClass<Dispatcher, "@durable-effect/jobs/Dispatcher", DispatcherServiceI>;
28
+ export declare class Dispatcher extends Dispatcher_base {
29
+ }
30
+ /**
31
+ * Creates the dispatcher that routes to job handlers.
32
+ *
33
+ * Phase 3: Routes to ContinuousHandler
34
+ * Phase 4: Add routing to DebounceHandler
35
+ * Phase 5: Add routing to WorkerPoolHandler
36
+ */
37
+ export declare const DispatcherLayer: Layer.Layer<Dispatcher, never, MetadataService | ContinuousHandler | DebounceHandler | TaskHandler>;
38
+ export {};
39
+ //# sourceMappingURL=dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/runtime/dispatcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAMvD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,CACf,OAAO,EAAE,UAAU,KAChB,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;IAE/C;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;CAChE;;AAMD,qBAAa,UAAW,SAAQ,eAEG;CAAG;AAMtC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,qGA6E3B,CAAC"}
@@ -0,0 +1,76 @@
1
+ // packages/jobs/src/runtime/dispatcher.ts
2
+ import { Context, Effect, Layer } from "effect";
3
+ import { MetadataService } from "../services/metadata";
4
+ import { ContinuousHandler } from "../handlers/continuous";
5
+ import { DebounceHandler } from "../handlers/debounce";
6
+ import { TaskHandler } from "../handlers/task";
7
+ import { UnknownJobTypeError } from "../errors";
8
+ // =============================================================================
9
+ // Service Tag
10
+ // =============================================================================
11
+ export class Dispatcher extends Context.Tag("@durable-effect/jobs/Dispatcher")() {
12
+ }
13
+ // =============================================================================
14
+ // Layer Implementation
15
+ // =============================================================================
16
+ /**
17
+ * Creates the dispatcher that routes to job handlers.
18
+ *
19
+ * Phase 3: Routes to ContinuousHandler
20
+ * Phase 4: Add routing to DebounceHandler
21
+ * Phase 5: Add routing to WorkerPoolHandler
22
+ */
23
+ export const DispatcherLayer = Layer.effect(Dispatcher, Effect.gen(function* () {
24
+ const metadata = yield* MetadataService;
25
+ const continuous = yield* ContinuousHandler;
26
+ const debounce = yield* DebounceHandler;
27
+ const task = yield* TaskHandler;
28
+ return {
29
+ handle: (request) => Effect.gen(function* () {
30
+ switch (request.type) {
31
+ case "continuous":
32
+ return yield* continuous.handle(request);
33
+ case "debounce":
34
+ return yield* debounce.handle(request);
35
+ case "task":
36
+ return yield* task.handle(request);
37
+ case "workerPool":
38
+ // TODO: Route to WorkerPoolHandler in Phase 5
39
+ return yield* Effect.fail(new UnknownJobTypeError({
40
+ type: `workerPool (handler not implemented)`,
41
+ }));
42
+ default:
43
+ // TypeScript exhaustiveness check
44
+ const _exhaustive = request;
45
+ return yield* Effect.fail(new UnknownJobTypeError({
46
+ type: request.type,
47
+ }));
48
+ }
49
+ }),
50
+ handleAlarm: () => Effect.gen(function* () {
51
+ const meta = yield* metadata.get();
52
+ // No metadata = instance was never initialized, nothing to do
53
+ if (!meta) {
54
+ return;
55
+ }
56
+ switch (meta.type) {
57
+ case "continuous":
58
+ yield* continuous.handleAlarm();
59
+ break;
60
+ case "debounce":
61
+ yield* debounce.handleAlarm();
62
+ break;
63
+ case "task":
64
+ yield* task.handleAlarm();
65
+ break;
66
+ case "workerPool":
67
+ // TODO: Route to WorkerPoolHandler.handleAlarm in Phase 5
68
+ yield* Effect.logInfo(`Alarm for workerPool/${meta.name} (handler not implemented)`);
69
+ break;
70
+ default:
71
+ yield* Effect.logWarning(`Unknown job type in alarm: ${meta.type}`);
72
+ }
73
+ }),
74
+ };
75
+ }));
76
+ //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/runtime/dispatcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type { JobRequest, JobResponse, ContinuousRequest, DebounceRequest, WorkerPoolRequest, ContinuousStartResponse, ContinuousTerminateResponse, ContinuousTriggerResponse, ContinuousStatusResponse, ContinuousGetStateResponse, DebounceAddResponse, DebounceFlushResponse, DebounceClearResponse, DebounceStatusResponse, DebounceGetStateResponse, WorkerPoolEnqueueResponse, WorkerPoolPauseResponse, WorkerPoolResumeResponse, WorkerPoolCancelResponse, WorkerPoolStatusResponse, WorkerPoolDrainResponse, } from "./types";
2
+ export { Dispatcher, DispatcherLayer, type DispatcherServiceI, } from "./dispatcher";
3
+ export { createJobsRuntime, createJobsRuntimeFromLayer, type JobsRuntime, type JobsRuntimeConfig, } from "./runtime";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,UAAU,EACV,eAAe,EACf,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,iBAAiB,EACjB,0BAA0B,EAC1B,KAAK,WAAW,EAChB,KAAK,iBAAiB,GACvB,MAAM,WAAW,CAAC"}
@@ -0,0 +1,6 @@
1
+ // packages/jobs/src/runtime/index.ts
2
+ // Dispatcher
3
+ export { Dispatcher, DispatcherLayer, } from "./dispatcher";
4
+ // Runtime
5
+ export { createJobsRuntime, createJobsRuntimeFromLayer, } from "./runtime";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AA2BrC,aAAa;AACb,OAAO,EACL,UAAU,EACV,eAAe,GAEhB,MAAM,cAAc,CAAC;AAEtB,UAAU;AACV,OAAO,EACL,iBAAiB,EACjB,0BAA0B,GAG3B,MAAM,WAAW,CAAC"}
@@ -0,0 +1,88 @@
1
+ import { type RuntimeLayer } from "@durable-effect/core";
2
+ import type { JobRequest, JobResponse } from "./types";
3
+ import type { RuntimeJobRegistry } from "../registry/typed";
4
+ /**
5
+ * Configuration for creating a jobs runtime.
6
+ */
7
+ export interface JobsRuntimeConfig {
8
+ /**
9
+ * Durable Object state (provides storage + alarm).
10
+ */
11
+ readonly doState: DurableObjectState;
12
+ /**
13
+ * Registry of job definitions.
14
+ * Required for handlers to look up definitions.
15
+ */
16
+ readonly registry: RuntimeJobRegistry;
17
+ }
18
+ /**
19
+ * The jobs runtime interface.
20
+ *
21
+ * This is what the DO shell delegates to. It's a simple interface
22
+ * that hides all the Effect complexity from the DO class.
23
+ */
24
+ export interface JobsRuntime {
25
+ /**
26
+ * Handle a job request.
27
+ */
28
+ readonly handle: (request: JobRequest) => Promise<JobResponse>;
29
+ /**
30
+ * Handle an alarm.
31
+ */
32
+ readonly handleAlarm: () => Promise<void>;
33
+ /**
34
+ * Flush any pending events.
35
+ * Should be called via waitUntil after handle/handleAlarm.
36
+ */
37
+ readonly flush: () => Promise<void>;
38
+ }
39
+ /**
40
+ * Creates a jobs runtime from DO state.
41
+ *
42
+ * This is the main entry point for the runtime layer. The DO class
43
+ * creates this once in its constructor and delegates all operations to it.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * class DurableJobsEngine extends DurableObject {
48
+ * #runtime: JobsRuntime;
49
+ *
50
+ * constructor(state: DurableObjectState, env: Env) {
51
+ * super(state, env);
52
+ * this.#runtime = createJobsRuntime({
53
+ * doState: state,
54
+ * registry: env.__JOB_REGISTRY__,
55
+ * });
56
+ * }
57
+ *
58
+ * async call(request: JobRequest): Promise<JobResponse> {
59
+ * const result = await this.#runtime.handle(request);
60
+ * this.ctx.waitUntil(this.#runtime.flush());
61
+ * return result;
62
+ * }
63
+ *
64
+ * async alarm(): Promise<void> {
65
+ * await this.#runtime.handleAlarm();
66
+ * this.ctx.waitUntil(this.#runtime.flush());
67
+ * }
68
+ * }
69
+ * ```
70
+ */
71
+ export declare function createJobsRuntime(config: JobsRuntimeConfig): JobsRuntime;
72
+ /**
73
+ * Creates a jobs runtime from a provided layer with a registry.
74
+ *
75
+ * Used for testing with in-memory adapters.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * const { layer, handles } = createTestRuntime("test-instance", 1000000);
80
+ * const runtime = createJobsRuntimeFromLayer(layer, registry);
81
+ *
82
+ * await runtime.handle({ type: "continuous", action: "start", ... });
83
+ * handles.scheduler.fire();
84
+ * await runtime.handleAlarm();
85
+ * ```
86
+ */
87
+ export declare function createJobsRuntimeFromLayer(coreLayer: RuntimeLayer, registry: RuntimeJobRegistry): JobsRuntime;
88
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2C,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIlG,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAM5D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAErC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;CACvC;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAE/D;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAqFD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,iBAAiB,GACxB,WAAW,CASb;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,YAAY,EACvB,QAAQ,EAAE,kBAAkB,GAC3B,WAAW,CAIb"}
@@ -0,0 +1,116 @@
1
+ // packages/jobs/src/runtime/runtime.ts
2
+ import { Effect, Layer } from "effect";
3
+ import { createDurableObjectRuntime, flushEvents } from "@durable-effect/core";
4
+ import { RuntimeServicesLayer, RegistryServiceLayer, JobExecutionServiceLayer, CleanupServiceLayer } from "../services";
5
+ import { JobHandlersLayer, RetryExecutorLayer } from "../handlers";
6
+ import { Dispatcher, DispatcherLayer } from "./dispatcher";
7
+ // =============================================================================
8
+ // Shared Layer Composition
9
+ // =============================================================================
10
+ /**
11
+ * Create the full dispatcher layer from a core layer and registry.
12
+ *
13
+ * This is the shared layer composition logic used by both
14
+ * createJobsRuntime and createJobsRuntimeFromLayer.
15
+ */
16
+ function createDispatcherLayer(coreLayer, registry) {
17
+ // Registry layer
18
+ const registryLayer = RegistryServiceLayer(registry);
19
+ // Runtime services layer (MetadataService, AlarmService, IdempotencyService)
20
+ const servicesLayer = RuntimeServicesLayer.pipe(Layer.provideMerge(coreLayer));
21
+ // Cleanup service layer (depends on AlarmService and StorageAdapter)
22
+ const cleanupLayer = CleanupServiceLayer.pipe(Layer.provideMerge(servicesLayer));
23
+ // Retry executor layer (depends on AlarmService from servicesLayer)
24
+ const retryLayer = RetryExecutorLayer.pipe(Layer.provideMerge(servicesLayer));
25
+ // Job Execution Service (depends on RetryExecutor, CleanupService, and Core)
26
+ const executionLayer = JobExecutionServiceLayer.pipe(Layer.provideMerge(retryLayer), Layer.provideMerge(cleanupLayer), Layer.provideMerge(coreLayer));
27
+ // Handlers layer (ContinuousHandler, DebounceHandler, etc.)
28
+ // Depends on: registry, services, retry executor, execution service
29
+ const handlersLayer = JobHandlersLayer.pipe(Layer.provideMerge(registryLayer), Layer.provideMerge(servicesLayer), Layer.provideMerge(retryLayer), Layer.provideMerge(executionLayer));
30
+ // Dispatcher layer (routes requests to handlers)
31
+ return DispatcherLayer.pipe(Layer.provideMerge(handlersLayer));
32
+ }
33
+ /**
34
+ * Create runtime implementation from dispatcher layer.
35
+ */
36
+ function createRuntimeFromDispatcherLayer(dispatcherLayer) {
37
+ // Helper to run effects with full layer stack
38
+ const runEffect = (effect) => Effect.runPromise(effect.pipe(Effect.provide(dispatcherLayer)));
39
+ return {
40
+ handle: (request) => runEffect(Effect.gen(function* () {
41
+ const dispatcher = yield* Dispatcher;
42
+ return yield* dispatcher.handle(request);
43
+ })),
44
+ handleAlarm: () => runEffect(Effect.gen(function* () {
45
+ const dispatcher = yield* Dispatcher;
46
+ yield* dispatcher.handleAlarm();
47
+ })),
48
+ flush: () => runEffect(flushEvents),
49
+ };
50
+ }
51
+ // =============================================================================
52
+ // Factory Functions
53
+ // =============================================================================
54
+ /**
55
+ * Creates a jobs runtime from DO state.
56
+ *
57
+ * This is the main entry point for the runtime layer. The DO class
58
+ * creates this once in its constructor and delegates all operations to it.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * class DurableJobsEngine extends DurableObject {
63
+ * #runtime: JobsRuntime;
64
+ *
65
+ * constructor(state: DurableObjectState, env: Env) {
66
+ * super(state, env);
67
+ * this.#runtime = createJobsRuntime({
68
+ * doState: state,
69
+ * registry: env.__JOB_REGISTRY__,
70
+ * });
71
+ * }
72
+ *
73
+ * async call(request: JobRequest): Promise<JobResponse> {
74
+ * const result = await this.#runtime.handle(request);
75
+ * this.ctx.waitUntil(this.#runtime.flush());
76
+ * return result;
77
+ * }
78
+ *
79
+ * async alarm(): Promise<void> {
80
+ * await this.#runtime.handleAlarm();
81
+ * this.ctx.waitUntil(this.#runtime.flush());
82
+ * }
83
+ * }
84
+ * ```
85
+ */
86
+ export function createJobsRuntime(config) {
87
+ if (!config.registry) {
88
+ throw new Error("createJobsRuntime requires a registry");
89
+ }
90
+ const coreLayer = createDurableObjectRuntime(config.doState);
91
+ const dispatcherLayer = createDispatcherLayer(coreLayer, config.registry);
92
+ return createRuntimeFromDispatcherLayer(dispatcherLayer);
93
+ }
94
+ // =============================================================================
95
+ // Test Runtime Factory
96
+ // =============================================================================
97
+ /**
98
+ * Creates a jobs runtime from a provided layer with a registry.
99
+ *
100
+ * Used for testing with in-memory adapters.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * const { layer, handles } = createTestRuntime("test-instance", 1000000);
105
+ * const runtime = createJobsRuntimeFromLayer(layer, registry);
106
+ *
107
+ * await runtime.handle({ type: "continuous", action: "start", ... });
108
+ * handles.scheduler.fire();
109
+ * await runtime.handleAlarm();
110
+ * ```
111
+ */
112
+ export function createJobsRuntimeFromLayer(coreLayer, registry) {
113
+ const dispatcherLayer = createDispatcherLayer(coreLayer, registry);
114
+ return createRuntimeFromDispatcherLayer(dispatcherLayer);
115
+ }
116
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"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"}