@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,283 @@
1
+ // packages/jobs/src/handlers/continuous/handler.ts
2
+ import { Context, Effect, Layer } from "effect";
3
+ import { RuntimeAdapter, StorageAdapter, } from "@durable-effect/core";
4
+ import { MetadataService } from "../../services/metadata";
5
+ import { AlarmService } from "../../services/alarm";
6
+ import { createEntityStateService } from "../../services/entity-state";
7
+ import { RegistryService } from "../../services/registry";
8
+ import { JobExecutionService } from "../../services/execution";
9
+ import { KEYS } from "../../storage-keys";
10
+ import { JobNotFoundError, ExecutionError, } from "../../errors";
11
+ import { RetryExecutor } from "../../retry";
12
+ import { createContinuousContext } from "./context";
13
+ export class ContinuousHandler extends Context.Tag("@durable-effect/jobs/ContinuousHandler")() {
14
+ }
15
+ export const ContinuousHandlerLayer = Layer.effect(ContinuousHandler, Effect.gen(function* () {
16
+ const registryService = yield* RegistryService;
17
+ const metadata = yield* MetadataService;
18
+ const alarm = yield* AlarmService;
19
+ const runtime = yield* RuntimeAdapter;
20
+ const storage = yield* StorageAdapter;
21
+ const execution = yield* JobExecutionService;
22
+ const retryExecutor = yield* RetryExecutor;
23
+ const getDefinition = (name) => {
24
+ const def = registryService.registry.continuous[name];
25
+ if (!def) {
26
+ return Effect.fail(new JobNotFoundError({ type: "continuous", name }));
27
+ }
28
+ return Effect.succeed(def);
29
+ };
30
+ const getRunCount = () => storage
31
+ .get(KEYS.CONTINUOUS.RUN_COUNT)
32
+ .pipe(Effect.map((count) => count ?? 0));
33
+ const incrementRunCount = () => Effect.gen(function* () {
34
+ const current = yield* getRunCount();
35
+ const next = current + 1;
36
+ yield* storage.put(KEYS.CONTINUOUS.RUN_COUNT, next);
37
+ return next;
38
+ });
39
+ const updateLastExecutedAt = () => Effect.gen(function* () {
40
+ const now = yield* runtime.now();
41
+ yield* storage.put(KEYS.CONTINUOUS.LAST_EXECUTED_AT, now);
42
+ });
43
+ const scheduleNext = (def) => {
44
+ const schedule = def.schedule;
45
+ switch (schedule._tag) {
46
+ case "Every":
47
+ return alarm.schedule(schedule.interval);
48
+ case "Cron":
49
+ return Effect.fail(new ExecutionError({
50
+ jobType: "continuous",
51
+ jobName: def.name,
52
+ instanceId: runtime.instanceId,
53
+ cause: new Error("Cron schedules are not supported yet"),
54
+ }));
55
+ }
56
+ };
57
+ const runExecution = (def, runCount) => execution.execute({
58
+ jobType: "continuous",
59
+ jobName: def.name,
60
+ schema: def.stateSchema,
61
+ retryConfig: def.retry,
62
+ runCount,
63
+ run: (ctx) => def.execute(ctx),
64
+ createContext: (base) => {
65
+ const proxyHolder = {
66
+ get current() {
67
+ return base.getState();
68
+ },
69
+ set current(val) {
70
+ base.setState(val);
71
+ },
72
+ get dirty() { return true; }, // Dummy, handled by service
73
+ set dirty(_) { }
74
+ };
75
+ return createContinuousContext(proxyHolder, base.instanceId, base.runCount, def.name, base.attempt);
76
+ }
77
+ });
78
+ const handleStart = (def, request) => Effect.gen(function* () {
79
+ const existing = yield* metadata.get();
80
+ if (existing) {
81
+ return {
82
+ _type: "continuous.start",
83
+ instanceId: runtime.instanceId,
84
+ created: false,
85
+ status: existing.status,
86
+ };
87
+ }
88
+ yield* metadata.initialize("continuous", request.name);
89
+ // Initial state set
90
+ // TODO: ExecutionService handles loading, but here we need to set INITIAL state
91
+ // We can use execution service to "seed" state? No, we should just use storage directly for init.
92
+ // Or we use a special "init" execution?
93
+ // Let's use direct storage access for init as before.
94
+ const stateService = yield* createEntityStateService(def.stateSchema).pipe(Effect.provideService(StorageAdapter, storage));
95
+ yield* stateService.set(request.input);
96
+ yield* storage.put(KEYS.CONTINUOUS.RUN_COUNT, 0);
97
+ yield* metadata.updateStatus("running");
98
+ let status = "running";
99
+ if (def.startImmediately !== false) {
100
+ const runCount = yield* incrementRunCount();
101
+ const result = yield* runExecution(def, runCount);
102
+ if (result.terminated) {
103
+ // Terminated - CleanupService has already purged everything
104
+ return {
105
+ _type: "continuous.start",
106
+ instanceId: runtime.instanceId,
107
+ created: true,
108
+ status: "terminated"
109
+ };
110
+ }
111
+ // Only update last executed if successful (or handled error)
112
+ if (result.success) {
113
+ yield* updateLastExecutedAt();
114
+ }
115
+ // If retry scheduled, we don't schedule next run yet (handled by retry alarm)
116
+ if (result.retryScheduled) {
117
+ // Do nothing, alarm is set
118
+ }
119
+ else if (!result.terminated) {
120
+ // Success, schedule next
121
+ yield* scheduleNext(def);
122
+ }
123
+ }
124
+ else {
125
+ yield* scheduleNext(def);
126
+ }
127
+ return {
128
+ _type: "continuous.start",
129
+ instanceId: runtime.instanceId,
130
+ created: true,
131
+ status,
132
+ };
133
+ });
134
+ const handleTerminate = (request) => Effect.gen(function* () {
135
+ const existing = yield* metadata.get();
136
+ if (!existing) {
137
+ return {
138
+ _type: "continuous.terminate",
139
+ terminated: false,
140
+ reason: "not_found",
141
+ };
142
+ }
143
+ // Cancel alarm
144
+ yield* alarm.cancel();
145
+ // Delete ALL storage (state, metadata, run count, etc.)
146
+ yield* storage.deleteAll();
147
+ return {
148
+ _type: "continuous.terminate",
149
+ terminated: true,
150
+ reason: request.reason,
151
+ };
152
+ });
153
+ const handleTrigger = (def) => Effect.gen(function* () {
154
+ const existing = yield* metadata.get();
155
+ if (!existing ||
156
+ existing.status === "stopped" ||
157
+ existing.status === "terminated") {
158
+ return {
159
+ _type: "continuous.trigger",
160
+ triggered: false,
161
+ };
162
+ }
163
+ // Reset retry state
164
+ yield* retryExecutor.reset().pipe(Effect.ignore);
165
+ const runCount = yield* incrementRunCount();
166
+ const result = yield* runExecution(def, runCount);
167
+ if (result.terminated) {
168
+ // Terminated - CleanupService has already purged everything
169
+ return {
170
+ _type: "continuous.trigger",
171
+ triggered: true,
172
+ terminated: true
173
+ };
174
+ }
175
+ if (result.retryScheduled) {
176
+ return {
177
+ _type: "continuous.trigger",
178
+ triggered: true,
179
+ retryScheduled: true
180
+ };
181
+ }
182
+ yield* updateLastExecutedAt();
183
+ yield* scheduleNext(def);
184
+ return {
185
+ _type: "continuous.trigger",
186
+ triggered: true,
187
+ };
188
+ });
189
+ const handleStatus = () => Effect.gen(function* () {
190
+ const existing = yield* metadata.get();
191
+ if (!existing) {
192
+ return {
193
+ _type: "continuous.status",
194
+ status: "not_found",
195
+ };
196
+ }
197
+ const runCount = yield* getRunCount();
198
+ const nextRunAt = yield* alarm.getScheduled();
199
+ return {
200
+ _type: "continuous.status",
201
+ status: existing.status,
202
+ nextRunAt,
203
+ runCount,
204
+ stopReason: existing.stopReason,
205
+ };
206
+ });
207
+ const handleGetState = (def) => Effect.gen(function* () {
208
+ const stateService = yield* createEntityStateService(def.stateSchema).pipe(Effect.provideService(StorageAdapter, storage));
209
+ const state = yield* stateService.get();
210
+ return {
211
+ _type: "continuous.getState",
212
+ state,
213
+ };
214
+ });
215
+ return {
216
+ handle: (request) => Effect.gen(function* () {
217
+ const def = yield* getDefinition(request.name);
218
+ switch (request.action) {
219
+ case "start":
220
+ return yield* handleStart(def, request);
221
+ case "terminate":
222
+ return yield* handleTerminate(request);
223
+ case "trigger":
224
+ return yield* handleTrigger(def);
225
+ case "status":
226
+ return yield* handleStatus();
227
+ case "getState":
228
+ return yield* handleGetState(def);
229
+ }
230
+ }).pipe(Effect.catchTag("StorageError", (e) => Effect.fail(new ExecutionError({
231
+ jobType: "continuous",
232
+ jobName: request.name,
233
+ instanceId: runtime.instanceId,
234
+ cause: e,
235
+ }))), Effect.catchTag("SchedulerError", (e) => Effect.fail(new ExecutionError({
236
+ jobType: "continuous",
237
+ jobName: request.name,
238
+ instanceId: runtime.instanceId,
239
+ cause: e,
240
+ })))),
241
+ handleAlarm: () => Effect.gen(function* () {
242
+ const meta = yield* metadata.get();
243
+ if (!meta ||
244
+ meta.status === "stopped" ||
245
+ meta.status === "terminated") {
246
+ return;
247
+ }
248
+ const def = yield* getDefinition(meta.name);
249
+ const isRetrying = yield* retryExecutor.isRetrying().pipe(Effect.catchAll(() => Effect.succeed(false)));
250
+ let runCount;
251
+ if (isRetrying) {
252
+ runCount = yield* getRunCount();
253
+ }
254
+ else {
255
+ runCount = yield* incrementRunCount();
256
+ }
257
+ const result = yield* runExecution(def, runCount);
258
+ if (result.retryScheduled) {
259
+ return;
260
+ }
261
+ if (result.terminated) {
262
+ // Terminated - CleanupService has already purged everything
263
+ return;
264
+ }
265
+ const currentMeta = yield* metadata.get();
266
+ if (currentMeta && currentMeta.status === "running") {
267
+ yield* updateLastExecutedAt();
268
+ yield* scheduleNext(def);
269
+ }
270
+ }).pipe(Effect.catchTag("StorageError", (e) => Effect.fail(new ExecutionError({
271
+ jobType: "continuous",
272
+ jobName: "unknown",
273
+ instanceId: runtime.instanceId,
274
+ cause: e,
275
+ }))), Effect.catchTag("SchedulerError", (e) => Effect.fail(new ExecutionError({
276
+ jobType: "continuous",
277
+ jobName: "unknown",
278
+ instanceId: runtime.instanceId,
279
+ cause: e,
280
+ })))),
281
+ };
282
+ }));
283
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/handlers/continuous/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { ContinuousHandler, ContinuousHandlerLayer } from "./handler";
2
+ export { createContinuousContext, type StateHolder } from "./context";
3
+ export type { ContinuousHandlerI, ContinuousResponse } from "./types";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/handlers/continuous/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,4 @@
1
+ // packages/jobs/src/handlers/continuous/index.ts
2
+ export { ContinuousHandler, ContinuousHandlerLayer } from "./handler";
3
+ export { createContinuousContext } from "./context";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/handlers/continuous/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAoB,MAAM,WAAW,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { Effect } from "effect";
2
+ import type { ContinuousRequest, ContinuousStartResponse, ContinuousTerminateResponse, ContinuousTriggerResponse, ContinuousStatusResponse, ContinuousGetStateResponse } from "../../runtime/types";
3
+ import type { JobError } from "../../errors";
4
+ /**
5
+ * Union of all continuous response types.
6
+ */
7
+ export type ContinuousResponse = ContinuousStartResponse | ContinuousTerminateResponse | ContinuousTriggerResponse | ContinuousStatusResponse | ContinuousGetStateResponse;
8
+ /**
9
+ * Continuous handler service interface.
10
+ *
11
+ * Handles all continuous job operations:
12
+ * - start: Initialize and optionally run first execution
13
+ * - terminate: Fully remove job (cancel alarm + delete all state)
14
+ * - trigger: Trigger immediate execution
15
+ * - status: Get current status
16
+ * - getState: Get current state
17
+ * - handleAlarm: Execute on schedule
18
+ */
19
+ export interface ContinuousHandlerI {
20
+ /**
21
+ * Handle a continuous request.
22
+ */
23
+ readonly handle: (request: ContinuousRequest) => Effect.Effect<ContinuousResponse, JobError>;
24
+ /**
25
+ * Handle an alarm for this continuous job.
26
+ */
27
+ readonly handleAlarm: () => Effect.Effect<void, JobError>;
28
+ }
29
+ /**
30
+ * Internal state stored alongside user state.
31
+ */
32
+ export interface ContinuousInternalState {
33
+ readonly runCount: number;
34
+ readonly lastExecutedAt: number | null;
35
+ }
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/handlers/continuous/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EACV,iBAAiB,EACjB,uBAAuB,EACvB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAM7C;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,uBAAuB,GACvB,2BAA2B,GAC3B,yBAAyB,GACzB,wBAAwB,GACxB,0BAA0B,CAAC;AAM/B;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,CACf,OAAO,EAAE,iBAAiB,KACvB,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAEjD;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;CAC3D;AAMD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC"}
@@ -0,0 +1,3 @@
1
+ // packages/jobs/src/handlers/continuous/types.ts
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/handlers/continuous/types.ts"],"names":[],"mappings":"AAAA,iDAAiD"}
@@ -0,0 +1,14 @@
1
+ import { Context, Layer } from "effect";
2
+ import { RuntimeAdapter, StorageAdapter } from "@durable-effect/core";
3
+ import { MetadataService } from "../../services/metadata";
4
+ import { AlarmService } from "../../services/alarm";
5
+ import { RegistryService } from "../../services/registry";
6
+ import { JobExecutionService } from "../../services/execution";
7
+ import { RetryExecutor } from "../../retry";
8
+ import type { DebounceHandlerI } from "./types";
9
+ declare const DebounceHandler_base: Context.TagClass<DebounceHandler, "@durable-effect/jobs/DebounceHandler", DebounceHandlerI>;
10
+ export declare class DebounceHandler extends DebounceHandler_base {
11
+ }
12
+ export declare const DebounceHandlerLayer: Layer.Layer<DebounceHandler, never, MetadataService | RuntimeAdapter | StorageAdapter | AlarmService | RegistryService | RetryExecutor | JobExecutionService>;
13
+ export {};
14
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/handlers/debounce/handler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAU,KAAK,EAAU,MAAM,QAAQ,CAAC;AACxD,OAAO,EACL,cAAc,EACd,cAAc,EAGf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAwB,MAAM,0BAA0B,CAAC;AAQrF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,SAAS,CAAC;;AAElE,qBAAa,eAAgB,SAAQ,oBAEC;CAAG;AAIzC,eAAO,MAAM,oBAAoB,+JA2VhC,CAAC"}
@@ -0,0 +1,261 @@
1
+ // packages/jobs/src/handlers/debounce/handler.ts
2
+ import { Context, Effect, Layer, Schema } from "effect";
3
+ import { RuntimeAdapter, StorageAdapter, } from "@durable-effect/core";
4
+ import { MetadataService } from "../../services/metadata";
5
+ import { AlarmService } from "../../services/alarm";
6
+ import { createEntityStateService } from "../../services/entity-state";
7
+ import { RegistryService } from "../../services/registry";
8
+ import { JobExecutionService } from "../../services/execution";
9
+ import { KEYS } from "../../storage-keys";
10
+ import { JobNotFoundError, ExecutionError, UnknownJobTypeError, } from "../../errors";
11
+ import { RetryExecutor } from "../../retry";
12
+ export class DebounceHandler extends Context.Tag("@durable-effect/jobs/DebounceHandler")() {
13
+ }
14
+ export const DebounceHandlerLayer = Layer.effect(DebounceHandler, Effect.gen(function* () {
15
+ const registryService = yield* RegistryService;
16
+ const metadata = yield* MetadataService;
17
+ const alarm = yield* AlarmService;
18
+ const runtime = yield* RuntimeAdapter;
19
+ const storage = yield* StorageAdapter;
20
+ const execution = yield* JobExecutionService;
21
+ const retryExecutor = yield* RetryExecutor;
22
+ const withStorage = (effect) => Effect.provideService(effect, StorageAdapter, storage);
23
+ const getDefinition = (name) => {
24
+ const def = registryService.registry.debounce[name];
25
+ if (!def) {
26
+ return Effect.fail(new JobNotFoundError({ type: "debounce", name }));
27
+ }
28
+ return Effect.succeed(def);
29
+ };
30
+ const getEventCount = () => storage.get(KEYS.DEBOUNCE.EVENT_COUNT).pipe(Effect.map((n) => n ?? 0));
31
+ const setEventCount = (count) => storage.put(KEYS.DEBOUNCE.EVENT_COUNT, count);
32
+ const getStartedAt = () => storage.get(KEYS.DEBOUNCE.STARTED_AT);
33
+ const setStartedAt = () => Effect.gen(function* () {
34
+ const now = yield* runtime.now();
35
+ yield* storage.put(KEYS.DEBOUNCE.STARTED_AT, now);
36
+ });
37
+ const purge = () => Effect.gen(function* () {
38
+ yield* alarm.cancel();
39
+ yield* storage.deleteAll();
40
+ });
41
+ const runFlush = (def, flushReason) => execution.execute({
42
+ jobType: "debounce",
43
+ jobName: def.name,
44
+ schema: def.stateSchema,
45
+ retryConfig: def.retry,
46
+ runCount: 0, // Debounce doesn't track runCount persistently in same way
47
+ run: (ctx) => def.execute(ctx),
48
+ createContext: (base) => {
49
+ return {
50
+ state: Effect.succeed(base.getState()), // Snapshotted state
51
+ eventCount: getEventCount().pipe(Effect.orDie), // Live event count
52
+ instanceId: base.instanceId,
53
+ debounceStartedAt: getStartedAt().pipe(Effect.orDie, Effect.map(t => t ?? 0)),
54
+ executionStartedAt: Date.now(),
55
+ flushReason,
56
+ attempt: base.attempt,
57
+ isRetry: base.isRetry
58
+ };
59
+ }
60
+ });
61
+ const handleAdd = (def, request) => Effect.gen(function* () {
62
+ const meta = yield* metadata.get();
63
+ const created = !meta;
64
+ if (created) {
65
+ yield* metadata.initialize("debounce", request.name);
66
+ yield* metadata.updateStatus("running");
67
+ yield* setStartedAt();
68
+ yield* setEventCount(0);
69
+ }
70
+ const stateService = yield* withStorage(createEntityStateService(def.stateSchema));
71
+ const currentState = yield* stateService.get();
72
+ const currentCount = yield* getEventCount();
73
+ const nextCount = currentCount + 1;
74
+ const decodeEvent = Schema.decodeUnknown(def.eventSchema);
75
+ const validatedEvent = yield* decodeEvent(request.event).pipe(Effect.mapError((e) => new ExecutionError({
76
+ jobType: "debounce",
77
+ jobName: def.name,
78
+ instanceId: runtime.instanceId,
79
+ cause: e,
80
+ })));
81
+ const stateForContext = currentState ?? validatedEvent;
82
+ const onEvent = def.onEvent;
83
+ // Cast is still needed unless we fix Definition generic constraints
84
+ const reducedState = yield* onEvent({
85
+ event: validatedEvent,
86
+ state: stateForContext,
87
+ eventCount: nextCount,
88
+ instanceId: runtime.instanceId,
89
+ });
90
+ yield* stateService.set(reducedState);
91
+ yield* setEventCount(nextCount);
92
+ if (created) {
93
+ yield* alarm.schedule(def.flushAfter);
94
+ }
95
+ const willFlushAt = yield* alarm.getScheduled();
96
+ if (def.maxEvents !== undefined && nextCount >= def.maxEvents) {
97
+ // Immediate flush
98
+ const result = yield* runFlush(def, "maxEvents");
99
+ if (result.success) {
100
+ // Success - purge state after flush
101
+ yield* purge();
102
+ }
103
+ else if (result.terminated) {
104
+ // Terminated by CleanupService - already purged
105
+ }
106
+ return {
107
+ _type: "debounce.add",
108
+ instanceId: runtime.instanceId,
109
+ eventCount: nextCount,
110
+ willFlushAt: result.retryScheduled ? ((yield* alarm.getScheduled()) ?? null) : null,
111
+ created,
112
+ retryScheduled: result.retryScheduled,
113
+ };
114
+ }
115
+ return {
116
+ _type: "debounce.add",
117
+ instanceId: runtime.instanceId,
118
+ eventCount: nextCount,
119
+ willFlushAt: willFlushAt ?? null,
120
+ created,
121
+ };
122
+ });
123
+ const handleFlush = (def, reason) => Effect.gen(function* () {
124
+ const meta = yield* metadata.get();
125
+ if (!meta) {
126
+ return {
127
+ _type: "debounce.flush",
128
+ flushed: false,
129
+ eventCount: 0,
130
+ reason: "empty",
131
+ };
132
+ }
133
+ const eventCount = yield* getEventCount();
134
+ if (eventCount === 0) {
135
+ yield* purge();
136
+ return {
137
+ _type: "debounce.flush",
138
+ flushed: false,
139
+ eventCount: 0,
140
+ reason: "empty",
141
+ };
142
+ }
143
+ const result = yield* runFlush(def, reason);
144
+ if (result.success) {
145
+ // Success - purge state after flush
146
+ yield* purge();
147
+ }
148
+ else if (result.terminated) {
149
+ // Terminated by CleanupService - already purged
150
+ }
151
+ return {
152
+ _type: "debounce.flush",
153
+ flushed: true,
154
+ eventCount,
155
+ reason,
156
+ retryScheduled: result.retryScheduled
157
+ };
158
+ });
159
+ const handleClear = () => Effect.gen(function* () {
160
+ const meta = yield* metadata.get();
161
+ if (!meta) {
162
+ return {
163
+ _type: "debounce.clear",
164
+ cleared: false,
165
+ discardedEvents: 0,
166
+ };
167
+ }
168
+ const eventCount = yield* getEventCount();
169
+ yield* purge();
170
+ return {
171
+ _type: "debounce.clear",
172
+ cleared: true,
173
+ discardedEvents: eventCount,
174
+ };
175
+ });
176
+ const handleStatus = () => Effect.gen(function* () {
177
+ const meta = yield* metadata.get();
178
+ if (!meta) {
179
+ return {
180
+ _type: "debounce.status",
181
+ status: "not_found",
182
+ };
183
+ }
184
+ const eventCount = yield* getEventCount();
185
+ const startedAt = yield* getStartedAt();
186
+ const willFlushAt = yield* alarm.getScheduled();
187
+ return {
188
+ _type: "debounce.status",
189
+ status: eventCount > 0 ? "debouncing" : "idle",
190
+ eventCount,
191
+ startedAt,
192
+ willFlushAt: willFlushAt ?? undefined,
193
+ };
194
+ });
195
+ const handleGetState = (def) => Effect.gen(function* () {
196
+ const stateService = yield* withStorage(createEntityStateService(def.stateSchema));
197
+ const state = yield* stateService.get();
198
+ return {
199
+ _type: "debounce.getState",
200
+ state,
201
+ };
202
+ });
203
+ return {
204
+ handle: (request) => Effect.gen(function* () {
205
+ const def = yield* getDefinition(request.name);
206
+ switch (request.action) {
207
+ case "add":
208
+ return yield* handleAdd(def, request);
209
+ case "flush":
210
+ return yield* handleFlush(def, "manual");
211
+ case "clear":
212
+ return yield* handleClear();
213
+ case "status":
214
+ return yield* handleStatus();
215
+ case "getState":
216
+ return yield* handleGetState(def);
217
+ default:
218
+ return yield* Effect.fail(new UnknownJobTypeError({ type: `debounce/${request.action}` }));
219
+ }
220
+ }).pipe(Effect.catchTag("StorageError", (e) => Effect.fail(new ExecutionError({
221
+ jobType: "debounce",
222
+ jobName: request.name,
223
+ instanceId: runtime.instanceId,
224
+ cause: e,
225
+ }))), Effect.catchTag("SchedulerError", (e) => Effect.fail(new ExecutionError({
226
+ jobType: "debounce",
227
+ jobName: request.name,
228
+ instanceId: runtime.instanceId,
229
+ cause: e,
230
+ })))),
231
+ handleAlarm: () => Effect.gen(function* () {
232
+ const meta = yield* metadata.get();
233
+ if (!meta || meta.status === "stopped" || meta.status === "terminated") {
234
+ return;
235
+ }
236
+ const def = yield* getDefinition(meta.name);
237
+ // Check if this is a retry alarm
238
+ const isRetrying = yield* retryExecutor.isRetrying().pipe(Effect.catchAll(() => Effect.succeed(false)));
239
+ // Reset retry state if manual trigger while retrying
240
+ if (!isRetrying) {
241
+ yield* retryExecutor.reset().pipe(Effect.ignore);
242
+ }
243
+ const result = yield* handleFlush(def, "flushAfter");
244
+ void result;
245
+ // Note: handleFlush already purges on success.
246
+ // If retryScheduled, handleFlush returns retryScheduled=true.
247
+ // We don't need to do anything else.
248
+ }).pipe(Effect.catchTag("StorageError", (e) => Effect.fail(new ExecutionError({
249
+ jobType: "debounce",
250
+ jobName: "unknown",
251
+ instanceId: runtime.instanceId,
252
+ cause: e,
253
+ }))), Effect.catchTag("SchedulerError", (e) => Effect.fail(new ExecutionError({
254
+ jobType: "debounce",
255
+ jobName: "unknown",
256
+ instanceId: runtime.instanceId,
257
+ cause: e,
258
+ })))),
259
+ };
260
+ }));
261
+ //# sourceMappingURL=handler.js.map