effect 4.0.0-beta.101 → 4.0.0-beta.102

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 (494) hide show
  1. package/dist/Array.d.ts.map +1 -1
  2. package/dist/Array.js +81 -5
  3. package/dist/Array.js.map +1 -1
  4. package/dist/Channel.d.ts.map +1 -1
  5. package/dist/Channel.js +27 -9
  6. package/dist/Channel.js.map +1 -1
  7. package/dist/Config.d.ts +1 -1
  8. package/dist/Config.d.ts.map +1 -1
  9. package/dist/Config.js +6 -5
  10. package/dist/Config.js.map +1 -1
  11. package/dist/ConfigProvider.js +7 -7
  12. package/dist/ConfigProvider.js.map +1 -1
  13. package/dist/Data.d.ts.map +1 -1
  14. package/dist/Data.js +2 -1
  15. package/dist/Data.js.map +1 -1
  16. package/dist/Effect.d.ts +61 -100
  17. package/dist/Effect.d.ts.map +1 -1
  18. package/dist/Effect.js +66 -39
  19. package/dist/Effect.js.map +1 -1
  20. package/dist/FiberHandle.d.ts.map +1 -1
  21. package/dist/FiberHandle.js +3 -2
  22. package/dist/FiberHandle.js.map +1 -1
  23. package/dist/Iterable.d.ts.map +1 -1
  24. package/dist/Iterable.js +2 -1
  25. package/dist/Iterable.js.map +1 -1
  26. package/dist/JsonPatch.d.ts.map +1 -1
  27. package/dist/JsonPatch.js +4 -3
  28. package/dist/JsonPatch.js.map +1 -1
  29. package/dist/JsonSchema.d.ts.map +1 -1
  30. package/dist/JsonSchema.js +9 -11
  31. package/dist/JsonSchema.js.map +1 -1
  32. package/dist/Logger.d.ts.map +1 -1
  33. package/dist/Logger.js +3 -2
  34. package/dist/Logger.js.map +1 -1
  35. package/dist/ManagedRuntime.d.ts +9 -0
  36. package/dist/ManagedRuntime.d.ts.map +1 -1
  37. package/dist/ManagedRuntime.js +3 -0
  38. package/dist/ManagedRuntime.js.map +1 -1
  39. package/dist/Metric.d.ts.map +1 -1
  40. package/dist/Metric.js +4 -3
  41. package/dist/Metric.js.map +1 -1
  42. package/dist/Optic.d.ts.map +1 -1
  43. package/dist/Optic.js +5 -4
  44. package/dist/Optic.js.map +1 -1
  45. package/dist/Option.d.ts.map +1 -1
  46. package/dist/Option.js +2 -1
  47. package/dist/Option.js.map +1 -1
  48. package/dist/PartitionedSemaphore.d.ts.map +1 -1
  49. package/dist/PartitionedSemaphore.js +1 -4
  50. package/dist/PartitionedSemaphore.js.map +1 -1
  51. package/dist/Record.d.ts +93 -1
  52. package/dist/Record.d.ts.map +1 -1
  53. package/dist/Record.js +57 -19
  54. package/dist/Record.js.map +1 -1
  55. package/dist/References.d.ts +0 -45
  56. package/dist/References.d.ts.map +1 -1
  57. package/dist/References.js +0 -45
  58. package/dist/References.js.map +1 -1
  59. package/dist/Request.d.ts.map +1 -1
  60. package/dist/Request.js +9 -6
  61. package/dist/Request.js.map +1 -1
  62. package/dist/Result.d.ts.map +1 -1
  63. package/dist/Result.js +2 -1
  64. package/dist/Result.js.map +1 -1
  65. package/dist/Schema.d.ts +1268 -495
  66. package/dist/Schema.d.ts.map +1 -1
  67. package/dist/Schema.js +2308 -614
  68. package/dist/Schema.js.map +1 -1
  69. package/dist/SchemaAST.d.ts +2 -2
  70. package/dist/SchemaAST.d.ts.map +1 -1
  71. package/dist/SchemaAST.js +189 -130
  72. package/dist/SchemaAST.js.map +1 -1
  73. package/dist/SchemaError.js +1 -1
  74. package/dist/SchemaError.js.map +1 -1
  75. package/dist/SchemaGetter.d.ts +13 -11
  76. package/dist/SchemaGetter.d.ts.map +1 -1
  77. package/dist/SchemaGetter.js +34 -24
  78. package/dist/SchemaGetter.js.map +1 -1
  79. package/dist/SchemaIssue.js +1 -1
  80. package/dist/SchemaIssue.js.map +1 -1
  81. package/dist/SchemaParser.d.ts.map +1 -1
  82. package/dist/SchemaParser.js +1 -12
  83. package/dist/SchemaParser.js.map +1 -1
  84. package/dist/SchemaRepresentation.d.ts +403 -1504
  85. package/dist/SchemaRepresentation.d.ts.map +1 -1
  86. package/dist/SchemaRepresentation.js +294 -2852
  87. package/dist/SchemaRepresentation.js.map +1 -1
  88. package/dist/SchemaTransformation.d.ts +2 -2
  89. package/dist/SchemaTransformation.js +3 -3
  90. package/dist/SchemaTransformation.js.map +1 -1
  91. package/dist/Semaphore.d.ts +5 -3
  92. package/dist/Semaphore.d.ts.map +1 -1
  93. package/dist/Semaphore.js.map +1 -1
  94. package/dist/Stream.d.ts +15 -9
  95. package/dist/Stream.d.ts.map +1 -1
  96. package/dist/Stream.js +46 -16
  97. package/dist/Stream.js.map +1 -1
  98. package/dist/Struct.d.ts.map +1 -1
  99. package/dist/Struct.js +5 -4
  100. package/dist/Struct.js.map +1 -1
  101. package/dist/Types.d.ts +1 -3
  102. package/dist/Types.d.ts.map +1 -1
  103. package/dist/index.d.ts +0 -4
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +0 -4
  106. package/dist/index.js.map +1 -1
  107. package/dist/internal/core.js +2 -1
  108. package/dist/internal/core.js.map +1 -1
  109. package/dist/internal/effect.js +64 -21
  110. package/dist/internal/effect.js.map +1 -1
  111. package/dist/internal/matcher.js +1 -1
  112. package/dist/internal/matcher.js.map +1 -1
  113. package/dist/internal/record.d.ts +0 -3
  114. package/dist/internal/record.d.ts.map +1 -1
  115. package/dist/internal/record.js +10 -5
  116. package/dist/internal/record.js.map +1 -1
  117. package/dist/internal/references.js +0 -4
  118. package/dist/internal/references.js.map +1 -1
  119. package/dist/internal/schema/annotations.js +12 -0
  120. package/dist/internal/schema/annotations.js.map +1 -1
  121. package/dist/internal/schema/fromJsonSchemaDocument.d.ts +2 -0
  122. package/dist/internal/schema/fromJsonSchemaDocument.d.ts.map +1 -0
  123. package/dist/internal/schema/fromJsonSchemaDocument.js +743 -0
  124. package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -0
  125. package/dist/internal/schema/fromRepresentation.d.ts +2 -0
  126. package/dist/internal/schema/fromRepresentation.d.ts.map +1 -0
  127. package/dist/internal/schema/fromRepresentation.js +252 -0
  128. package/dist/internal/schema/fromRepresentation.js.map +1 -0
  129. package/dist/internal/schema/schema.js +28 -40
  130. package/dist/internal/schema/schema.js.map +1 -1
  131. package/dist/internal/schema/{arbitrary.d.ts → toArbitrary.d.ts} +1 -1
  132. package/dist/internal/schema/toArbitrary.d.ts.map +1 -0
  133. package/dist/internal/schema/{arbitrary.js → toArbitrary.js} +8 -9
  134. package/dist/internal/schema/toArbitrary.js.map +1 -0
  135. package/dist/internal/schema/toCodeDocument.d.ts +2 -0
  136. package/dist/internal/schema/toCodeDocument.d.ts.map +1 -0
  137. package/dist/internal/schema/toCodeDocument.js +438 -0
  138. package/dist/internal/schema/toCodeDocument.js.map +1 -0
  139. package/dist/internal/schema/toEquivalence.d.ts +2 -0
  140. package/dist/internal/schema/toEquivalence.d.ts.map +1 -0
  141. package/dist/internal/schema/{equivalence.js → toEquivalence.js} +15 -13
  142. package/dist/internal/schema/toEquivalence.js.map +1 -0
  143. package/dist/internal/schema/toJsonSchemaDocument.d.ts +2 -0
  144. package/dist/internal/schema/toJsonSchemaDocument.d.ts.map +1 -0
  145. package/dist/internal/schema/toJsonSchemaDocument.js +466 -0
  146. package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -0
  147. package/dist/internal/schema/toRepresentation.d.ts +2 -0
  148. package/dist/internal/schema/toRepresentation.d.ts.map +1 -0
  149. package/dist/internal/schema/toRepresentation.js +369 -0
  150. package/dist/internal/schema/toRepresentation.js.map +1 -0
  151. package/dist/internal/stackTraceLimit.js +3 -6
  152. package/dist/internal/stackTraceLimit.js.map +1 -1
  153. package/dist/testing/TestClock.js +4 -1
  154. package/dist/testing/TestClock.js.map +1 -1
  155. package/dist/unstable/ai/AiError.d.ts +26 -26
  156. package/dist/unstable/ai/AiError.d.ts.map +1 -1
  157. package/dist/unstable/ai/AiError.js +5 -4
  158. package/dist/unstable/ai/AiError.js.map +1 -1
  159. package/dist/unstable/ai/AnthropicStructuredOutput.d.ts +21 -6
  160. package/dist/unstable/ai/AnthropicStructuredOutput.d.ts.map +1 -1
  161. package/dist/unstable/ai/AnthropicStructuredOutput.js +86 -316
  162. package/dist/unstable/ai/AnthropicStructuredOutput.js.map +1 -1
  163. package/dist/unstable/ai/EmbeddingModel.d.ts +1 -1
  164. package/dist/unstable/ai/EmbeddingModel.js +1 -1
  165. package/dist/unstable/ai/EmbeddingModel.js.map +1 -1
  166. package/dist/unstable/ai/LanguageModel.d.ts +4 -1
  167. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  168. package/dist/unstable/ai/LanguageModel.js +19 -17
  169. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  170. package/dist/unstable/ai/McpSchema.d.ts +197 -197
  171. package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
  172. package/dist/unstable/ai/McpSchema.js +13 -13
  173. package/dist/unstable/ai/McpSchema.js.map +1 -1
  174. package/dist/unstable/ai/McpServer.d.ts +4 -4
  175. package/dist/unstable/ai/McpServer.d.ts.map +1 -1
  176. package/dist/unstable/ai/McpServer.js +116 -49
  177. package/dist/unstable/ai/McpServer.js.map +1 -1
  178. package/dist/unstable/ai/OpenAiStructuredOutput.d.ts +32 -10
  179. package/dist/unstable/ai/OpenAiStructuredOutput.d.ts.map +1 -1
  180. package/dist/unstable/ai/OpenAiStructuredOutput.js +193 -377
  181. package/dist/unstable/ai/OpenAiStructuredOutput.js.map +1 -1
  182. package/dist/unstable/ai/Response.d.ts +19 -19
  183. package/dist/unstable/ai/Response.d.ts.map +1 -1
  184. package/dist/unstable/ai/Response.js +14 -14
  185. package/dist/unstable/ai/Response.js.map +1 -1
  186. package/dist/unstable/ai/Tool.d.ts +4 -0
  187. package/dist/unstable/ai/Tool.d.ts.map +1 -1
  188. package/dist/unstable/ai/Tool.js +11 -3
  189. package/dist/unstable/ai/Tool.js.map +1 -1
  190. package/dist/unstable/ai/Toolkit.d.ts +9 -1
  191. package/dist/unstable/ai/Toolkit.d.ts.map +1 -1
  192. package/dist/unstable/ai/Toolkit.js +14 -10
  193. package/dist/unstable/ai/Toolkit.js.map +1 -1
  194. package/dist/unstable/ai/internal/codec-transformer.js +15 -12
  195. package/dist/unstable/ai/internal/codec-transformer.js.map +1 -1
  196. package/dist/unstable/ai/internal/structured-output.d.ts +2 -0
  197. package/dist/unstable/ai/internal/structured-output.d.ts.map +1 -0
  198. package/dist/unstable/ai/internal/structured-output.js +316 -0
  199. package/dist/unstable/ai/internal/structured-output.js.map +1 -0
  200. package/dist/unstable/cli/CliError.d.ts +40 -2
  201. package/dist/unstable/cli/CliError.d.ts.map +1 -1
  202. package/dist/unstable/cli/CliError.js +45 -6
  203. package/dist/unstable/cli/CliError.js.map +1 -1
  204. package/dist/unstable/cli/Command.js +14 -5
  205. package/dist/unstable/cli/Command.js.map +1 -1
  206. package/dist/unstable/cli/Param.js +3 -3
  207. package/dist/unstable/cli/Param.js.map +1 -1
  208. package/dist/unstable/cli/Primitive.js +1 -1
  209. package/dist/unstable/cli/Primitive.js.map +1 -1
  210. package/dist/unstable/cli/internal/command.d.ts +3 -1
  211. package/dist/unstable/cli/internal/command.d.ts.map +1 -1
  212. package/dist/unstable/cli/internal/command.js +11 -4
  213. package/dist/unstable/cli/internal/command.js.map +1 -1
  214. package/dist/unstable/cli/internal/config.d.ts +0 -48
  215. package/dist/unstable/cli/internal/config.d.ts.map +1 -1
  216. package/dist/unstable/cli/internal/config.js +8 -10
  217. package/dist/unstable/cli/internal/config.js.map +1 -1
  218. package/dist/unstable/cluster/ClusterWorkflowEngine.js +1 -1
  219. package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
  220. package/dist/unstable/cluster/Entity.js +1 -1
  221. package/dist/unstable/cluster/Entity.js.map +1 -1
  222. package/dist/unstable/cluster/Envelope.d.ts.map +1 -1
  223. package/dist/unstable/cluster/Envelope.js +2 -1
  224. package/dist/unstable/cluster/Envelope.js.map +1 -1
  225. package/dist/unstable/cluster/Reply.js +1 -1
  226. package/dist/unstable/cluster/Reply.js.map +1 -1
  227. package/dist/unstable/cluster/Runner.d.ts +1 -1
  228. package/dist/unstable/cluster/Runner.js +1 -1
  229. package/dist/unstable/cluster/Runner.js.map +1 -1
  230. package/dist/unstable/cluster/RunnerAddress.d.ts +1 -1
  231. package/dist/unstable/cluster/RunnerAddress.js +1 -1
  232. package/dist/unstable/cluster/RunnerAddress.js.map +1 -1
  233. package/dist/unstable/cluster/ShardId.js +1 -1
  234. package/dist/unstable/cluster/ShardId.js.map +1 -1
  235. package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
  236. package/dist/unstable/cluster/Sharding.js +125 -24
  237. package/dist/unstable/cluster/Sharding.js.map +1 -1
  238. package/dist/unstable/cluster/ShardingConfig.d.ts +10 -2
  239. package/dist/unstable/cluster/ShardingConfig.d.ts.map +1 -1
  240. package/dist/unstable/cluster/ShardingConfig.js.map +1 -1
  241. package/dist/unstable/cluster/SingleRunner.d.ts +4 -2
  242. package/dist/unstable/cluster/SingleRunner.d.ts.map +1 -1
  243. package/dist/unstable/cluster/SingleRunner.js +2 -1
  244. package/dist/unstable/cluster/SingleRunner.js.map +1 -1
  245. package/dist/unstable/cluster/SqlMessageStorage.d.ts +7 -4
  246. package/dist/unstable/cluster/SqlMessageStorage.d.ts.map +1 -1
  247. package/dist/unstable/cluster/SqlMessageStorage.js +55 -24
  248. package/dist/unstable/cluster/SqlMessageStorage.js.map +1 -1
  249. package/dist/unstable/cluster/SqlRunnerStorage.d.ts.map +1 -1
  250. package/dist/unstable/cluster/SqlRunnerStorage.js +109 -62
  251. package/dist/unstable/cluster/SqlRunnerStorage.js.map +1 -1
  252. package/dist/unstable/cluster/internal/entityManager.js +19 -7
  253. package/dist/unstable/cluster/internal/entityManager.js.map +1 -1
  254. package/dist/unstable/cluster/internal/shardLock.d.ts +2 -0
  255. package/dist/unstable/cluster/internal/shardLock.d.ts.map +1 -0
  256. package/dist/unstable/cluster/internal/shardLock.js +4 -0
  257. package/dist/unstable/cluster/internal/shardLock.js.map +1 -0
  258. package/dist/unstable/devtools/DevToolsSchema.d.ts +20 -20
  259. package/dist/unstable/devtools/DevToolsSchema.d.ts.map +1 -1
  260. package/dist/unstable/devtools/DevToolsSchema.js +8 -5
  261. package/dist/unstable/devtools/DevToolsSchema.js.map +1 -1
  262. package/dist/unstable/eventlog/EventJournal.d.ts +1 -1
  263. package/dist/unstable/eventlog/EventJournal.js +1 -1
  264. package/dist/unstable/eventlog/EventJournal.js.map +1 -1
  265. package/dist/unstable/eventlog/EventLog.d.ts.map +1 -1
  266. package/dist/unstable/eventlog/EventLog.js +15 -11
  267. package/dist/unstable/eventlog/EventLog.js.map +1 -1
  268. package/dist/unstable/eventlog/EventLogEncryption.d.ts +1 -1
  269. package/dist/unstable/eventlog/EventLogEncryption.js +1 -1
  270. package/dist/unstable/eventlog/EventLogEncryption.js.map +1 -1
  271. package/dist/unstable/eventlog/EventLogMessage.d.ts +4 -4
  272. package/dist/unstable/eventlog/EventLogMessage.d.ts.map +1 -1
  273. package/dist/unstable/eventlog/EventLogMessage.js +8 -3
  274. package/dist/unstable/eventlog/EventLogMessage.js.map +1 -1
  275. package/dist/unstable/eventlog/EventLogRemote.d.ts +1 -1
  276. package/dist/unstable/eventlog/SqlEventJournal.js +2 -2
  277. package/dist/unstable/eventlog/SqlEventJournal.js.map +1 -1
  278. package/dist/unstable/eventlog/SqlEventLogServerEncrypted.js +1 -1
  279. package/dist/unstable/eventlog/SqlEventLogServerEncrypted.js.map +1 -1
  280. package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js +3 -3
  281. package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js.map +1 -1
  282. package/dist/unstable/http/Cookies.d.ts.map +1 -1
  283. package/dist/unstable/http/Cookies.js +24 -22
  284. package/dist/unstable/http/Cookies.js.map +1 -1
  285. package/dist/unstable/http/Headers.js +8 -8
  286. package/dist/unstable/http/Headers.js.map +1 -1
  287. package/dist/unstable/http/HttpClientRequest.d.ts +44 -0
  288. package/dist/unstable/http/HttpClientRequest.d.ts.map +1 -1
  289. package/dist/unstable/http/HttpClientRequest.js +14 -0
  290. package/dist/unstable/http/HttpClientRequest.js.map +1 -1
  291. package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
  292. package/dist/unstable/http/HttpServerRequest.js +5 -4
  293. package/dist/unstable/http/HttpServerRequest.js.map +1 -1
  294. package/dist/unstable/http/Multipart.d.ts.map +1 -1
  295. package/dist/unstable/http/Multipart.js +17 -15
  296. package/dist/unstable/http/Multipart.js.map +1 -1
  297. package/dist/unstable/http/Template.js +1 -1
  298. package/dist/unstable/http/Template.js.map +1 -1
  299. package/dist/unstable/http/UrlParams.d.ts.map +1 -1
  300. package/dist/unstable/http/UrlParams.js +17 -14
  301. package/dist/unstable/http/UrlParams.js.map +1 -1
  302. package/dist/unstable/httpapi/HttpApi.js +3 -3
  303. package/dist/unstable/httpapi/HttpApi.js.map +1 -1
  304. package/dist/unstable/httpapi/HttpApiClient.js +5 -5
  305. package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
  306. package/dist/unstable/httpapi/HttpApiGroup.js +1 -1
  307. package/dist/unstable/httpapi/HttpApiGroup.js.map +1 -1
  308. package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
  309. package/dist/unstable/httpapi/OpenApi.js +37 -24
  310. package/dist/unstable/httpapi/OpenApi.js.map +1 -1
  311. package/dist/unstable/observability/OtlpExporter.d.ts +72 -1
  312. package/dist/unstable/observability/OtlpExporter.d.ts.map +1 -1
  313. package/dist/unstable/observability/OtlpExporter.js +69 -4
  314. package/dist/unstable/observability/OtlpExporter.js.map +1 -1
  315. package/dist/unstable/observability/OtlpLogger.d.ts +4 -3
  316. package/dist/unstable/observability/OtlpLogger.d.ts.map +1 -1
  317. package/dist/unstable/observability/OtlpLogger.js +2 -2
  318. package/dist/unstable/observability/OtlpLogger.js.map +1 -1
  319. package/dist/unstable/observability/OtlpMetrics.d.ts +7 -3
  320. package/dist/unstable/observability/OtlpMetrics.d.ts.map +1 -1
  321. package/dist/unstable/observability/OtlpMetrics.js +5 -2
  322. package/dist/unstable/observability/OtlpMetrics.js.map +1 -1
  323. package/dist/unstable/observability/OtlpTracer.d.ts +4 -3
  324. package/dist/unstable/observability/OtlpTracer.d.ts.map +1 -1
  325. package/dist/unstable/observability/OtlpTracer.js +2 -2
  326. package/dist/unstable/observability/OtlpTracer.js.map +1 -1
  327. package/dist/unstable/persistence/Persistable.d.ts.map +1 -1
  328. package/dist/unstable/persistence/Persistable.js +2 -1
  329. package/dist/unstable/persistence/Persistable.js.map +1 -1
  330. package/dist/unstable/persistence/RateLimiter.d.ts +2 -2
  331. package/dist/unstable/persistence/RateLimiter.js +2 -2
  332. package/dist/unstable/persistence/RateLimiter.js.map +1 -1
  333. package/dist/unstable/persistence/Redis.d.ts.map +1 -1
  334. package/dist/unstable/persistence/Redis.js +2 -2
  335. package/dist/unstable/persistence/Redis.js.map +1 -1
  336. package/dist/unstable/process/ChildProcessSpawner.js +3 -1
  337. package/dist/unstable/process/ChildProcessSpawner.js.map +1 -1
  338. package/dist/unstable/reactivity/AsyncResult.d.ts.map +1 -1
  339. package/dist/unstable/reactivity/AsyncResult.js +4 -3
  340. package/dist/unstable/reactivity/AsyncResult.js.map +1 -1
  341. package/dist/unstable/reactivity/Atom.d.ts +83 -0
  342. package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
  343. package/dist/unstable/reactivity/Atom.js +31 -0
  344. package/dist/unstable/reactivity/Atom.js.map +1 -1
  345. package/dist/unstable/reactivity/AtomRegistry.js +1 -1
  346. package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
  347. package/dist/unstable/rpc/RpcClient.d.ts.map +1 -1
  348. package/dist/unstable/rpc/RpcClient.js +2 -1
  349. package/dist/unstable/rpc/RpcClient.js.map +1 -1
  350. package/dist/unstable/schema/VariantSchema.d.ts +1 -2
  351. package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
  352. package/dist/unstable/schema/VariantSchema.js +13 -10
  353. package/dist/unstable/schema/VariantSchema.js.map +1 -1
  354. package/dist/unstable/socket/Socket.d.ts +1 -1
  355. package/dist/unstable/socket/Socket.js +1 -1
  356. package/dist/unstable/socket/Socket.js.map +1 -1
  357. package/dist/unstable/sql/SqlError.d.ts +2 -2
  358. package/dist/unstable/sql/SqlError.js +2 -2
  359. package/dist/unstable/sql/SqlError.js.map +1 -1
  360. package/dist/unstable/sql/Statement.d.ts.map +1 -1
  361. package/dist/unstable/sql/Statement.js +7 -6
  362. package/dist/unstable/sql/Statement.js.map +1 -1
  363. package/package.json +1 -1
  364. package/src/Array.ts +86 -25
  365. package/src/Channel.ts +32 -14
  366. package/src/Config.ts +6 -5
  367. package/src/ConfigProvider.ts +7 -7
  368. package/src/Data.ts +3 -2
  369. package/src/Effect.ts +70 -116
  370. package/src/FiberHandle.ts +3 -2
  371. package/src/Iterable.ts +2 -1
  372. package/src/JsonPatch.ts +4 -3
  373. package/src/JsonSchema.ts +9 -11
  374. package/src/Logger.ts +3 -2
  375. package/src/ManagedRuntime.ts +13 -0
  376. package/src/Metric.ts +4 -3
  377. package/src/Optic.ts +5 -4
  378. package/src/Option.ts +2 -1
  379. package/src/PartitionedSemaphore.ts +1 -4
  380. package/src/Record.ts +119 -22
  381. package/src/References.ts +0 -46
  382. package/src/Request.ts +5 -7
  383. package/src/Result.ts +2 -1
  384. package/src/Schema.ts +2537 -986
  385. package/src/SchemaAST.ts +228 -149
  386. package/src/SchemaError.ts +1 -1
  387. package/src/SchemaGetter.ts +36 -29
  388. package/src/SchemaIssue.ts +1 -1
  389. package/src/SchemaParser.ts +1 -25
  390. package/src/SchemaRepresentation.ts +697 -3398
  391. package/src/SchemaTransformation.ts +3 -3
  392. package/src/Semaphore.ts +5 -3
  393. package/src/Stream.ts +63 -19
  394. package/src/Struct.ts +5 -4
  395. package/src/Types.ts +1 -3
  396. package/src/index.ts +0 -5
  397. package/src/internal/core.ts +3 -2
  398. package/src/internal/effect.ts +67 -31
  399. package/src/internal/matcher.ts +1 -1
  400. package/src/internal/record.ts +11 -7
  401. package/src/internal/references.ts +0 -5
  402. package/src/internal/schema/annotations.ts +44 -0
  403. package/src/internal/schema/fromJsonSchemaDocument.ts +957 -0
  404. package/src/internal/schema/fromRepresentation.ts +345 -0
  405. package/src/internal/schema/schema.ts +45 -46
  406. package/src/internal/schema/{arbitrary.ts → toArbitrary.ts} +8 -10
  407. package/src/internal/schema/toCodeDocument.ts +572 -0
  408. package/src/internal/schema/{equivalence.ts → toEquivalence.ts} +12 -7
  409. package/src/internal/schema/toJsonSchemaDocument.ts +475 -0
  410. package/src/internal/schema/toRepresentation.ts +401 -0
  411. package/src/internal/stackTraceLimit.ts +3 -7
  412. package/src/testing/TestClock.ts +1 -1
  413. package/src/unstable/ai/AiError.ts +5 -4
  414. package/src/unstable/ai/AnthropicStructuredOutput.ts +102 -333
  415. package/src/unstable/ai/EmbeddingModel.ts +1 -1
  416. package/src/unstable/ai/LanguageModel.ts +30 -28
  417. package/src/unstable/ai/McpSchema.ts +15 -15
  418. package/src/unstable/ai/McpServer.ts +172 -56
  419. package/src/unstable/ai/OpenAiStructuredOutput.ts +230 -395
  420. package/src/unstable/ai/Response.ts +24 -24
  421. package/src/unstable/ai/Tool.ts +22 -4
  422. package/src/unstable/ai/Toolkit.ts +19 -7
  423. package/src/unstable/ai/internal/codec-transformer.ts +13 -7
  424. package/src/unstable/ai/internal/structured-output.ts +458 -0
  425. package/src/unstable/cli/CliError.ts +51 -5
  426. package/src/unstable/cli/Command.ts +4 -4
  427. package/src/unstable/cli/Param.ts +3 -3
  428. package/src/unstable/cli/Primitive.ts +1 -1
  429. package/src/unstable/cli/internal/command.ts +13 -5
  430. package/src/unstable/cli/internal/config.ts +8 -10
  431. package/src/unstable/cluster/ClusterWorkflowEngine.ts +3 -3
  432. package/src/unstable/cluster/Entity.ts +1 -1
  433. package/src/unstable/cluster/Envelope.ts +2 -1
  434. package/src/unstable/cluster/Reply.ts +1 -1
  435. package/src/unstable/cluster/Runner.ts +1 -1
  436. package/src/unstable/cluster/RunnerAddress.ts +1 -1
  437. package/src/unstable/cluster/ShardId.ts +1 -1
  438. package/src/unstable/cluster/Sharding.ts +161 -34
  439. package/src/unstable/cluster/ShardingConfig.ts +5 -1
  440. package/src/unstable/cluster/SingleRunner.ts +4 -2
  441. package/src/unstable/cluster/SqlMessageStorage.ts +83 -35
  442. package/src/unstable/cluster/SqlRunnerStorage.ts +186 -116
  443. package/src/unstable/cluster/internal/entityManager.ts +31 -10
  444. package/src/unstable/cluster/internal/shardLock.ts +9 -0
  445. package/src/unstable/devtools/DevToolsSchema.ts +10 -5
  446. package/src/unstable/eventlog/EventJournal.ts +1 -1
  447. package/src/unstable/eventlog/EventLog.ts +21 -11
  448. package/src/unstable/eventlog/EventLogEncryption.ts +1 -1
  449. package/src/unstable/eventlog/EventLogMessage.ts +10 -3
  450. package/src/unstable/eventlog/SqlEventJournal.ts +2 -2
  451. package/src/unstable/eventlog/SqlEventLogServerEncrypted.ts +1 -1
  452. package/src/unstable/eventlog/SqlEventLogServerUnencrypted.ts +6 -3
  453. package/src/unstable/http/Cookies.ts +29 -24
  454. package/src/unstable/http/Headers.ts +8 -8
  455. package/src/unstable/http/HttpClientRequest.ts +57 -0
  456. package/src/unstable/http/HttpServerRequest.ts +5 -4
  457. package/src/unstable/http/Multipart.ts +16 -13
  458. package/src/unstable/http/Template.ts +1 -1
  459. package/src/unstable/http/UrlParams.ts +17 -14
  460. package/src/unstable/httpapi/HttpApi.ts +3 -3
  461. package/src/unstable/httpapi/HttpApiClient.ts +5 -5
  462. package/src/unstable/httpapi/HttpApiGroup.ts +1 -1
  463. package/src/unstable/httpapi/OpenApi.ts +52 -28
  464. package/src/unstable/observability/OtlpExporter.ts +109 -5
  465. package/src/unstable/observability/OtlpLogger.ts +5 -5
  466. package/src/unstable/observability/OtlpMetrics.ts +8 -4
  467. package/src/unstable/observability/OtlpTracer.ts +8 -4
  468. package/src/unstable/persistence/Persistable.ts +3 -2
  469. package/src/unstable/persistence/RateLimiter.ts +2 -2
  470. package/src/unstable/persistence/Redis.ts +2 -2
  471. package/src/unstable/process/ChildProcessSpawner.ts +1 -1
  472. package/src/unstable/reactivity/AsyncResult.ts +4 -3
  473. package/src/unstable/reactivity/Atom.ts +92 -0
  474. package/src/unstable/reactivity/AtomRegistry.ts +1 -1
  475. package/src/unstable/rpc/RpcClient.ts +2 -1
  476. package/src/unstable/schema/VariantSchema.ts +14 -24
  477. package/src/unstable/socket/Socket.ts +1 -1
  478. package/src/unstable/sql/SqlError.ts +2 -2
  479. package/src/unstable/sql/Statement.ts +7 -6
  480. package/dist/SchemaUtils.d.ts +0 -28
  481. package/dist/SchemaUtils.d.ts.map +0 -1
  482. package/dist/SchemaUtils.js +0 -45
  483. package/dist/SchemaUtils.js.map +0 -1
  484. package/dist/internal/schema/arbitrary.d.ts.map +0 -1
  485. package/dist/internal/schema/arbitrary.js.map +0 -1
  486. package/dist/internal/schema/equivalence.d.ts +0 -2
  487. package/dist/internal/schema/equivalence.d.ts.map +0 -1
  488. package/dist/internal/schema/equivalence.js.map +0 -1
  489. package/dist/internal/schema/representation.d.ts +0 -2
  490. package/dist/internal/schema/representation.d.ts.map +0 -1
  491. package/dist/internal/schema/representation.js +0 -865
  492. package/dist/internal/schema/representation.js.map +0 -1
  493. package/src/SchemaUtils.ts +0 -51
  494. package/src/internal/schema/representation.ts +0 -795
@@ -8,13 +8,21 @@
8
8
  * storage constructor, layers, migrations, optional table prefixes, and the row
9
9
  * mapping needed by encoded message storage.
10
10
  *
11
+ * Request deduplication keys that exceed the 255-character `message_id`
12
+ * column are hashed with the `Crypto` service before they are written, so
13
+ * composed keys of any length are supported; shorter keys are stored as
14
+ * plaintext, byte-compatible with rows written by previous versions.
15
+ *
11
16
  * @since 4.0.0
12
17
  */
13
18
  // eslint-disable effect/no-bigint-literals
14
19
  import * as Arr from "../../Array.ts"
20
+ import * as Crypto from "../../Crypto.ts"
15
21
  import * as Effect from "../../Effect.ts"
22
+ import * as Encoding from "../../Encoding.ts"
16
23
  import * as Layer from "../../Layer.ts"
17
24
  import * as Option from "../../Option.ts"
25
+ import type * as PlatformError from "../../PlatformError.ts"
18
26
  import * as Schedule from "../../Schedule.ts"
19
27
  import * as Migrator from "../sql/Migrator.ts"
20
28
  import * as SqlClient from "../sql/SqlClient.ts"
@@ -61,9 +69,10 @@ export const make: (options?: {
61
69
  }) => Effect.Effect<
62
70
  MessageStorage.MessageStorage["Service"],
63
71
  never,
64
- SqlClient.SqlClient | Snowflake.Generator
72
+ SqlClient.SqlClient | Snowflake.Generator | Crypto.Crypto
65
73
  > = Effect.fnUntraced(function*(options) {
66
74
  const sql = (yield* SqlClient.SqlClient).withoutTransforms()
75
+ const crypto = yield* Crypto.Crypto
67
76
  const prefix = options?.prefix ?? "cluster"
68
77
  const table = (name: string) => `${prefix}_${name}`
69
78
 
@@ -84,6 +93,30 @@ export const make: (options?: {
84
93
  const repliesTable = table("replies")
85
94
  const repliesTableSql = sql(repliesTable)
86
95
 
96
+ // The composed primary key (`entityType/entityId/tag/id`) can legally exceed
97
+ // the 255-character `message_id` column: entity_type(150) + entity_id(255) +
98
+ // tag(50) alone total 458 characters before the RPC primary key is appended.
99
+ // Keys that fit are stored as-is, keeping `message_id` byte-compatible with
100
+ // rows written by previous versions; longer keys are stored as a SHA-256
101
+ // digest (64 hex characters, collision probability negligible at a 2^128
102
+ // birthday bound). Digests never contain "/" while composed keys always do,
103
+ // so the two encodings cannot collide.
104
+ const encoder = new TextEncoder()
105
+ const messageIdForPrimaryKey = (primaryKey: string): Effect.Effect<string, PlatformError.PlatformError> =>
106
+ primaryKey.length <= 255
107
+ ? Effect.succeed(primaryKey)
108
+ : Effect.map(crypto.digest("SHA-256", encoder.encode(primaryKey)), Encoding.encodeHex)
109
+
110
+ const messageIdEnforcesWidth = sql.onDialectOrElse({
111
+ mssql: () => true,
112
+ mysql: () => true,
113
+ pg: () => true,
114
+ orElse: () => false
115
+ })
116
+ // sqlite's TEXT message_id column stored over-length plaintext keys before
117
+ // digests were introduced; those legacy rows need a plaintext fallback read
118
+ const mayHaveLegacyRow = (primaryKey: string): boolean => !messageIdEnforcesWidth && primaryKey.length > 255
119
+
87
120
  const envelopeToRow = (
88
121
  envelope: Envelope.Encoded,
89
122
  message_id: string | null,
@@ -238,6 +271,14 @@ export const make: (options?: {
238
271
  const sqlFalse = sql.literal(supportsBooleans ? "FALSE" : "0")
239
272
  const sqlTrue = sql.literal(supportsBooleans ? "TRUE" : "1")
240
273
 
274
+ const selectByMessageId = (message_id: string): Effect.Effect<ReadonlyArray<Row>, SqlError> =>
275
+ sql`
276
+ SELECT m.id, r.id as reply_id, r.kind as reply_kind, r.payload as reply_payload, r.sequence as reply_sequence
277
+ FROM ${messagesTableSql} m
278
+ LEFT JOIN ${repliesTableSql} r ON r.id = m.last_reply_id
279
+ WHERE m.message_id = ${message_id}
280
+ `
281
+
241
282
  const insertEnvelope: (
242
283
  row: MessageRow,
243
284
  message_id: string
@@ -250,12 +291,7 @@ export const make: (options?: {
250
291
  `.pipe(Effect.flatMap((rows) => {
251
292
  // inserted a new row
252
293
  if (rows.length > 0) return Effect.succeed([])
253
- return sql`
254
- SELECT m.id, r.id as reply_id, r.kind as reply_kind, r.payload as reply_payload, r.sequence as reply_sequence
255
- FROM ${messagesTableSql} m
256
- LEFT JOIN ${repliesTableSql} r ON r.id = m.last_reply_id
257
- WHERE m.message_id = ${message_id}
258
- `
294
+ return selectByMessageId(message_id)
259
295
  })),
260
296
  mysql: () => (row, message_id) =>
261
297
  Effect.flatMap(
@@ -264,12 +300,7 @@ export const make: (options?: {
264
300
  if (row.affectedRows > 0) {
265
301
  return Effect.succeed([])
266
302
  }
267
- return sql`
268
- SELECT m.id, r.id as reply_id, r.kind as reply_kind, r.payload as reply_payload, r.sequence as reply_sequence
269
- FROM ${messagesTableSql} m
270
- LEFT JOIN ${repliesTableSql} r ON r.id = m.last_reply_id
271
- WHERE m.message_id = ${message_id}
272
- `
303
+ return selectByMessageId(message_id)
273
304
  }
274
305
  ),
275
306
  mssql: () => (row, message_id) =>
@@ -311,12 +342,7 @@ export const make: (options?: {
311
342
  END as reply_sequence;
312
343
  `,
313
344
  orElse: () => (row, message_id) =>
314
- sql`
315
- SELECT m.id, r.id as reply_id, r.kind as reply_kind, r.payload as reply_payload, r.sequence as reply_sequence
316
- FROM ${messagesTableSql} m
317
- LEFT JOIN ${repliesTableSql} r ON r.id = m.last_reply_id
318
- WHERE m.message_id = ${message_id}
319
- `.pipe(
345
+ selectByMessageId(message_id).pipe(
320
346
  Effect.tap(sql`INSERT OR IGNORE INTO ${messagesTableSql} ${sql.insert(row)}`),
321
347
  sql.withTransaction,
322
348
  Effect.retry({ times: 3 })
@@ -406,18 +432,30 @@ export const make: (options?: {
406
432
  return yield* MessageStorage.makeEncoded({
407
433
  saveEnvelope: ({ deliverAt, envelope, primaryKey }) =>
408
434
  Effect.suspend(() => {
409
- const row = envelopeToRow(envelope, primaryKey, deliverAt)
410
- let insert = primaryKey
411
- ? insertEnvelope(row, primaryKey)
412
- : Effect.as(sql`INSERT INTO ${messagesTableSql} ${sql.insert(row)}`.unprepared, [])
413
- if (envelope._tag === "AckChunk") {
414
- insert = sql`UPDATE ${repliesTableSql} SET acked = ${sqlTrue} WHERE id = ${envelope.replyId}`.pipe(
415
- Effect.andThen(
416
- sql`UPDATE ${messagesTableSql} SET processed = ${sqlTrue} WHERE processed = ${sqlFalse} AND request_id = ${envelope.requestId} AND kind = ${messageKindAckChunk}`
417
- ),
418
- Effect.andThen(insert),
419
- sql.withTransaction
420
- )
435
+ let insert: Effect.Effect<ReadonlyArray<Row>, SqlError | PlatformError.PlatformError>
436
+ if (primaryKey !== null) {
437
+ insert = Effect.flatMap(messageIdForPrimaryKey(primaryKey), (messageId) => {
438
+ const row = envelopeToRow(envelope, messageId, deliverAt)
439
+ if (!mayHaveLegacyRow(primaryKey)) {
440
+ return insertEnvelope(row, messageId)
441
+ }
442
+ return Effect.flatMap(
443
+ selectByMessageId(primaryKey),
444
+ (rows) => rows.length > 0 ? Effect.succeed(rows) : insertEnvelope(row, messageId)
445
+ )
446
+ })
447
+ } else {
448
+ const row = envelopeToRow(envelope, null, deliverAt)
449
+ insert = Effect.as(sql`INSERT INTO ${messagesTableSql} ${sql.insert(row)}`.unprepared, [])
450
+ if (envelope._tag === "AckChunk") {
451
+ insert = sql`UPDATE ${repliesTableSql} SET acked = ${sqlTrue} WHERE id = ${envelope.replyId}`.pipe(
452
+ Effect.andThen(
453
+ sql`UPDATE ${messagesTableSql} SET processed = ${sqlTrue} WHERE processed = ${sqlFalse} AND request_id = ${envelope.requestId} AND kind = ${messageKindAckChunk}`
454
+ ),
455
+ Effect.andThen(insert),
456
+ sql.withTransaction
457
+ )
458
+ }
421
459
  }
422
460
  return insert.pipe(
423
461
  Effect.map((rows) => {
@@ -488,7 +526,15 @@ export const make: (options?: {
488
526
  ),
489
527
 
490
528
  requestIdForPrimaryKey: (primaryKey) =>
491
- sql<{ id: string | bigint }>`SELECT id FROM ${messagesTableSql} WHERE message_id = ${primaryKey}`.pipe(
529
+ messageIdForPrimaryKey(primaryKey).pipe(
530
+ Effect.flatMap((messageId) =>
531
+ sql<{ id: string | bigint }>`SELECT id FROM ${messagesTableSql} WHERE message_id = ${messageId}`
532
+ ),
533
+ Effect.flatMap((rows) =>
534
+ rows.length === 0 && mayHaveLegacyRow(primaryKey)
535
+ ? sql<{ id: string | bigint }>`SELECT id FROM ${messagesTableSql} WHERE message_id = ${primaryKey}`
536
+ : Effect.succeed(rows)
537
+ ),
492
538
  Effect.map((rows) => Option.map(Option.fromNullishOr(rows[0]?.id), Snowflake.Snowflake)),
493
539
  Effect.provideService(SqlClient.SafeIntegers, true),
494
540
  PersistenceError.refail,
@@ -645,7 +691,9 @@ export const make: (options?: {
645
691
  *
646
692
  * The layer runs the SQL migrations through `make`, provides `MessageStorage`,
647
693
  * and supplies `Snowflake.layerGenerator` internally. Callers still provide
648
- * `SqlClient` and `ShardingConfig`.
694
+ * `SqlClient`, `ShardingConfig`, and `Crypto.Crypto`, which is used to hash
695
+ * message deduplication keys that would overflow the fixed-width
696
+ * `message_id` column.
649
697
  *
650
698
  * **Gotchas**
651
699
  *
@@ -662,7 +710,7 @@ export const make: (options?: {
662
710
  export const layer: Layer.Layer<
663
711
  MessageStorage.MessageStorage,
664
712
  never,
665
- SqlClient.SqlClient | ShardingConfig
713
+ SqlClient.SqlClient | ShardingConfig | Crypto.Crypto
666
714
  > = Layer.effect(MessageStorage.MessageStorage, make()).pipe(
667
715
  Layer.provide(Snowflake.layerGenerator)
668
716
  )
@@ -675,7 +723,7 @@ export const layer: Layer.Layer<
675
723
  */
676
724
  export const layerWith = (options: {
677
725
  readonly prefix?: string | undefined
678
- }): Layer.Layer<MessageStorage.MessageStorage, never, SqlClient.SqlClient | ShardingConfig> =>
726
+ }): Layer.Layer<MessageStorage.MessageStorage, never, SqlClient.SqlClient | ShardingConfig | Crypto.Crypto> =>
679
727
  Layer.effect(MessageStorage.MessageStorage, make(options)).pipe(
680
728
  Layer.provide(Snowflake.layerGenerator)
681
729
  )
@@ -12,6 +12,8 @@
12
12
  import * as Arr from "../../Array.ts"
13
13
  import * as Duration from "../../Duration.ts"
14
14
  import * as Effect from "../../Effect.ts"
15
+ import * as Exit from "../../Exit.ts"
16
+ import * as Fiber from "../../Fiber.ts"
15
17
  import * as Layer from "../../Layer.ts"
16
18
  import * as Scope from "../../Scope.ts"
17
19
  import * as SqlClient from "../sql/SqlClient.ts"
@@ -19,6 +21,7 @@ import type { SqlError } from "../sql/SqlError.ts"
19
21
  import type * as Statement from "../sql/Statement.ts"
20
22
  import { PersistenceError } from "./ClusterError.ts"
21
23
  import { ResourceRef } from "./internal/resourceRef.ts"
24
+ import { effectiveInterval } from "./internal/shardLock.ts"
22
25
  import * as RunnerStorage from "./RunnerStorage.ts"
23
26
  import * as ShardId from "./ShardId.ts"
24
27
  import * as ShardingConfig from "./ShardingConfig.ts"
@@ -60,18 +63,31 @@ export const make = Effect.fnUntraced(function*(options: {
60
63
  const shardGroups = ShardingConfig.shardGroupConfig(config)
61
64
  const availableShardGroups = Array.from(shardGroups.available)
62
65
  const disableAdvisoryLocks = config.shardLockDisableAdvisory
66
+ const lockOperationInterval = effectiveInterval(config)
63
67
  const sql = (yield* SqlClient.SqlClient).withoutTransforms()
68
+ const layerScope = yield* Effect.scope
64
69
  const prefix = options?.prefix ?? "cluster"
65
70
  const table = (name: string) => `${prefix}_${name}`
66
71
 
72
+ // Keep all PostgreSQL and MySQL shard-lock operations on a rebuildable
73
+ // reserved connection, including when advisory locks are disabled.
67
74
  const acquireLockConn = sql.onDialectOrElse({
68
75
  pg: () =>
69
76
  Effect.fnUntraced(function*(scope: Scope.Scope) {
70
77
  const conn = yield* Effect.orDie(sql.reserve).pipe(
71
78
  Scope.provide(scope)
72
79
  )
73
- const pid = (yield* conn.executeValues("SELECT pg_backend_pid()", []))[0][0] as number
74
- yield* Scope.addFinalizerExit(scope, () => Effect.orDie(conn.executeRaw("SELECT pg_advisory_unlock_all()", [])))
80
+ const pid = disableAdvisoryLocks
81
+ ? 0
82
+ : (yield* conn.executeValues("SELECT pg_backend_pid()", []))[0][0] as number
83
+ if (!disableAdvisoryLocks) {
84
+ yield* Scope.addFinalizerExit(scope, () =>
85
+ conn.executeRaw("SELECT pg_advisory_unlock_all()", []).pipe(
86
+ Effect.timeout(lockOperationInterval),
87
+ Effect.interruptible,
88
+ Effect.ignoreCause
89
+ ))
90
+ }
75
91
  return [conn, pid] as const
76
92
  }, Effect.orDie),
77
93
  mysql: () =>
@@ -79,6 +95,7 @@ export const make = Effect.fnUntraced(function*(options: {
79
95
  const conn = yield* Effect.orDie(sql.reserve).pipe(
80
96
  Scope.provide(scope)
81
97
  )
98
+ if (disableAdvisoryLocks) return [conn, 0] as const
82
99
  // we need to get the connection id using IS_USED_LOCK to properly
83
100
  // support vitess
84
101
  let pid: number | undefined = undefined
@@ -91,12 +108,79 @@ export const make = Effect.fnUntraced(function*(options: {
91
108
  if (taken[0] === null) continue
92
109
  pid = taken[1]
93
110
  }
94
- yield* Scope.addFinalizerExit(scope, () => Effect.orDie(conn.executeRaw("SELECT RELEASE_ALL_LOCKS()", [])))
111
+ if (!disableAdvisoryLocks) {
112
+ yield* Scope.addFinalizerExit(scope, () =>
113
+ conn.executeRaw("SELECT RELEASE_ALL_LOCKS()", []).pipe(
114
+ Effect.timeout(lockOperationInterval),
115
+ Effect.interruptible,
116
+ Effect.ignoreCause
117
+ ))
118
+ }
95
119
  return [conn, pid] as const
96
120
  }, Effect.orDie),
97
121
  orElse: () => undefined
98
122
  })
99
- const lockConn = acquireLockConn && (yield* ResourceRef.from(yield* Effect.scope, acquireLockConn))
123
+ const lockConn = acquireLockConn && (yield* ResourceRef.from(layerScope, acquireLockConn))
124
+
125
+ // `Effect.timeout` waits for the timed-out effect to finish interrupting, so
126
+ // an operation stuck in an uninterruptible region (such as a scope finalizer
127
+ // releasing an unresponsive connection) can outlive its deadline. Fork the
128
+ // operation and timeout the join instead, leaving stalled cleanup to finish
129
+ // detached in the layer scope.
130
+ const withDeadline = Effect.fnUntraced(function*<A, E, R>(operation: Effect.Effect<A, E, R>) {
131
+ const fiber = yield* Effect.forkIn(operation, layerScope, { startImmediately: true })
132
+ return yield* Fiber.join(fiber).pipe(
133
+ Effect.timeout(lockOperationInterval),
134
+ Effect.ensuring(Effect.suspend(() =>
135
+ fiber.pollUnsafe() !== undefined ? Effect.void : Fiber.interrupt(fiber).pipe(
136
+ Effect.forkIn(layerScope, { startImmediately: true }),
137
+ Effect.asVoid
138
+ )
139
+ ))
140
+ )
141
+ })
142
+
143
+ let lockConnRebuilding = false
144
+ // Incremented every time the reserved connection is replaced, so failures
145
+ // from operations that ran on an already replaced connection do not trigger
146
+ // another rebuild.
147
+ let lockConnGeneration = 0
148
+ const rebuildLockConn = (generation: number) => {
149
+ if (
150
+ !lockConn ||
151
+ lockConnRebuilding ||
152
+ generation !== lockConnGeneration ||
153
+ lockConn.state.current._tag === "Closed"
154
+ ) return Effect.void
155
+ lockConnRebuilding = true
156
+ // The rebuild starts by closing the previous scope, releasing the
157
+ // unresponsive connection back to the pool. Bound it with `withDeadline`
158
+ // so a release that never completes cannot leave `lockConnRebuilding` set
159
+ // forever, which would disable every subsequent rebuild.
160
+ return withDeadline(lockConn.rebuildUnsafe()).pipe(
161
+ Effect.exit,
162
+ Effect.tap((exit) =>
163
+ Effect.sync(() => {
164
+ if (Exit.isSuccess(exit) && lockConn.state.current._tag === "Acquired") {
165
+ lockConnGeneration++
166
+ }
167
+ })
168
+ ),
169
+ Effect.ensuring(Effect.sync(() => {
170
+ lockConnRebuilding = false
171
+ })),
172
+ Effect.forkIn(layerScope, { startImmediately: true }),
173
+ Effect.asVoid
174
+ )
175
+ }
176
+ // Rebuild the reserved connection when `effect` fails on it. Failures keep
177
+ // scheduling rebuilds, so a rebuilt connection that is also unresponsive is
178
+ // replaced again.
179
+ const onErrorRebuildLockConn = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
180
+ Effect.suspend(() => {
181
+ const generation = lockConnGeneration
182
+ return Effect.onError(effect, () => rebuildLockConn(generation))
183
+ })
100
184
 
101
185
  const runnersTable = table("runners")
102
186
  const runnersTableSql = sql(runnersTable)
@@ -276,7 +360,7 @@ export const make = Effect.fnUntraced(function*(options: {
276
360
  const [query, params] = effect.compile()
277
361
  return lockConn.await.pipe(
278
362
  Effect.flatMap(([conn]) => conn.executeRaw(query, params)),
279
- Effect.onError(() => lockConn.rebuildUnsafe())
363
+ onErrorRebuildLockConn
280
364
  )
281
365
  }
282
366
  const execWithLockConnUnprepared = <A>(
@@ -286,7 +370,7 @@ export const make = Effect.fnUntraced(function*(options: {
286
370
  const [query, params] = effect.compile()
287
371
  return lockConn.await.pipe(
288
372
  Effect.flatMap(([conn]) => conn.executeUnprepared(query, params, undefined)),
289
- Effect.onError(() => lockConn.rebuildUnsafe())
373
+ onErrorRebuildLockConn
290
374
  )
291
375
  }
292
376
  const execWithLockConnValues = <A>(
@@ -296,7 +380,7 @@ export const make = Effect.fnUntraced(function*(options: {
296
380
  const [query, params] = effect.compile()
297
381
  return lockConn.await.pipe(
298
382
  Effect.flatMap(([conn]) => conn.executeValues(query, params)),
299
- Effect.onError(() => lockConn.rebuildUnsafe())
383
+ onErrorRebuildLockConn
300
384
  )
301
385
  }
302
386
 
@@ -314,6 +398,7 @@ export const make = Effect.fnUntraced(function*(options: {
314
398
  WHERE ${locksTableSql}.address = ${address}
315
399
  OR ${locksTableSql}.acquired_at < ${lockExpiresAt}
316
400
  `.pipe(
401
+ execWithLockConn,
317
402
  Effect.andThen(acquiredLocks(address, shardIds))
318
403
  )
319
404
  }
@@ -342,7 +427,7 @@ export const make = Effect.fnUntraced(function*(options: {
342
427
  }
343
428
  }
344
429
  return acquiredShardIds
345
- }, Effect.onError(() => lockConn!.rebuildUnsafe()))
430
+ }, onErrorRebuildLockConn)
346
431
  },
347
432
 
348
433
  mysql: () => {
@@ -356,7 +441,8 @@ export const make = Effect.fnUntraced(function*(options: {
356
441
  ON DUPLICATE KEY UPDATE
357
442
  address = IF(address = VALUES(address) OR acquired_at < ${lockExpiresAt}, VALUES(address), address),
358
443
  acquired_at = IF(address = VALUES(address) OR acquired_at < ${lockExpiresAt}, VALUES(acquired_at), acquired_at)
359
- `.unprepared.pipe(
444
+ `.pipe(
445
+ execWithLockConnUnprepared,
360
446
  Effect.andThen(acquiredLocks(address, shardIds))
361
447
  )
362
448
  }
@@ -385,7 +471,7 @@ export const make = Effect.fnUntraced(function*(options: {
385
471
  }
386
472
  }
387
473
  return acquiredShardIds
388
- }, Effect.onError(() => lockConn!.rebuildUnsafe()))
474
+ }, onErrorRebuildLockConn)
389
475
  },
390
476
 
391
477
  mssql: () => (address: string, shardIds: ReadonlyArray<string>) => {
@@ -477,7 +563,8 @@ export const make = Effect.fnUntraced(function*(options: {
477
563
  WHERE address = ${address}
478
564
  AND acquired_at >= ${lockExpiresAt}
479
565
  AND shard_id IN ${stringLiteralArr(shardIds)}
480
- `.values.pipe(
566
+ `.pipe(
567
+ execWithLockConnValues,
481
568
  Effect.map((rows) => rows.map((row) => row[0] as string))
482
569
  )
483
570
 
@@ -533,6 +620,72 @@ export const make = Effect.fnUntraced(function*(options: {
533
620
  `.pipe(execWithLockConnValues, Effect.map((rows) => rows.map((row) => row[0] as string)))
534
621
  })
535
622
 
623
+ const withLockOperationDeadline = <A, E, R>(operation: Effect.Effect<A, E, R>) =>
624
+ onErrorRebuildLockConn(withDeadline(operation))
625
+
626
+ const releaseShard = sql.onDialectOrElse({
627
+ pg: () => {
628
+ if (disableAdvisoryLocks) {
629
+ return (address: string, shardId: string) =>
630
+ sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(execWithLockConn)
631
+ }
632
+ return Effect.fnUntraced(
633
+ function*(_address, shardId) {
634
+ const lockNum = lockNumbers.get(shardId)!
635
+ for (let i = 0; i < 5; i++) {
636
+ const [conn] = yield* lockConn!.await
637
+ yield* conn.executeRaw(`SELECT pg_advisory_unlock(${lockNum})`, [])
638
+ const takenLocks = yield* conn.executeValues(
639
+ `SELECT 1 FROM pg_locks WHERE locktype = 'advisory' AND granted = true AND pid = pg_backend_pid() AND objid = ${lockNum}`,
640
+ []
641
+ )
642
+ if (takenLocks.length === 0) return
643
+ }
644
+ const [conn] = yield* lockConn!.await
645
+ yield* conn.executeRaw(`SELECT pg_advisory_unlock_all()`, [])
646
+ },
647
+ onErrorRebuildLockConn,
648
+ Effect.asVoid
649
+ )
650
+ },
651
+ mysql: () => {
652
+ if (disableAdvisoryLocks) {
653
+ return (address: string, shardId: string) =>
654
+ sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(execWithLockConn)
655
+ }
656
+ return Effect.fnUntraced(
657
+ function*(_address, shardId) {
658
+ const lockName = lockNames.get(shardId)!
659
+ while (true) {
660
+ const [conn, pid] = yield* lockConn!.await
661
+ yield* conn.executeRaw(`SELECT RELEASE_LOCK('${lockName}')`, [])
662
+ const takenLocks = yield* conn.executeValues(
663
+ `SELECT IS_USED_LOCK('${lockName}')`,
664
+ []
665
+ )
666
+ if (takenLocks.length === 0 || takenLocks[0][0] !== pid) return
667
+ }
668
+ },
669
+ onErrorRebuildLockConn,
670
+ Effect.asVoid
671
+ )
672
+ },
673
+ orElse: () => (address: string, shardId: string) =>
674
+ sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`
675
+ })
676
+
677
+ const releaseAllShards = sql.onDialectOrElse({
678
+ pg: () => (address: string) =>
679
+ disableAdvisoryLocks
680
+ ? sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(execWithLockConn)
681
+ : sql`SELECT pg_advisory_unlock_all()`.pipe(execWithLockConn, Effect.asVoid),
682
+ mysql: () => (address: string) =>
683
+ disableAdvisoryLocks
684
+ ? sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(execWithLockConn)
685
+ : sql`SELECT RELEASE_ALL_LOCKS()`.pipe(execWithLockConn, Effect.asVoid),
686
+ orElse: () => (address: string) => sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`
687
+ })
688
+
536
689
  return RunnerStorage.makeEncoded({
537
690
  getRunners: sql`SELECT runner, healthy FROM ${runnersTableSql} WHERE last_heartbeat > ${lockExpiresAt}`.values.pipe(
538
691
  PersistenceError.refail,
@@ -563,120 +716,37 @@ export const make = Effect.fnUntraced(function*(options: {
563
716
  ),
564
717
 
565
718
  acquire: (address, shardIds) =>
566
- acquireLock(address, shardIds).pipe(
719
+ withLockOperationDeadline(acquireLock(address, shardIds)).pipe(
567
720
  PersistenceError.refail,
568
721
  withTracerDisabled
569
722
  ),
570
723
 
571
724
  refresh: (address, shardIds) =>
572
- sql`UPDATE ${runnersTableSql} SET last_heartbeat = ${sqlNow} WHERE address = ${address}`.pipe(
573
- execWithLockConn,
574
- shardIds.length > 0 ?
575
- Effect.andThen(refreshShards(address, shardIds)) :
576
- Effect.as([]),
725
+ withLockOperationDeadline(
726
+ sql`UPDATE ${runnersTableSql} SET last_heartbeat = ${sqlNow} WHERE address = ${address}`.pipe(
727
+ execWithLockConn,
728
+ shardIds.length > 0 ?
729
+ Effect.andThen(refreshShards(address, shardIds)) :
730
+ Effect.as([])
731
+ )
732
+ ).pipe(
577
733
  PersistenceError.refail,
578
734
  withTracerDisabled
579
735
  ),
580
736
 
581
- release: sql.onDialectOrElse({
582
- pg: () => {
583
- if (disableAdvisoryLocks) {
584
- return (address: string, shardId: string) =>
585
- sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(
586
- PersistenceError.refail,
587
- withTracerDisabled
588
- )
589
- }
590
- return Effect.fnUntraced(
591
- function*(_address, shardId) {
592
- const lockNum = lockNumbers.get(shardId)!
593
- for (let i = 0; i < 5; i++) {
594
- const [conn] = yield* lockConn!.await
595
- yield* conn.executeRaw(`SELECT pg_advisory_unlock(${lockNum})`, [])
596
- const takenLocks = yield* conn.executeValues(
597
- `SELECT 1 FROM pg_locks WHERE locktype = 'advisory' AND granted = true AND pid = pg_backend_pid() AND objid = ${lockNum}`,
598
- []
599
- )
600
- if (takenLocks.length === 0) return
601
- }
602
- const [conn] = yield* lockConn!.await
603
- yield* conn.executeRaw(`SELECT pg_advisory_unlock_all()`, [])
604
- },
605
- Effect.onError(() => lockConn!.rebuildUnsafe()),
606
- Effect.asVoid,
607
- PersistenceError.refail,
608
- withTracerDisabled
609
- )
610
- },
611
- mysql: () => {
612
- if (disableAdvisoryLocks) {
613
- return (address: string, shardId: string) =>
614
- sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(
615
- PersistenceError.refail,
616
- withTracerDisabled
617
- )
618
- }
619
- return Effect.fnUntraced(
620
- function*(_address, shardId) {
621
- const lockName = lockNames.get(shardId)!
622
- while (true) {
623
- const [conn, pid] = yield* lockConn!.await
624
- yield* conn.executeRaw(`SELECT RELEASE_LOCK('${lockName}')`, [])
625
- const takenLocks = yield* conn.executeValues(
626
- `SELECT IS_USED_LOCK('${lockName}')`,
627
- []
628
- )
629
- if (takenLocks.length === 0 || takenLocks[0][0] !== pid) return
630
- }
631
- },
632
- Effect.onError(() => lockConn!.rebuildUnsafe()),
633
- Effect.asVoid,
634
- PersistenceError.refail,
635
- withTracerDisabled
636
- )
637
- },
638
- orElse: () => (address, shardId) =>
639
- sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(
640
- PersistenceError.refail,
641
- withTracerDisabled
642
- )
643
- }),
644
-
645
- releaseAll: sql.onDialectOrElse({
646
- pg: () => (address) => {
647
- if (disableAdvisoryLocks) {
648
- return sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(
649
- PersistenceError.refail,
650
- withTracerDisabled
651
- )
652
- }
653
- return sql`SELECT pg_advisory_unlock_all()`.pipe(
654
- execWithLockConn,
655
- Effect.asVoid,
656
- PersistenceError.refail,
657
- withTracerDisabled
658
- )
659
- },
660
- mysql: () => (address) => {
661
- if (disableAdvisoryLocks) {
662
- return sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(
663
- PersistenceError.refail,
664
- withTracerDisabled
665
- )
666
- }
667
- return sql`SELECT RELEASE_ALL_LOCKS()`.pipe(
668
- execWithLockConn,
669
- Effect.asVoid,
670
- PersistenceError.refail,
671
- withTracerDisabled
672
- )
673
- },
674
- orElse: () => (address) =>
675
- sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(
676
- PersistenceError.refail,
677
- withTracerDisabled
678
- )
679
- })
737
+ release: (address, shardId) =>
738
+ withLockOperationDeadline(releaseShard(address, shardId)).pipe(
739
+ Effect.asVoid,
740
+ PersistenceError.refail,
741
+ withTracerDisabled
742
+ ),
743
+
744
+ releaseAll: (address) =>
745
+ withLockOperationDeadline(releaseAllShards(address)).pipe(
746
+ Effect.asVoid,
747
+ PersistenceError.refail,
748
+ withTracerDisabled
749
+ )
680
750
  })
681
751
  }, withTracerDisabled)
682
752