@effect/platform-cloudflare 0.0.0-stage → 4.1.3

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 (237) hide show
  1. package/AGENTS.md +434 -0
  2. package/CLAUDE.md +434 -0
  3. package/LICENSE +21 -0
  4. package/README.md +505 -2
  5. package/ai-docs/README.md +44 -0
  6. package/ai-docs/package.json +36 -0
  7. package/ai-docs/src/01_effect/01_basics/01_effect-gen.ts +30 -0
  8. package/ai-docs/src/01_effect/01_basics/02_effect-fn.ts +52 -0
  9. package/ai-docs/src/01_effect/01_basics/10_creating-effects.ts +74 -0
  10. package/ai-docs/src/01_effect/01_basics/index.md +7 -0
  11. package/ai-docs/src/01_effect/02_schema/10_schema-basics.ts +43 -0
  12. package/ai-docs/src/01_effect/02_schema/index.md +7 -0
  13. package/ai-docs/src/01_effect/03_services/01_service.ts +45 -0
  14. package/ai-docs/src/01_effect/03_services/10_reference.ts +10 -0
  15. package/ai-docs/src/01_effect/03_services/20_layer-composition.ts +70 -0
  16. package/ai-docs/src/01_effect/03_services/20_layer-unwrap.ts +66 -0
  17. package/ai-docs/src/01_effect/03_services/index.md +5 -0
  18. package/ai-docs/src/01_effect/04_errors/01_error-handling.ts +30 -0
  19. package/ai-docs/src/01_effect/04_errors/10_catch-tags.ts +24 -0
  20. package/ai-docs/src/01_effect/04_errors/20_reason-errors.ts +64 -0
  21. package/ai-docs/src/01_effect/04_errors/index.md +1 -0
  22. package/ai-docs/src/01_effect/05_resources/10_acquire-release.ts +105 -0
  23. package/ai-docs/src/01_effect/05_resources/20_layer-side-effects.ts +31 -0
  24. package/ai-docs/src/01_effect/05_resources/30_layer-map.ts +86 -0
  25. package/ai-docs/src/01_effect/05_resources/index.md +3 -0
  26. package/ai-docs/src/01_effect/06_running/10_run-main.ts +30 -0
  27. package/ai-docs/src/01_effect/06_running/20_layer-launch.ts +27 -0
  28. package/ai-docs/src/01_effect/06_running/index.md +1 -0
  29. package/ai-docs/src/01_effect/07_pubsub/10_pubsub.ts +56 -0
  30. package/ai-docs/src/01_effect/07_pubsub/index.md +3 -0
  31. package/ai-docs/src/03_stream/10_creating-streams.ts +103 -0
  32. package/ai-docs/src/03_stream/20_consuming-streams.ts +137 -0
  33. package/ai-docs/src/03_stream/30_encoding.ts +163 -0
  34. package/ai-docs/src/03_stream/index.md +4 -0
  35. package/ai-docs/src/04_integration/10_managed-runtime.ts +129 -0
  36. package/ai-docs/src/04_integration/index.md +5 -0
  37. package/ai-docs/src/05_batching/10_request-resolver.ts +89 -0
  38. package/ai-docs/src/05_batching/index.md +3 -0
  39. package/ai-docs/src/06_schedule/10_schedules.ts +111 -0
  40. package/ai-docs/src/06_schedule/index.md +3 -0
  41. package/ai-docs/src/07_datetime/10_creating-and-formatting.ts +30 -0
  42. package/ai-docs/src/07_datetime/20_time-zones.ts +44 -0
  43. package/ai-docs/src/07_datetime/index.md +5 -0
  44. package/ai-docs/src/08_observability/10_logging.ts +66 -0
  45. package/ai-docs/src/08_observability/20_otlp-tracing.ts +95 -0
  46. package/ai-docs/src/08_observability/index.md +7 -0
  47. package/ai-docs/src/09_testing/10_effect-tests.ts +55 -0
  48. package/ai-docs/src/09_testing/20_layer-tests.ts +138 -0
  49. package/ai-docs/src/09_testing/index.md +1 -0
  50. package/ai-docs/src/10_predicate/01_basics.ts +14 -0
  51. package/ai-docs/src/10_predicate/index.md +9 -0
  52. package/ai-docs/src/40_sql/10_basics.ts +175 -0
  53. package/ai-docs/src/40_sql/index.md +6 -0
  54. package/ai-docs/src/50_http-client/10_basics.ts +102 -0
  55. package/ai-docs/src/50_http-client/index.md +3 -0
  56. package/ai-docs/src/51_http-server/10_basics.ts +118 -0
  57. package/ai-docs/src/51_http-server/20_testing.ts +100 -0
  58. package/ai-docs/src/51_http-server/fixtures/api/Api.ts +14 -0
  59. package/ai-docs/src/51_http-server/fixtures/api/Authorization.ts +36 -0
  60. package/ai-docs/src/51_http-server/fixtures/api/System.ts +10 -0
  61. package/ai-docs/src/51_http-server/fixtures/api/Users.ts +107 -0
  62. package/ai-docs/src/51_http-server/fixtures/domain/User.ts +21 -0
  63. package/ai-docs/src/51_http-server/fixtures/domain/UserErrors.ts +22 -0
  64. package/ai-docs/src/51_http-server/fixtures/server/Authorization.ts +37 -0
  65. package/ai-docs/src/51_http-server/fixtures/server/Users/http.ts +80 -0
  66. package/ai-docs/src/51_http-server/fixtures/server/Users.ts +183 -0
  67. package/ai-docs/src/51_http-server/index.md +3 -0
  68. package/ai-docs/src/52_graphql/10_basics.ts +117 -0
  69. package/ai-docs/src/52_graphql/20_testing.ts +45 -0
  70. package/ai-docs/src/52_graphql/30_batching.ts +118 -0
  71. package/ai-docs/src/52_graphql/40_aliased-batching.ts +124 -0
  72. package/ai-docs/src/52_graphql/50_errors-and-retries.ts +74 -0
  73. package/ai-docs/src/52_graphql/index.md +6 -0
  74. package/ai-docs/src/60_child-process/10_working-with-child-processes.ts +117 -0
  75. package/ai-docs/src/60_child-process/index.md +3 -0
  76. package/ai-docs/src/70_cli/10_basics.ts +162 -0
  77. package/ai-docs/src/70_cli/index.md +5 -0
  78. package/ai-docs/src/71_ai/10_language-model.ts +156 -0
  79. package/ai-docs/src/71_ai/20_tools.ts +226 -0
  80. package/ai-docs/src/71_ai/30_chat.ts +158 -0
  81. package/ai-docs/src/71_ai/fixtures/domain/LaunchPlan.ts +9 -0
  82. package/ai-docs/src/71_ai/index.md +5 -0
  83. package/ai-docs/src/80_cluster/10_entities.ts +97 -0
  84. package/ai-docs/src/80_cluster/index.md +4 -0
  85. package/ai-docs/src/index.md +10 -0
  86. package/ai-docs/tsconfig.json +28 -0
  87. package/dist/AlchemyCloudflareCluster.d.ts +134 -0
  88. package/dist/AlchemyCloudflareCluster.d.ts.map +1 -0
  89. package/dist/AlchemyCloudflareCluster.js +111 -0
  90. package/dist/AlchemyCloudflareCluster.js.map +1 -0
  91. package/dist/CloudflareCluster.d.ts +196 -0
  92. package/dist/CloudflareCluster.d.ts.map +1 -0
  93. package/dist/CloudflareCluster.js +533 -0
  94. package/dist/CloudflareCluster.js.map +1 -0
  95. package/dist/CloudflareDurableObjectPrograms.d.ts +279 -0
  96. package/dist/CloudflareDurableObjectPrograms.d.ts.map +1 -0
  97. package/dist/CloudflareDurableObjectPrograms.js +295 -0
  98. package/dist/CloudflareDurableObjectPrograms.js.map +1 -0
  99. package/dist/CloudflareDurableObjects.d.ts +149 -0
  100. package/dist/CloudflareDurableObjects.d.ts.map +1 -0
  101. package/dist/CloudflareDurableObjects.js +337 -0
  102. package/dist/CloudflareDurableObjects.js.map +1 -0
  103. package/dist/CloudflarePersistedQueue.d.ts +36 -0
  104. package/dist/CloudflarePersistedQueue.d.ts.map +1 -0
  105. package/dist/CloudflarePersistedQueue.js +122 -0
  106. package/dist/CloudflarePersistedQueue.js.map +1 -0
  107. package/dist/CloudflareWorkflowEngine.d.ts +72 -0
  108. package/dist/CloudflareWorkflowEngine.d.ts.map +1 -0
  109. package/dist/CloudflareWorkflowEngine.js +187 -0
  110. package/dist/CloudflareWorkflowEngine.js.map +1 -0
  111. package/dist/index.d.ts +29 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +33 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/internal/alchemyCluster.d.ts +2 -0
  116. package/dist/internal/alchemyCluster.d.ts.map +1 -0
  117. package/dist/internal/alchemyCluster.js +75 -0
  118. package/dist/internal/alchemyCluster.js.map +1 -0
  119. package/dist/internal/boundedMap.d.ts +3 -0
  120. package/dist/internal/boundedMap.d.ts.map +1 -0
  121. package/dist/internal/boundedMap.js +15 -0
  122. package/dist/internal/boundedMap.js.map +1 -0
  123. package/dist/internal/cluster.d.ts +57 -0
  124. package/dist/internal/cluster.d.ts.map +1 -0
  125. package/dist/internal/cluster.js +2 -0
  126. package/dist/internal/cluster.js.map +1 -0
  127. package/dist/internal/clusterName.d.ts +2 -0
  128. package/dist/internal/clusterName.d.ts.map +1 -0
  129. package/dist/internal/clusterName.js +16 -0
  130. package/dist/internal/clusterName.js.map +1 -0
  131. package/dist/internal/entityKeepAlive.d.ts +2 -0
  132. package/dist/internal/entityKeepAlive.d.ts.map +1 -0
  133. package/dist/internal/entityKeepAlive.js +73 -0
  134. package/dist/internal/entityKeepAlive.js.map +1 -0
  135. package/dist/internal/entityMailbox.d.ts +2 -0
  136. package/dist/internal/entityMailbox.d.ts.map +1 -0
  137. package/dist/internal/entityMailbox.js +160 -0
  138. package/dist/internal/entityMailbox.js.map +1 -0
  139. package/dist/internal/entityRegistry.d.ts +16 -0
  140. package/dist/internal/entityRegistry.d.ts.map +1 -0
  141. package/dist/internal/entityRegistry.js +22 -0
  142. package/dist/internal/entityRegistry.js.map +1 -0
  143. package/dist/internal/entityReply.d.ts +2 -0
  144. package/dist/internal/entityReply.d.ts.map +1 -0
  145. package/dist/internal/entityReply.js +35 -0
  146. package/dist/internal/entityReply.js.map +1 -0
  147. package/dist/internal/entityRuntime.d.ts +2 -0
  148. package/dist/internal/entityRuntime.d.ts.map +1 -0
  149. package/dist/internal/entityRuntime.js +823 -0
  150. package/dist/internal/entityRuntime.js.map +1 -0
  151. package/dist/internal/entitySql.d.ts +2 -0
  152. package/dist/internal/entitySql.d.ts.map +1 -0
  153. package/dist/internal/entitySql.js +29 -0
  154. package/dist/internal/entitySql.js.map +1 -0
  155. package/dist/internal/entityStorage.d.ts +2 -0
  156. package/dist/internal/entityStorage.d.ts.map +1 -0
  157. package/dist/internal/entityStorage.js +98 -0
  158. package/dist/internal/entityStorage.js.map +1 -0
  159. package/dist/internal/entityWire.d.ts +2 -0
  160. package/dist/internal/entityWire.d.ts.map +1 -0
  161. package/dist/internal/entityWire.js +146 -0
  162. package/dist/internal/entityWire.js.map +1 -0
  163. package/dist/internal/queueRuntime.d.ts +2 -0
  164. package/dist/internal/queueRuntime.d.ts.map +1 -0
  165. package/dist/internal/queueRuntime.js +88 -0
  166. package/dist/internal/queueRuntime.js.map +1 -0
  167. package/dist/internal/queueStorage.d.ts +2 -0
  168. package/dist/internal/queueStorage.d.ts.map +1 -0
  169. package/dist/internal/queueStorage.js +129 -0
  170. package/dist/internal/queueStorage.js.map +1 -0
  171. package/dist/internal/registry.d.ts +10 -0
  172. package/dist/internal/registry.d.ts.map +1 -0
  173. package/dist/internal/registry.js +24 -0
  174. package/dist/internal/registry.js.map +1 -0
  175. package/dist/internal/singletonRegistry.d.ts +2 -0
  176. package/dist/internal/singletonRegistry.d.ts.map +1 -0
  177. package/dist/internal/singletonRegistry.js +9 -0
  178. package/dist/internal/singletonRegistry.js.map +1 -0
  179. package/dist/internal/singletonRuntime.d.ts +2 -0
  180. package/dist/internal/singletonRuntime.d.ts.map +1 -0
  181. package/dist/internal/singletonRuntime.js +42 -0
  182. package/dist/internal/singletonRuntime.js.map +1 -0
  183. package/dist/internal/singletonStorage.d.ts +2 -0
  184. package/dist/internal/singletonStorage.d.ts.map +1 -0
  185. package/dist/internal/singletonStorage.js +34 -0
  186. package/dist/internal/singletonStorage.js.map +1 -0
  187. package/dist/internal/transport.d.ts +2 -0
  188. package/dist/internal/transport.d.ts.map +1 -0
  189. package/dist/internal/transport.js +49 -0
  190. package/dist/internal/transport.js.map +1 -0
  191. package/dist/internal/workflowRegistry.d.ts +2 -0
  192. package/dist/internal/workflowRegistry.d.ts.map +1 -0
  193. package/dist/internal/workflowRegistry.js +29 -0
  194. package/dist/internal/workflowRegistry.js.map +1 -0
  195. package/dist/internal/workflowRuntime.d.ts +2 -0
  196. package/dist/internal/workflowRuntime.d.ts.map +1 -0
  197. package/dist/internal/workflowRuntime.js +322 -0
  198. package/dist/internal/workflowRuntime.js.map +1 -0
  199. package/dist/internal/workflowStorage.d.ts +2 -0
  200. package/dist/internal/workflowStorage.d.ts.map +1 -0
  201. package/dist/internal/workflowStorage.js +113 -0
  202. package/dist/internal/workflowStorage.js.map +1 -0
  203. package/dist/internal/workflowWire.d.ts +2 -0
  204. package/dist/internal/workflowWire.d.ts.map +1 -0
  205. package/dist/internal/workflowWire.js +52 -0
  206. package/dist/internal/workflowWire.js.map +1 -0
  207. package/package.json +74 -3
  208. package/src/AlchemyCloudflareCluster.ts +200 -0
  209. package/src/CloudflareCluster.ts +704 -0
  210. package/src/CloudflareDurableObjectPrograms.ts +543 -0
  211. package/src/CloudflareDurableObjects.ts +430 -0
  212. package/src/CloudflarePersistedQueue.ts +189 -0
  213. package/src/CloudflareWorkflowEngine.ts +220 -0
  214. package/src/index.ts +38 -0
  215. package/src/internal/alchemyCluster.ts +120 -0
  216. package/src/internal/boundedMap.ts +15 -0
  217. package/src/internal/cluster.ts +57 -0
  218. package/src/internal/clusterName.ts +19 -0
  219. package/src/internal/entityKeepAlive.ts +121 -0
  220. package/src/internal/entityMailbox.ts +324 -0
  221. package/src/internal/entityRegistry.ts +46 -0
  222. package/src/internal/entityReply.ts +54 -0
  223. package/src/internal/entityRuntime.ts +1318 -0
  224. package/src/internal/entitySql.ts +60 -0
  225. package/src/internal/entityStorage.ts +168 -0
  226. package/src/internal/entityWire.ts +204 -0
  227. package/src/internal/queueRuntime.ts +174 -0
  228. package/src/internal/queueStorage.ts +255 -0
  229. package/src/internal/registry.ts +31 -0
  230. package/src/internal/singletonRegistry.ts +21 -0
  231. package/src/internal/singletonRuntime.ts +88 -0
  232. package/src/internal/singletonStorage.ts +64 -0
  233. package/src/internal/transport.ts +67 -0
  234. package/src/internal/workflowRegistry.ts +78 -0
  235. package/src/internal/workflowRuntime.ts +443 -0
  236. package/src/internal/workflowStorage.ts +234 -0
  237. package/src/internal/workflowWire.ts +123 -0
@@ -0,0 +1,149 @@
1
+ /**
2
+ * The Durable Object classes behind `CloudflareCluster.layer`.
3
+ *
4
+ * A Worker using the Cloudflare cluster re-exports these four classes from its
5
+ * entry module and binds each one in `wrangler.jsonc` as a SQLite-backed
6
+ * Durable Object class. The cluster resolves objects through the same-Worker
7
+ * namespace bindings only; none of these classes serve a public route, and any
8
+ * direct `fetch` of an object is rejected.
9
+ *
10
+ * @stability experimental
11
+ * @since 4.1.3
12
+ */
13
+ import { DurableObject } from "cloudflare:workers";
14
+ /**
15
+ * Initializes the Worker application before a Cloudflare cluster Durable
16
+ * Object handles requests or alarms. The initializer is shared by all four
17
+ * Durable Object classes and runs once per Worker isolate unless a build fails
18
+ * or stalls.
19
+ *
20
+ * **Details**
21
+ *
22
+ * The initializer runs inside a Durable Object constructor's
23
+ * `blockConcurrencyWhile`, which Cloudflare cancels after 30 seconds. It must
24
+ * complete within 15 seconds: a build still pending after that is treated as
25
+ * abandoned, and a waiting object runs the initializer again.
26
+ *
27
+ * @stability experimental
28
+ * @category models
29
+ * @since 4.1.3
30
+ */
31
+ export type Initializer<Env = unknown, A = unknown> = (env: Env) => PromiseLike<A>;
32
+ /**
33
+ * Registers the Worker application initializer used by the Cloudflare cluster
34
+ * Durable Object classes.
35
+ *
36
+ * **Details**
37
+ *
38
+ * Call this once from the Worker entry module with the same lazy application
39
+ * build used by its request handlers. Every entity, workflow, queue, and
40
+ * singleton object blocks requests and alarms until that build completes. A
41
+ * failure is reported to every caller already waiting on that build, and the
42
+ * next cold caller runs the initializer again. The initializer must complete
43
+ * within 15 seconds. A build still pending after that is treated as abandoned,
44
+ * and a waiter runs the initializer itself, so a build can run more than once
45
+ * in an isolate. A Durable Object waiter starts a build only while it has
46
+ * waited less than 15 seconds, so any replacement keeps at least 15 seconds of
47
+ * the 30 second `blockConcurrencyWhile` limit. The returned function joins the
48
+ * same readiness state from Worker handlers.
49
+ *
50
+ * @stability experimental
51
+ * @category initialization
52
+ * @since 4.1.3
53
+ */
54
+ export declare const setInitializer: <Env, A>(handler: Initializer<Env, A>) => (env: Env) => Promise<A>;
55
+ /**
56
+ * The shared entity class. One instance holds one entity address; the handlers
57
+ * for every `EntityType` are registered at Worker init.
58
+ *
59
+ * **Details**
60
+ *
61
+ * The constructor stays cheap: it opens SQLite, ensures the mailbox tables,
62
+ * and re-arms the single alarm from the earliest pending `deliver_at`, or the
63
+ * keep-alive heartbeat when the entity holds `Entity.keepAlive`. User
64
+ * handlers are never built in the constructor; requests and alarms wait for
65
+ * the registered {@link setInitializer} callback, then handlers are built once
66
+ * per wake. Each build gets a `DurableObjectSqlClient` on this object's SQLite
67
+ * storage; tables whose names start with `cluster_` are reserved for the mailbox.
68
+ *
69
+ * @stability experimental
70
+ * @category durable objects
71
+ * @since 4.1.3
72
+ */
73
+ export declare class ClusterEntity extends DurableObject<unknown> {
74
+ #private;
75
+ constructor(ctx: DurableObjectState, env: unknown);
76
+ alarm(): Promise<void>;
77
+ fetch: () => never;
78
+ }
79
+ /**
80
+ * The workflow execution class behind `CloudflareWorkflowEngine`. One
81
+ * instance holds one workflow execution: run state, activity results keyed
82
+ * `${name}/${attempt}`, durable deferred exits, and the clock due table.
83
+ *
84
+ * **Details**
85
+ *
86
+ * The constructor stays cheap: it opens SQLite, ensures the workflow tables,
87
+ * and re-arms the single alarm from the earliest pending clock. Workflow
88
+ * requests and alarms wait for the registered {@link setInitializer} callback
89
+ * before handlers are looked up in the module-level registry and built once
90
+ * per wake.
91
+ *
92
+ * @stability experimental
93
+ * @category durable objects
94
+ * @since 4.1.3
95
+ */
96
+ export declare class ClusterWorkflow extends DurableObject<unknown> {
97
+ #private;
98
+ constructor(ctx: DurableObjectState, env: unknown);
99
+ alarm(): Promise<void>;
100
+ fetch: () => never;
101
+ }
102
+ /**
103
+ * The durable queue class behind the `PersistedQueue` implementation used by
104
+ * `DurableQueue`. One instance holds one named queue.
105
+ *
106
+ * **Details**
107
+ *
108
+ * The constructor stays cheap: it opens SQLite, ensures the queue table, and
109
+ * re-arms the single alarm from the earliest pending lease expiry. Items are
110
+ * leased to takers for a bounded time; the alarm watchdog expires overdue
111
+ * leases so an item whose worker died is redelivered. Requests and alarms wait
112
+ * for the registered {@link setInitializer} callback first.
113
+ *
114
+ * @stability experimental
115
+ * @category durable objects
116
+ * @since 4.1.3
117
+ */
118
+ export declare class ClusterDurableQueue extends DurableObject<unknown> {
119
+ #private;
120
+ constructor(ctx: DurableObjectState, env: unknown);
121
+ alarm(): Promise<void>;
122
+ fetch: () => never;
123
+ }
124
+ /**
125
+ * The singleton class. One object holds one registered singleton under the
126
+ * name `Singleton/<name>` and is woken by a Worker Cron Trigger.
127
+ *
128
+ * **Details**
129
+ *
130
+ * The constructor opens SQLite, ensures the singleton state table, and
131
+ * re-arms the watchdog alarm for a wake interrupted by isolate loss. `wake()`
132
+ * runs the registered effect once and returns; it never appends
133
+ * `Effect.never`, so Cloudflare may hibernate the object afterward. A failed
134
+ * run is logged and resolves `wake()` with a `Failure`, so only a transport
135
+ * failure rejects it. Requests
136
+ * and alarms wait for the registered {@link setInitializer} callback before
137
+ * consulting the singleton registry.
138
+ *
139
+ * @stability experimental
140
+ * @category durable objects
141
+ * @since 4.1.3
142
+ */
143
+ export declare class ClusterSingleton extends DurableObject<unknown> {
144
+ #private;
145
+ constructor(ctx: DurableObjectState, env: unknown);
146
+ alarm(): Promise<void>;
147
+ fetch: () => never;
148
+ }
149
+ //# sourceMappingURL=CloudflareDurableObjects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflareDurableObjects.d.ts","sourceRoot":"","sources":["../src/CloudflareDurableObjects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAyBlD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,WAAW,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,WAAW,CAAC,CAAC,CAAC,CAAA;AA0BlF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,cAAc,GAAI,GAAG,EAAE,CAAC,WAAW,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,KAAG,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAQ5F,CAAA;AAiED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAc,SAAQ,aAAa,CAAC,OAAO,CAAC;;IAIvD,YAAY,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,OAAO,EAKhD;IAEQ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9B;IAgCQ,KAAK,EAAE,MAAM,KAAK,CAA8B;CAC1D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,eAAgB,SAAQ,aAAa,CAAC,OAAO,CAAC;;IAIzD,YAAY,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,OAAO,EAKhD;IAqCQ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9B;IAEQ,KAAK,EAAE,MAAM,KAAK,CAAgC;CAC5D;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,mBAAoB,SAAQ,aAAa,CAAC,OAAO,CAAC;;IAI7D,YAAY,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,OAAO,EAKhD;IA8CQ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9B;IAEQ,KAAK,EAAE,MAAM,KAAK,CAAoC;CAChE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,gBAAiB,SAAQ,aAAa,CAAC,OAAO,CAAC;;IAI1D,YAAY,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,OAAO,EAKhD;IAOQ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9B;IAEQ,KAAK,EAAE,MAAM,KAAK,CAAiC;CAC7D"}
@@ -0,0 +1,337 @@
1
+ /**
2
+ * The Durable Object classes behind `CloudflareCluster.layer`.
3
+ *
4
+ * A Worker using the Cloudflare cluster re-exports these four classes from its
5
+ * entry module and binds each one in `wrangler.jsonc` as a SQLite-backed
6
+ * Durable Object class. The cluster resolves objects through the same-Worker
7
+ * namespace bindings only; none of these classes serve a public route, and any
8
+ * direct `fetch` of an object is rejected.
9
+ *
10
+ * @stability experimental
11
+ * @since 4.1.3
12
+ */
13
+ import { DurableObject } from "cloudflare:workers";
14
+ import * as Effect from "effect/Effect";
15
+ import { makeClusterDurableQueueProgram, makeClusterEntityProgram, makeClusterSingletonProgram, makeClusterWorkflowProgram } from "./CloudflareDurableObjectPrograms.js";
16
+ const notExposed = className => () => {
17
+ throw new Error(`@effect/platform-cloudflare: ${className} is not exposed over fetch, use the same-Worker namespace binding`);
18
+ };
19
+ // Durable Object waiters run inside `blockConcurrencyWhile`, which Cloudflare
20
+ // cancels after 30 seconds. A build still pending after 15 seconds is treated
21
+ // as abandoned. Only a Durable Object waiter that has itself waited less than
22
+ // 15 seconds starts a build, whether it takes over a stale one or retries after
23
+ // a failure. The first build and any replacement therefore both get at least
24
+ // 15 seconds.
25
+ const staleInitializationMillis = 15_000;
26
+ const durableObjectTakeoverMillis = 15_000;
27
+ const initializationPollMillis = 20;
28
+ let initializer;
29
+ let initialization;
30
+ /**
31
+ * Registers the Worker application initializer used by the Cloudflare cluster
32
+ * Durable Object classes.
33
+ *
34
+ * **Details**
35
+ *
36
+ * Call this once from the Worker entry module with the same lazy application
37
+ * build used by its request handlers. Every entity, workflow, queue, and
38
+ * singleton object blocks requests and alarms until that build completes. A
39
+ * failure is reported to every caller already waiting on that build, and the
40
+ * next cold caller runs the initializer again. The initializer must complete
41
+ * within 15 seconds. A build still pending after that is treated as abandoned,
42
+ * and a waiter runs the initializer itself, so a build can run more than once
43
+ * in an isolate. A Durable Object waiter starts a build only while it has
44
+ * waited less than 15 seconds, so any replacement keeps at least 15 seconds of
45
+ * the 30 second `blockConcurrencyWhile` limit. The returned function joins the
46
+ * same readiness state from Worker handlers.
47
+ *
48
+ * @stability experimental
49
+ * @category initialization
50
+ * @since 4.1.3
51
+ */
52
+ export const setInitializer = handler => {
53
+ if (initializer !== undefined) {
54
+ throw new Error("@effect/platform-cloudflare: the Durable Object initializer is already set");
55
+ }
56
+ initializer = handler;
57
+ // Worker handlers are not bounded by `blockConcurrencyWhile`, so they may
58
+ // take over a stale build however long they have waited.
59
+ return env => waitForInitialization(env, Infinity);
60
+ };
61
+ const waitForInitialization = async (env, takeoverMillis) => {
62
+ if (initializer === undefined) return;
63
+ const waitStartedAt = Date.now();
64
+ const isFresh = () => Date.now() - waitStartedAt < takeoverMillis;
65
+ const canTakeOver = attempt => isStale(attempt) && isFresh();
66
+ // A waiter too old to take over keeps following the current attempt.
67
+ const keepsWaiting = attempt => attempt.exit === undefined && initialization === attempt && !canTakeOver(attempt);
68
+ while (true) {
69
+ const attempt = initialization;
70
+ if (attempt === undefined ? isFresh() : canTakeOver(attempt)) {
71
+ return runInitializer(initializer, env);
72
+ }
73
+ if (attempt === undefined) {
74
+ // The attempt this waiter followed was replaced by one that already
75
+ // failed. A waiter this old leaves the retry to a fresher caller and
76
+ // follows the attempt that caller starts.
77
+ await scheduler.wait(initializationPollMillis);
78
+ continue;
79
+ }
80
+ // Cloudflare promises belong to the request context that created them. A
81
+ // fresh wait in this context observes the shared plain-JavaScript state
82
+ // without awaiting the first Durable Object's promise from another event.
83
+ while (keepsWaiting(attempt)) {
84
+ await scheduler.wait(initializationPollMillis);
85
+ }
86
+ if (attempt.exit === undefined) continue;
87
+ if (attempt.exit._tag === "Failure") throw attempt.exit.error;
88
+ return attempt.exit.value;
89
+ }
90
+ };
91
+ const isStale = attempt => attempt.exit === undefined && Date.now() - attempt.startedAt >= staleInitializationMillis;
92
+ const runInitializer = async (run, env) => {
93
+ const attempt = {
94
+ startedAt: Date.now(),
95
+ exit: undefined
96
+ };
97
+ initialization = attempt;
98
+ try {
99
+ const value = await run(env);
100
+ attempt.exit = {
101
+ _tag: "Success",
102
+ value
103
+ };
104
+ // An abandoned build that settles late still makes the isolate ready.
105
+ if (initialization?.exit?._tag !== "Success") initialization = attempt;
106
+ return value;
107
+ } catch (error) {
108
+ attempt.exit = {
109
+ _tag: "Failure",
110
+ error
111
+ };
112
+ // Waiters holding this attempt see the failure; the next cold caller retries.
113
+ if (initialization === attempt) initialization = undefined;
114
+ throw error;
115
+ }
116
+ };
117
+ const blockOnInitialization = (ctx, env, after) => {
118
+ void ctx.blockConcurrencyWhile(async () => {
119
+ await waitForInitialization(env, durableObjectTakeoverMillis);
120
+ if (after !== undefined) await after();
121
+ });
122
+ };
123
+ /**
124
+ * The shared entity class. One instance holds one entity address; the handlers
125
+ * for every `EntityType` are registered at Worker init.
126
+ *
127
+ * **Details**
128
+ *
129
+ * The constructor stays cheap: it opens SQLite, ensures the mailbox tables,
130
+ * and re-arms the single alarm from the earliest pending `deliver_at`, or the
131
+ * keep-alive heartbeat when the entity holds `Entity.keepAlive`. User
132
+ * handlers are never built in the constructor; requests and alarms wait for
133
+ * the registered {@link setInitializer} callback, then handlers are built once
134
+ * per wake. Each build gets a `DurableObjectSqlClient` on this object's SQLite
135
+ * storage; tables whose names start with `cluster_` are reserved for the mailbox.
136
+ *
137
+ * @stability experimental
138
+ * @category durable objects
139
+ * @since 4.1.3
140
+ */
141
+ export class ClusterEntity extends DurableObject {
142
+ // blockConcurrencyWhile completes this assignment before any RPC or alarm.
143
+ #program;
144
+ constructor(ctx, env) {
145
+ super(ctx, env);
146
+ blockOnInitialization(ctx, env, async () => {
147
+ this.#program = await Effect.runPromise(makeClusterEntityProgram(ctx));
148
+ });
149
+ }
150
+ alarm() {
151
+ return Effect.runPromise(this.#program.alarm());
152
+ }
153
+ /** @internal Keeps this object non-hibernateable while entity resources have holders. */
154
+ hold() {
155
+ return Effect.runPromise(this.#program.hold());
156
+ }
157
+ /** @internal Same-Worker RPC transport used by `CloudflareCluster.layer`. */
158
+ invoke(envelopeText, discard, delivery) {
159
+ return Effect.runPromise(this.#program.invoke(envelopeText, discard, delivery));
160
+ }
161
+ /** @internal Acknowledges a streamed chunk. */
162
+ acknowledge(requestId, replyId) {
163
+ return Effect.runPromise(this.#program.acknowledge(requestId, replyId));
164
+ }
165
+ /** @internal Interrupts a handler execution and completes its persisted ask, if any. */
166
+ interrupt(storageRequestId, clientRequestId = storageRequestId) {
167
+ return Effect.runPromise(this.#program.interrupt(storageRequestId, clientRequestId));
168
+ }
169
+ /** @internal Clears stored replies so a reset request replays from scratch. */
170
+ reset(requestId) {
171
+ return Effect.runPromise(this.#program.reset(requestId));
172
+ }
173
+ /** @internal Completes an in-memory delayed ask owned by this entity object. */
174
+ deliverReply(requestId, reply) {
175
+ return Effect.runPromise(this.#program.deliverReply(requestId, reply));
176
+ }
177
+ fetch = /*#__PURE__*/notExposed("ClusterEntity");
178
+ }
179
+ /**
180
+ * The workflow execution class behind `CloudflareWorkflowEngine`. One
181
+ * instance holds one workflow execution: run state, activity results keyed
182
+ * `${name}/${attempt}`, durable deferred exits, and the clock due table.
183
+ *
184
+ * **Details**
185
+ *
186
+ * The constructor stays cheap: it opens SQLite, ensures the workflow tables,
187
+ * and re-arms the single alarm from the earliest pending clock. Workflow
188
+ * requests and alarms wait for the registered {@link setInitializer} callback
189
+ * before handlers are looked up in the module-level registry and built once
190
+ * per wake.
191
+ *
192
+ * @stability experimental
193
+ * @category durable objects
194
+ * @since 4.1.3
195
+ */
196
+ export class ClusterWorkflow extends DurableObject {
197
+ // blockConcurrencyWhile completes this assignment before any RPC or alarm.
198
+ #program;
199
+ constructor(ctx, env) {
200
+ super(ctx, env);
201
+ blockOnInitialization(ctx, env, async () => {
202
+ this.#program = await Effect.runPromise(makeClusterWorkflowProgram(ctx));
203
+ });
204
+ }
205
+ /** @internal Same-Worker RPC transport used by `CloudflareWorkflowEngine`. */
206
+ run(payload, options) {
207
+ return Effect.runPromise(this.#program.run(payload, options));
208
+ }
209
+ /** @internal */
210
+ poll() {
211
+ return Effect.runPromise(this.#program.poll());
212
+ }
213
+ /** @internal */
214
+ resume(mode) {
215
+ return Effect.runPromise(this.#program.resume(mode));
216
+ }
217
+ /** @internal */
218
+ interrupt() {
219
+ return Effect.runPromise(this.#program.interrupt());
220
+ }
221
+ /** @internal */
222
+ interruptUnsafe() {
223
+ return Effect.runPromise(this.#program.interruptUnsafe());
224
+ }
225
+ /** @internal Records a durable deferred exit and resumes the execution. */
226
+ deferredDone(name, exit) {
227
+ return Effect.runPromise(this.#program.deferredDone(name, exit));
228
+ }
229
+ /** @internal Persists a durable clock and arms the single alarm. */
230
+ scheduleClock(name, deferredName, wakeUp) {
231
+ return Effect.runPromise(this.#program.scheduleClock(name, deferredName, wakeUp));
232
+ }
233
+ alarm() {
234
+ return Effect.runPromise(this.#program.alarm());
235
+ }
236
+ fetch = /*#__PURE__*/notExposed("ClusterWorkflow");
237
+ }
238
+ /**
239
+ * The durable queue class behind the `PersistedQueue` implementation used by
240
+ * `DurableQueue`. One instance holds one named queue.
241
+ *
242
+ * **Details**
243
+ *
244
+ * The constructor stays cheap: it opens SQLite, ensures the queue table, and
245
+ * re-arms the single alarm from the earliest pending lease expiry. Items are
246
+ * leased to takers for a bounded time; the alarm watchdog expires overdue
247
+ * leases so an item whose worker died is redelivered. Requests and alarms wait
248
+ * for the registered {@link setInitializer} callback first.
249
+ *
250
+ * @stability experimental
251
+ * @category durable objects
252
+ * @since 4.1.3
253
+ */
254
+ export class ClusterDurableQueue extends DurableObject {
255
+ // blockConcurrencyWhile completes this assignment before any RPC or alarm.
256
+ #program;
257
+ constructor(ctx, env) {
258
+ super(ctx, env);
259
+ blockOnInitialization(ctx, env, async () => {
260
+ this.#program = await Effect.runPromise(makeClusterDurableQueueProgram(ctx));
261
+ });
262
+ }
263
+ /** @internal Same-Worker RPC transport used by `CloudflarePersistedQueue.layer`. */
264
+ offer(id, element, delayMillis, deduplicate) {
265
+ return Effect.runPromise(this.#program.offer(id, element, delayMillis, deduplicate));
266
+ }
267
+ /** @internal Waits until an item is available, then leases it to the caller. */
268
+ take(takerId, maxAttempts, leaseMillis) {
269
+ return Effect.runPromise(this.#program.take(takerId, maxAttempts, leaseMillis));
270
+ }
271
+ /** @internal Cancels a waiting take, releasing an item already leased to it. */
272
+ cancelTake(takerId) {
273
+ return Effect.runPromise(this.#program.cancelTake(takerId));
274
+ }
275
+ /** @internal Completes the item while the taker still owns its lease. */
276
+ complete(id, takerId) {
277
+ return Effect.runPromise(this.#program.complete(id, takerId));
278
+ }
279
+ /**
280
+ * @internal Records a failed attempt and requeues the item, or marks it failed
281
+ * after its final attempt or a terminal failure. A requeued item stays hidden
282
+ * for `retryDelayMillis`.
283
+ */
284
+ fail(id, lastFailure, takerId, terminal, retryDelayMillis) {
285
+ return Effect.runPromise(this.#program.fail(id, lastFailure, takerId, terminal, retryDelayMillis));
286
+ }
287
+ /** @internal Requeues the item and refunds the attempt its lease counted. */
288
+ release(id, takerId) {
289
+ return Effect.runPromise(this.#program.release(id, takerId));
290
+ }
291
+ /** @internal Extends the lease of an item still being processed. */
292
+ extend(id, leaseMillis, takerId) {
293
+ return Effect.runPromise(this.#program.extend(id, leaseMillis, takerId));
294
+ }
295
+ alarm() {
296
+ return Effect.runPromise(this.#program.alarm());
297
+ }
298
+ fetch = /*#__PURE__*/notExposed("ClusterDurableQueue");
299
+ }
300
+ /**
301
+ * The singleton class. One object holds one registered singleton under the
302
+ * name `Singleton/<name>` and is woken by a Worker Cron Trigger.
303
+ *
304
+ * **Details**
305
+ *
306
+ * The constructor opens SQLite, ensures the singleton state table, and
307
+ * re-arms the watchdog alarm for a wake interrupted by isolate loss. `wake()`
308
+ * runs the registered effect once and returns; it never appends
309
+ * `Effect.never`, so Cloudflare may hibernate the object afterward. A failed
310
+ * run is logged and resolves `wake()` with a `Failure`, so only a transport
311
+ * failure rejects it. Requests
312
+ * and alarms wait for the registered {@link setInitializer} callback before
313
+ * consulting the singleton registry.
314
+ *
315
+ * @stability experimental
316
+ * @category durable objects
317
+ * @since 4.1.3
318
+ */
319
+ export class ClusterSingleton extends DurableObject {
320
+ // blockConcurrencyWhile completes this assignment before any RPC or alarm.
321
+ #program;
322
+ constructor(ctx, env) {
323
+ super(ctx, env);
324
+ blockOnInitialization(ctx, env, async () => {
325
+ this.#program = await Effect.runPromise(makeClusterSingletonProgram(ctx));
326
+ });
327
+ }
328
+ /** @internal Runs one Cron Trigger fire, coalescing a concurrent duplicate. */
329
+ wake() {
330
+ return Effect.runPromise(this.#program.wake());
331
+ }
332
+ alarm() {
333
+ return Effect.runPromise(this.#program.alarm());
334
+ }
335
+ fetch = /*#__PURE__*/notExposed("ClusterSingleton");
336
+ }
337
+ //# sourceMappingURL=CloudflareDurableObjects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflareDurableObjects.js","names":[],"sources":["../src/CloudflareDurableObjects.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;;;;;;;;AAYA,SAAS,aAAa,QAAQ,oBAAoB;AAClD,OAAO,KAAK,MAAM,MAAM,eAAe;AACvC,SAUE,8BAA8B,EAC9B,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,QAErB,sCAAsC;AAE7C,MAAM,UAAU,GAAI,SAAiB,IAAK,MAAK;EAC7C,MAAM,IAAI,KAAK,CACb,gCAAgC,SAAS,mEAAmE,CAC7G;AACH,CAAC;AAgCD;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,yBAAyB,GAAG,MAAM;AACxC,MAAM,2BAA2B,GAAG,MAAM;AAC1C,MAAM,wBAAwB,GAAG,EAAE;AAEnC,IAAI,WAAoC;AACxC,IAAI,cAAiD;AAErD;;;;;;;;;;;;;;;;;;;;;;AAsBA,OAAO,MAAM,cAAc,GAAY,OAA4B,IAA8B;EAC/F,IAAI,WAAW,KAAK,SAAS,EAAE;IAC7B,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC;EAC/F;EACA,WAAW,GAAG,OAAsB;EACpC;EACA;EACA,OAAQ,GAAG,IAAK,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAe;AACpE,CAAC;AAED,MAAM,qBAAqB,GAAG,OAAO,GAAY,EAAE,cAAsB,KAAsB;EAC7F,IAAI,WAAW,KAAK,SAAS,EAAE;EAC/B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE;EAChC,MAAM,OAAO,GAAG,MAAe,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,GAAG,cAAc;EAC1E,MAAM,WAAW,GAAI,OAA8B,IAAc,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,EAAE;EAC9F;EACA,MAAM,YAAY,GAAI,OAA8B,IAClD,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,cAAc,KAAK,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;EACnF,OAAO,IAAI,EAAE;IACX,MAAM,OAAO,GAAG,cAAc;IAC9B,IAAI,OAAO,KAAK,SAAS,GAAG,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE;MAC5D,OAAO,cAAc,CAAC,WAAW,EAAE,GAAG,CAAC;IACzC;IACA,IAAI,OAAO,KAAK,SAAS,EAAE;MACzB;MACA;MACA;MACA,MAAM,SAAS,CAAC,IAAI,CAAC,wBAAwB,CAAC;MAC9C;IACF;IACA;IACA;IACA;IACA,OAAO,YAAY,CAAC,OAAO,CAAC,EAAE;MAC5B,MAAM,SAAS,CAAC,IAAI,CAAC,wBAAwB,CAAC;IAChD;IACA,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE;IAChC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK;IAC7D,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK;EAC3B;AACF,CAAC;AAED,MAAM,OAAO,GAAI,OAA8B,IAC7C,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,IAAI,yBAAyB;AAE3F,MAAM,cAAc,GAAG,OAAO,GAAgB,EAAE,GAAY,KAAsB;EAChF,MAAM,OAAO,GAA0B;IAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE;EAAS,CAAE;EACjF,cAAc,GAAG,OAAO;EACxB,IAAI;IACF,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC;IAC5B,OAAO,CAAC,IAAI,GAAG;MAAE,IAAI,EAAE,SAAS;MAAE;IAAK,CAAE;IACzC;IACA,IAAI,cAAc,EAAE,IAAI,EAAE,IAAI,KAAK,SAAS,EAAE,cAAc,GAAG,OAAO;IACtE,OAAO,KAAK;EACd,CAAC,CAAC,OAAO,KAAK,EAAE;IACd,OAAO,CAAC,IAAI,GAAG;MAAE,IAAI,EAAE,SAAS;MAAE;IAAK,CAAE;IACzC;IACA,IAAI,cAAc,KAAK,OAAO,EAAE,cAAc,GAAG,SAAS;IAC1D,MAAM,KAAK;EACb;AACF,CAAC;AAED,MAAM,qBAAqB,GAAG,CAC5B,GAAuB,EACvB,GAAY,EACZ,KAA4C,KACpC;EACR,KAAK,GAAG,CAAC,qBAAqB,CAAC,YAAW;IACxC,MAAM,qBAAqB,CAAC,GAAG,EAAE,2BAA2B,CAAC;IAC7D,IAAI,KAAK,KAAK,SAAS,EAAE,MAAM,KAAK,EAAE;EACxC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;AAkBA,OAAM,MAAO,aAAc,SAAQ,aAAsB;EACvD;EACA,QAAQ;EAER,YAAY,GAAuB,EAAE,GAAY;IAC/C,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC;IACf,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,YAAW;MACzC,IAAI,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;IACxE,CAAC,CAAC;EACJ;EAES,KAAK;IACZ,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;EACjD;EAEA;EACA,IAAI;IACF,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;EAChD;EAEA;EACA,MAAM,CAAC,YAAoB,EAAE,OAAgB,EAAE,QAAgC;IAC7E,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;EACjF;EAEA;EACA,WAAW,CAAC,SAAiB,EAAE,OAAe;IAC5C,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;EACzE;EAEA;EACA,SAAS,CAAC,gBAAwB,EAAE,eAAe,GAAG,gBAAgB;IACpE,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;EACtF;EAEA;EACA,KAAK,CAAC,SAAiB;IACrB,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;EAC1D;EAEA;EACA,YAAY,CAAC,SAAiB,EAAE,KAAa;IAC3C,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;EACxE;EAES,KAAK,gBAAgB,UAAU,CAAC,eAAe,CAAC;;AAG3D;;;;;;;;;;;;;;;;;AAiBA,OAAM,MAAO,eAAgB,SAAQ,aAAsB;EACzD;EACA,QAAQ;EAER,YAAY,GAAuB,EAAE,GAAY;IAC/C,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC;IACf,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,YAAW;MACzC,IAAI,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,0BAA0B,CAAC,GAAG,CAAC,CAAC;IAC1E,CAAC,CAAC;EACJ;EAEA;EACA,GAAG,CAAC,OAAe,EAAE,OAAkC;IACrD,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;EAC/D;EAEA;EACA,IAAI;IACF,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;EAChD;EAEA;EACA,MAAM,CAAC,IAA8B;IACnC,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;EACtD;EAEA;EACA,SAAS;IACP,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;EACrD;EAEA;EACA,eAAe;IACb,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;EAC3D;EAEA;EACA,YAAY,CAAC,IAAY,EAAE,IAAY;IACrC,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;EAClE;EAEA;EACA,aAAa,CAAC,IAAY,EAAE,YAAoB,EAAE,MAAc;IAC9D,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;EACnF;EAES,KAAK;IACZ,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;EACjD;EAES,KAAK,gBAAgB,UAAU,CAAC,iBAAiB,CAAC;;AAG7D;;;;;;;;;;;;;;;;AAgBA,OAAM,MAAO,mBAAoB,SAAQ,aAAsB;EAC7D;EACA,QAAQ;EAER,YAAY,GAAuB,EAAE,GAAY;IAC/C,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC;IACf,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,YAAW;MACzC,IAAI,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,GAAG,CAAC,CAAC;IAC9E,CAAC,CAAC;EACJ;EAEA;EACA,KAAK,CACH,EAAU,EACV,OAAe,EACf,WAAoB,EACpB,WAA8C;IAE9C,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;EACtF;EAEA;EACA,IAAI,CAAC,OAAe,EAAE,WAAmB,EAAE,WAAmB;IAC5D,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;EACjF;EAEA;EACA,UAAU,CAAC,OAAe;IACxB,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;EAC7D;EAEA;EACA,QAAQ,CAAC,EAAU,EAAE,OAAe;IAClC,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;EAC/D;EAEA;;;;;EAKA,IAAI,CAAC,EAAU,EAAE,WAAmB,EAAE,OAAe,EAAE,QAAkB,EAAE,gBAAyB;IAClG,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;EACpG;EAEA;EACA,OAAO,CAAC,EAAU,EAAE,OAAe;IACjC,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;EAC9D;EAEA;EACA,MAAM,CAAC,EAAU,EAAE,WAAmB,EAAE,OAAe;IACrD,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;EAC1E;EAES,KAAK;IACZ,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;EACjD;EAES,KAAK,gBAAgB,UAAU,CAAC,qBAAqB,CAAC;;AAGjE;;;;;;;;;;;;;;;;;;;AAmBA,OAAM,MAAO,gBAAiB,SAAQ,aAAsB;EAC1D;EACA,QAAQ;EAER,YAAY,GAAuB,EAAE,GAAY;IAC/C,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC;IACf,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,YAAW;MACzC,IAAI,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;IAC3E,CAAC,CAAC;EACJ;EAEA;EACA,IAAI;IACF,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;EAChD;EAES,KAAK;IACZ,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;EACjD;EAES,KAAK,gBAAgB,UAAU,CAAC,kBAAkB,CAAC","ignoreList":[]}
@@ -0,0 +1,36 @@
1
+ import * as Layer from "effect/Layer";
2
+ import * as PersistedQueue from "effect/persistence/PersistedQueue";
3
+ /**
4
+ * The queue Durable Object namespace binding the store is built from.
5
+ *
6
+ * @stability experimental
7
+ * @category layers
8
+ * @since 4.1.3
9
+ */
10
+ export interface LayerOptions {
11
+ readonly queueNamespace: DurableObjectNamespace;
12
+ }
13
+ /**
14
+ * Creates the `PersistedQueueStore` backed by the queue Durable Object
15
+ * namespace binding.
16
+ *
17
+ * @stability experimental
18
+ * @category constructors
19
+ * @since 4.1.3
20
+ */
21
+ export declare const make: (options: LayerOptions) => PersistedQueue.PersistedQueueStore["Service"];
22
+ /**
23
+ * Layer that provides the `PersistedQueueFactory` backed by the queue Durable
24
+ * Object namespace binding.
25
+ *
26
+ * **Details**
27
+ *
28
+ * `CloudflareCluster.layer` already includes this layer; use it directly only
29
+ * when persisted queues are needed without the rest of the cluster.
30
+ *
31
+ * @stability experimental
32
+ * @category layers
33
+ * @since 4.1.3
34
+ */
35
+ export declare const layer: (options: LayerOptions) => Layer.Layer<PersistedQueue.PersistedQueueFactory>;
36
+ //# sourceMappingURL=CloudflarePersistedQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflarePersistedQueue.d.ts","sourceRoot":"","sources":["../src/CloudflarePersistedQueue.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,cAAc,MAAM,mCAAmC,CAAA;AAKnE;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,EAAE,sBAAsB,CAAA;CAChD;AAkCD;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,YAAa,YAAY,KAAG,cAAc,CAAC,mBAAmB,CAAC,SAAS,CA4ExF,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK,YAAa,YAAY,KAAG,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,qBAAqB,CAG3F,CAAA"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Runs persisted queues on the dedicated queue Durable Object class.
3
+ *
4
+ * On this path one queue name is one Durable Object: the Worker encodes the
5
+ * queue name into a Durable Object name with the same length-prefix scheme as
6
+ * entities and resolves the object through the queue namespace binding. Items,
7
+ * their attempt counts, and their in-flight leases live on the object's SQLite
8
+ * storage behind its single alarm; a take with no available item waits inside
9
+ * the object until an offer, a retry, or an expired lease produces one.
10
+ *
11
+ * Delivery is at-least-once: a taken item is leased for a bounded time and the
12
+ * lease is refreshed while the handler runs, so an item whose worker died is
13
+ * redelivered once the alarm watchdog expires the lease. Leasing an item counts
14
+ * an attempt, so a worker that dies still consumes one, and an expired lease on
15
+ * the last attempt marks the item failed.
16
+ * Offer delays use the object's clock and persist an initial visibility
17
+ * deadline; the alarm wakes waiting takers when that deadline expires.
18
+ *
19
+ * This backs the `DurableQueue` user API; `CloudflareCluster.layer` already
20
+ * includes this layer.
21
+ *
22
+ * A failed item stays hidden on the object for the configured retry delay, so
23
+ * it does not hold a consumer while other items are ready. An element that
24
+ * fails to decode is marked failed immediately.
25
+ *
26
+ * `PersistedQueue.layerCleanup` is unsupported because the namespace binding
27
+ * cannot enumerate queue objects. Completed and failed rows remain retained for
28
+ * deduplication. A `deduplicate: "untilExecuted"` offer replaces such a row
29
+ * with a new element, which keeps only the latest failure.
30
+ *
31
+ * @stability experimental
32
+ * @since 4.1.3
33
+ */
34
+ import * as Cause from "effect/Cause";
35
+ import * as Duration from "effect/Duration";
36
+ import * as Effect from "effect/Effect";
37
+ import * as Exit from "effect/Exit";
38
+ import * as Layer from "effect/Layer";
39
+ import * as PersistedQueue from "effect/persistence/PersistedQueue";
40
+ import * as Schedule from "effect/Schedule";
41
+ import { encodeName } from "./internal/clusterName.js";
42
+ const leaseMillis = 120_000;
43
+ const leaseRefreshMillis = 30_000;
44
+ const attempt = run => Effect.promise(run).pipe(Effect.sandbox, Effect.retry({
45
+ times: 5,
46
+ schedule: Schedule.exponential(100, 1.5)
47
+ }));
48
+ const finalize = run => Effect.orDie(attempt(run));
49
+ /**
50
+ * Creates the `PersistedQueueStore` backed by the queue Durable Object
51
+ * namespace binding.
52
+ *
53
+ * @stability experimental
54
+ * @category constructors
55
+ * @since 4.1.3
56
+ */
57
+ export const make = options => {
58
+ const stubFor = name => options.queueNamespace.getByName(encodeName("PersistedQueue", name));
59
+ return PersistedQueue.PersistedQueueStore.of({
60
+ cleanup: () => Effect.fail(new PersistedQueue.PersistedQueueError({
61
+ message: "Cloudflare persisted queue cleanup is unsupported: the namespace binding cannot enumerate queue objects"
62
+ })),
63
+ offer: ({
64
+ deduplicate,
65
+ delay,
66
+ element,
67
+ id,
68
+ isCustomId,
69
+ name
70
+ }) => Effect.tryPromise({
71
+ try: () => stubFor(name).offer(id, JSON.stringify(element), delay === undefined ? 0 : Duration.toMillis(delay),
72
+ // generated ids are never offered twice
73
+ isCustomId ? deduplicate : undefined),
74
+ catch: cause => new PersistedQueue.PersistedQueueError({
75
+ message: "Failed to offer element to persisted queue",
76
+ cause
77
+ })
78
+ }),
79
+ take: ({
80
+ maxAttempts,
81
+ name,
82
+ retryDelay
83
+ }) =>
84
+ // Uninterruptible outside `restore` so the release finalizer is always
85
+ // registered once an item is leased; an interrupt while still waiting
86
+ // cancels the take by taker id, releasing an item that was already
87
+ // leased to it on the object.
88
+ Effect.uninterruptibleMask(restore => Effect.gen(function* () {
89
+ const takerId = crypto.randomUUID();
90
+ // A broken take RPC means the object was evicted while this taker
91
+ // waited; retrying re-enters the queue with nothing lost.
92
+ const item = yield* restore(Effect.promise(() => stubFor(name).take(takerId, maxAttempts, leaseMillis)).pipe(Effect.sandbox, Effect.tapCause(cause => Effect.logWarning("PersistedQueue take failed, retrying", cause)), Effect.retry(Schedule.spaced(500)), Effect.orDie)).pipe(Effect.onInterrupt(() => Effect.ignore(attempt(() => stubFor(name).cancelTake(takerId)))));
93
+ yield* Effect.addFinalizer(Exit.match({
94
+ onFailure: cause => Cause.hasInterruptsOnly(cause) ? finalize(() => stubFor(name).release(item.id, takerId)) : PersistedQueue.isDeadLetterCause(cause) ? finalize(() => stubFor(name).fail(item.id, Cause.pretty(cause), takerId, true)) : Effect.flatMap(retryDelay(item.attempts + 1), delay =>
95
+ // The delay follows the attempt count including this one.
96
+ finalize(() => stubFor(name).fail(item.id, Cause.pretty(cause), takerId, false, Duration.toMillis(delay)))),
97
+ onSuccess: () => finalize(() => stubFor(name).complete(item.id, takerId))
98
+ }));
99
+ yield* Effect.promise(() => stubFor(name).extend(item.id, leaseMillis, takerId)).pipe(Effect.sandbox, Effect.ignore, Effect.schedule(Schedule.spaced(leaseRefreshMillis)), Effect.forkScoped, Effect.interruptible);
100
+ return {
101
+ id: item.id,
102
+ attempts: item.attempts + 1,
103
+ element: JSON.parse(item.element)
104
+ };
105
+ }))
106
+ });
107
+ };
108
+ /**
109
+ * Layer that provides the `PersistedQueueFactory` backed by the queue Durable
110
+ * Object namespace binding.
111
+ *
112
+ * **Details**
113
+ *
114
+ * `CloudflareCluster.layer` already includes this layer; use it directly only
115
+ * when persisted queues are needed without the rest of the cluster.
116
+ *
117
+ * @stability experimental
118
+ * @category layers
119
+ * @since 4.1.3
120
+ */
121
+ export const layer = options => PersistedQueue.layer.pipe(Layer.provide(Layer.succeed(PersistedQueue.PersistedQueueStore)(make(options))));
122
+ //# sourceMappingURL=CloudflarePersistedQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflarePersistedQueue.js","names":[],"sources":["../src/CloudflarePersistedQueue.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}