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.
- package/dist/Array.d.ts.map +1 -1
- package/dist/Array.js +81 -5
- package/dist/Array.js.map +1 -1
- package/dist/Channel.d.ts.map +1 -1
- package/dist/Channel.js +27 -9
- package/dist/Channel.js.map +1 -1
- package/dist/Config.d.ts +1 -1
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js +6 -5
- package/dist/Config.js.map +1 -1
- package/dist/ConfigProvider.js +7 -7
- package/dist/ConfigProvider.js.map +1 -1
- package/dist/Data.d.ts.map +1 -1
- package/dist/Data.js +2 -1
- package/dist/Data.js.map +1 -1
- package/dist/Effect.d.ts +61 -100
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +66 -39
- package/dist/Effect.js.map +1 -1
- package/dist/FiberHandle.d.ts.map +1 -1
- package/dist/FiberHandle.js +3 -2
- package/dist/FiberHandle.js.map +1 -1
- package/dist/Iterable.d.ts.map +1 -1
- package/dist/Iterable.js +2 -1
- package/dist/Iterable.js.map +1 -1
- package/dist/JsonPatch.d.ts.map +1 -1
- package/dist/JsonPatch.js +4 -3
- package/dist/JsonPatch.js.map +1 -1
- package/dist/JsonSchema.d.ts.map +1 -1
- package/dist/JsonSchema.js +9 -11
- package/dist/JsonSchema.js.map +1 -1
- package/dist/Logger.d.ts.map +1 -1
- package/dist/Logger.js +3 -2
- package/dist/Logger.js.map +1 -1
- package/dist/ManagedRuntime.d.ts +9 -0
- package/dist/ManagedRuntime.d.ts.map +1 -1
- package/dist/ManagedRuntime.js +3 -0
- package/dist/ManagedRuntime.js.map +1 -1
- package/dist/Metric.d.ts.map +1 -1
- package/dist/Metric.js +4 -3
- package/dist/Metric.js.map +1 -1
- package/dist/Optic.d.ts.map +1 -1
- package/dist/Optic.js +5 -4
- package/dist/Optic.js.map +1 -1
- package/dist/Option.d.ts.map +1 -1
- package/dist/Option.js +2 -1
- package/dist/Option.js.map +1 -1
- package/dist/PartitionedSemaphore.d.ts.map +1 -1
- package/dist/PartitionedSemaphore.js +1 -4
- package/dist/PartitionedSemaphore.js.map +1 -1
- package/dist/Record.d.ts +93 -1
- package/dist/Record.d.ts.map +1 -1
- package/dist/Record.js +57 -19
- package/dist/Record.js.map +1 -1
- package/dist/References.d.ts +0 -45
- package/dist/References.d.ts.map +1 -1
- package/dist/References.js +0 -45
- package/dist/References.js.map +1 -1
- package/dist/Request.d.ts.map +1 -1
- package/dist/Request.js +9 -6
- package/dist/Request.js.map +1 -1
- package/dist/Result.d.ts.map +1 -1
- package/dist/Result.js +2 -1
- package/dist/Result.js.map +1 -1
- package/dist/Schema.d.ts +1268 -495
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +2308 -614
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaAST.d.ts +2 -2
- package/dist/SchemaAST.d.ts.map +1 -1
- package/dist/SchemaAST.js +189 -130
- package/dist/SchemaAST.js.map +1 -1
- package/dist/SchemaError.js +1 -1
- package/dist/SchemaError.js.map +1 -1
- package/dist/SchemaGetter.d.ts +13 -11
- package/dist/SchemaGetter.d.ts.map +1 -1
- package/dist/SchemaGetter.js +34 -24
- package/dist/SchemaGetter.js.map +1 -1
- package/dist/SchemaIssue.js +1 -1
- package/dist/SchemaIssue.js.map +1 -1
- package/dist/SchemaParser.d.ts.map +1 -1
- package/dist/SchemaParser.js +1 -12
- package/dist/SchemaParser.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +403 -1504
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +294 -2852
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/SchemaTransformation.d.ts +2 -2
- package/dist/SchemaTransformation.js +3 -3
- package/dist/SchemaTransformation.js.map +1 -1
- package/dist/Semaphore.d.ts +5 -3
- package/dist/Semaphore.d.ts.map +1 -1
- package/dist/Semaphore.js.map +1 -1
- package/dist/Stream.d.ts +15 -9
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +46 -16
- package/dist/Stream.js.map +1 -1
- package/dist/Struct.d.ts.map +1 -1
- package/dist/Struct.js +5 -4
- package/dist/Struct.js.map +1 -1
- package/dist/Types.d.ts +1 -3
- package/dist/Types.d.ts.map +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/core.js +2 -1
- package/dist/internal/core.js.map +1 -1
- package/dist/internal/effect.js +64 -21
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/matcher.js +1 -1
- package/dist/internal/matcher.js.map +1 -1
- package/dist/internal/record.d.ts +0 -3
- package/dist/internal/record.d.ts.map +1 -1
- package/dist/internal/record.js +10 -5
- package/dist/internal/record.js.map +1 -1
- package/dist/internal/references.js +0 -4
- package/dist/internal/references.js.map +1 -1
- package/dist/internal/schema/annotations.js +12 -0
- package/dist/internal/schema/annotations.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.d.ts +2 -0
- package/dist/internal/schema/fromJsonSchemaDocument.d.ts.map +1 -0
- package/dist/internal/schema/fromJsonSchemaDocument.js +743 -0
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -0
- package/dist/internal/schema/fromRepresentation.d.ts +2 -0
- package/dist/internal/schema/fromRepresentation.d.ts.map +1 -0
- package/dist/internal/schema/fromRepresentation.js +252 -0
- package/dist/internal/schema/fromRepresentation.js.map +1 -0
- package/dist/internal/schema/schema.js +28 -40
- package/dist/internal/schema/schema.js.map +1 -1
- package/dist/internal/schema/{arbitrary.d.ts → toArbitrary.d.ts} +1 -1
- package/dist/internal/schema/toArbitrary.d.ts.map +1 -0
- package/dist/internal/schema/{arbitrary.js → toArbitrary.js} +8 -9
- package/dist/internal/schema/toArbitrary.js.map +1 -0
- package/dist/internal/schema/toCodeDocument.d.ts +2 -0
- package/dist/internal/schema/toCodeDocument.d.ts.map +1 -0
- package/dist/internal/schema/toCodeDocument.js +438 -0
- package/dist/internal/schema/toCodeDocument.js.map +1 -0
- package/dist/internal/schema/toEquivalence.d.ts +2 -0
- package/dist/internal/schema/toEquivalence.d.ts.map +1 -0
- package/dist/internal/schema/{equivalence.js → toEquivalence.js} +15 -13
- package/dist/internal/schema/toEquivalence.js.map +1 -0
- package/dist/internal/schema/toJsonSchemaDocument.d.ts +2 -0
- package/dist/internal/schema/toJsonSchemaDocument.d.ts.map +1 -0
- package/dist/internal/schema/toJsonSchemaDocument.js +466 -0
- package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -0
- package/dist/internal/schema/toRepresentation.d.ts +2 -0
- package/dist/internal/schema/toRepresentation.d.ts.map +1 -0
- package/dist/internal/schema/toRepresentation.js +369 -0
- package/dist/internal/schema/toRepresentation.js.map +1 -0
- package/dist/internal/stackTraceLimit.js +3 -6
- package/dist/internal/stackTraceLimit.js.map +1 -1
- package/dist/testing/TestClock.js +4 -1
- package/dist/testing/TestClock.js.map +1 -1
- package/dist/unstable/ai/AiError.d.ts +26 -26
- package/dist/unstable/ai/AiError.d.ts.map +1 -1
- package/dist/unstable/ai/AiError.js +5 -4
- package/dist/unstable/ai/AiError.js.map +1 -1
- package/dist/unstable/ai/AnthropicStructuredOutput.d.ts +21 -6
- package/dist/unstable/ai/AnthropicStructuredOutput.d.ts.map +1 -1
- package/dist/unstable/ai/AnthropicStructuredOutput.js +86 -316
- package/dist/unstable/ai/AnthropicStructuredOutput.js.map +1 -1
- package/dist/unstable/ai/EmbeddingModel.d.ts +1 -1
- package/dist/unstable/ai/EmbeddingModel.js +1 -1
- package/dist/unstable/ai/EmbeddingModel.js.map +1 -1
- package/dist/unstable/ai/LanguageModel.d.ts +4 -1
- package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
- package/dist/unstable/ai/LanguageModel.js +19 -17
- package/dist/unstable/ai/LanguageModel.js.map +1 -1
- package/dist/unstable/ai/McpSchema.d.ts +197 -197
- package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
- package/dist/unstable/ai/McpSchema.js +13 -13
- package/dist/unstable/ai/McpSchema.js.map +1 -1
- package/dist/unstable/ai/McpServer.d.ts +4 -4
- package/dist/unstable/ai/McpServer.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.js +116 -49
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/ai/OpenAiStructuredOutput.d.ts +32 -10
- package/dist/unstable/ai/OpenAiStructuredOutput.d.ts.map +1 -1
- package/dist/unstable/ai/OpenAiStructuredOutput.js +193 -377
- package/dist/unstable/ai/OpenAiStructuredOutput.js.map +1 -1
- package/dist/unstable/ai/Response.d.ts +19 -19
- package/dist/unstable/ai/Response.d.ts.map +1 -1
- package/dist/unstable/ai/Response.js +14 -14
- package/dist/unstable/ai/Response.js.map +1 -1
- package/dist/unstable/ai/Tool.d.ts +4 -0
- package/dist/unstable/ai/Tool.d.ts.map +1 -1
- package/dist/unstable/ai/Tool.js +11 -3
- package/dist/unstable/ai/Tool.js.map +1 -1
- package/dist/unstable/ai/Toolkit.d.ts +9 -1
- package/dist/unstable/ai/Toolkit.d.ts.map +1 -1
- package/dist/unstable/ai/Toolkit.js +14 -10
- package/dist/unstable/ai/Toolkit.js.map +1 -1
- package/dist/unstable/ai/internal/codec-transformer.js +15 -12
- package/dist/unstable/ai/internal/codec-transformer.js.map +1 -1
- package/dist/unstable/ai/internal/structured-output.d.ts +2 -0
- package/dist/unstable/ai/internal/structured-output.d.ts.map +1 -0
- package/dist/unstable/ai/internal/structured-output.js +316 -0
- package/dist/unstable/ai/internal/structured-output.js.map +1 -0
- package/dist/unstable/cli/CliError.d.ts +40 -2
- package/dist/unstable/cli/CliError.d.ts.map +1 -1
- package/dist/unstable/cli/CliError.js +45 -6
- package/dist/unstable/cli/CliError.js.map +1 -1
- package/dist/unstable/cli/Command.js +14 -5
- package/dist/unstable/cli/Command.js.map +1 -1
- package/dist/unstable/cli/Param.js +3 -3
- package/dist/unstable/cli/Param.js.map +1 -1
- package/dist/unstable/cli/Primitive.js +1 -1
- package/dist/unstable/cli/Primitive.js.map +1 -1
- package/dist/unstable/cli/internal/command.d.ts +3 -1
- package/dist/unstable/cli/internal/command.d.ts.map +1 -1
- package/dist/unstable/cli/internal/command.js +11 -4
- package/dist/unstable/cli/internal/command.js.map +1 -1
- package/dist/unstable/cli/internal/config.d.ts +0 -48
- package/dist/unstable/cli/internal/config.d.ts.map +1 -1
- package/dist/unstable/cli/internal/config.js +8 -10
- package/dist/unstable/cli/internal/config.js.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.js +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/unstable/cluster/Entity.js +1 -1
- package/dist/unstable/cluster/Entity.js.map +1 -1
- package/dist/unstable/cluster/Envelope.d.ts.map +1 -1
- package/dist/unstable/cluster/Envelope.js +2 -1
- package/dist/unstable/cluster/Envelope.js.map +1 -1
- package/dist/unstable/cluster/Reply.js +1 -1
- package/dist/unstable/cluster/Reply.js.map +1 -1
- package/dist/unstable/cluster/Runner.d.ts +1 -1
- package/dist/unstable/cluster/Runner.js +1 -1
- package/dist/unstable/cluster/Runner.js.map +1 -1
- package/dist/unstable/cluster/RunnerAddress.d.ts +1 -1
- package/dist/unstable/cluster/RunnerAddress.js +1 -1
- package/dist/unstable/cluster/RunnerAddress.js.map +1 -1
- package/dist/unstable/cluster/ShardId.js +1 -1
- package/dist/unstable/cluster/ShardId.js.map +1 -1
- package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
- package/dist/unstable/cluster/Sharding.js +125 -24
- package/dist/unstable/cluster/Sharding.js.map +1 -1
- package/dist/unstable/cluster/ShardingConfig.d.ts +10 -2
- package/dist/unstable/cluster/ShardingConfig.d.ts.map +1 -1
- package/dist/unstable/cluster/ShardingConfig.js.map +1 -1
- package/dist/unstable/cluster/SingleRunner.d.ts +4 -2
- package/dist/unstable/cluster/SingleRunner.d.ts.map +1 -1
- package/dist/unstable/cluster/SingleRunner.js +2 -1
- package/dist/unstable/cluster/SingleRunner.js.map +1 -1
- package/dist/unstable/cluster/SqlMessageStorage.d.ts +7 -4
- package/dist/unstable/cluster/SqlMessageStorage.d.ts.map +1 -1
- package/dist/unstable/cluster/SqlMessageStorage.js +55 -24
- package/dist/unstable/cluster/SqlMessageStorage.js.map +1 -1
- package/dist/unstable/cluster/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/unstable/cluster/SqlRunnerStorage.js +109 -62
- package/dist/unstable/cluster/SqlRunnerStorage.js.map +1 -1
- package/dist/unstable/cluster/internal/entityManager.js +19 -7
- package/dist/unstable/cluster/internal/entityManager.js.map +1 -1
- package/dist/unstable/cluster/internal/shardLock.d.ts +2 -0
- package/dist/unstable/cluster/internal/shardLock.d.ts.map +1 -0
- package/dist/unstable/cluster/internal/shardLock.js +4 -0
- package/dist/unstable/cluster/internal/shardLock.js.map +1 -0
- package/dist/unstable/devtools/DevToolsSchema.d.ts +20 -20
- package/dist/unstable/devtools/DevToolsSchema.d.ts.map +1 -1
- package/dist/unstable/devtools/DevToolsSchema.js +8 -5
- package/dist/unstable/devtools/DevToolsSchema.js.map +1 -1
- package/dist/unstable/eventlog/EventJournal.d.ts +1 -1
- package/dist/unstable/eventlog/EventJournal.js +1 -1
- package/dist/unstable/eventlog/EventJournal.js.map +1 -1
- package/dist/unstable/eventlog/EventLog.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLog.js +15 -11
- package/dist/unstable/eventlog/EventLog.js.map +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.d.ts +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.js +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.js.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.d.ts +4 -4
- package/dist/unstable/eventlog/EventLogMessage.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.js +8 -3
- package/dist/unstable/eventlog/EventLogMessage.js.map +1 -1
- package/dist/unstable/eventlog/EventLogRemote.d.ts +1 -1
- package/dist/unstable/eventlog/SqlEventJournal.js +2 -2
- package/dist/unstable/eventlog/SqlEventJournal.js.map +1 -1
- package/dist/unstable/eventlog/SqlEventLogServerEncrypted.js +1 -1
- package/dist/unstable/eventlog/SqlEventLogServerEncrypted.js.map +1 -1
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js +3 -3
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js.map +1 -1
- package/dist/unstable/http/Cookies.d.ts.map +1 -1
- package/dist/unstable/http/Cookies.js +24 -22
- package/dist/unstable/http/Cookies.js.map +1 -1
- package/dist/unstable/http/Headers.js +8 -8
- package/dist/unstable/http/Headers.js.map +1 -1
- package/dist/unstable/http/HttpClientRequest.d.ts +44 -0
- package/dist/unstable/http/HttpClientRequest.d.ts.map +1 -1
- package/dist/unstable/http/HttpClientRequest.js +14 -0
- package/dist/unstable/http/HttpClientRequest.js.map +1 -1
- package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerRequest.js +5 -4
- package/dist/unstable/http/HttpServerRequest.js.map +1 -1
- package/dist/unstable/http/Multipart.d.ts.map +1 -1
- package/dist/unstable/http/Multipart.js +17 -15
- package/dist/unstable/http/Multipart.js.map +1 -1
- package/dist/unstable/http/Template.js +1 -1
- package/dist/unstable/http/Template.js.map +1 -1
- package/dist/unstable/http/UrlParams.d.ts.map +1 -1
- package/dist/unstable/http/UrlParams.js +17 -14
- package/dist/unstable/http/UrlParams.js.map +1 -1
- package/dist/unstable/httpapi/HttpApi.js +3 -3
- package/dist/unstable/httpapi/HttpApi.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiClient.js +5 -5
- package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiGroup.js +1 -1
- package/dist/unstable/httpapi/HttpApiGroup.js.map +1 -1
- package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
- package/dist/unstable/httpapi/OpenApi.js +37 -24
- package/dist/unstable/httpapi/OpenApi.js.map +1 -1
- package/dist/unstable/observability/OtlpExporter.d.ts +72 -1
- package/dist/unstable/observability/OtlpExporter.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpExporter.js +69 -4
- package/dist/unstable/observability/OtlpExporter.js.map +1 -1
- package/dist/unstable/observability/OtlpLogger.d.ts +4 -3
- package/dist/unstable/observability/OtlpLogger.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpLogger.js +2 -2
- package/dist/unstable/observability/OtlpLogger.js.map +1 -1
- package/dist/unstable/observability/OtlpMetrics.d.ts +7 -3
- package/dist/unstable/observability/OtlpMetrics.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpMetrics.js +5 -2
- package/dist/unstable/observability/OtlpMetrics.js.map +1 -1
- package/dist/unstable/observability/OtlpTracer.d.ts +4 -3
- package/dist/unstable/observability/OtlpTracer.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpTracer.js +2 -2
- package/dist/unstable/observability/OtlpTracer.js.map +1 -1
- package/dist/unstable/persistence/Persistable.d.ts.map +1 -1
- package/dist/unstable/persistence/Persistable.js +2 -1
- package/dist/unstable/persistence/Persistable.js.map +1 -1
- package/dist/unstable/persistence/RateLimiter.d.ts +2 -2
- package/dist/unstable/persistence/RateLimiter.js +2 -2
- package/dist/unstable/persistence/RateLimiter.js.map +1 -1
- package/dist/unstable/persistence/Redis.d.ts.map +1 -1
- package/dist/unstable/persistence/Redis.js +2 -2
- package/dist/unstable/persistence/Redis.js.map +1 -1
- package/dist/unstable/process/ChildProcessSpawner.js +3 -1
- package/dist/unstable/process/ChildProcessSpawner.js.map +1 -1
- package/dist/unstable/reactivity/AsyncResult.d.ts.map +1 -1
- package/dist/unstable/reactivity/AsyncResult.js +4 -3
- package/dist/unstable/reactivity/AsyncResult.js.map +1 -1
- package/dist/unstable/reactivity/Atom.d.ts +83 -0
- package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
- package/dist/unstable/reactivity/Atom.js +31 -0
- package/dist/unstable/reactivity/Atom.js.map +1 -1
- package/dist/unstable/reactivity/AtomRegistry.js +1 -1
- package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
- package/dist/unstable/rpc/RpcClient.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcClient.js +2 -1
- package/dist/unstable/rpc/RpcClient.js.map +1 -1
- package/dist/unstable/schema/VariantSchema.d.ts +1 -2
- package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
- package/dist/unstable/schema/VariantSchema.js +13 -10
- package/dist/unstable/schema/VariantSchema.js.map +1 -1
- package/dist/unstable/socket/Socket.d.ts +1 -1
- package/dist/unstable/socket/Socket.js +1 -1
- package/dist/unstable/socket/Socket.js.map +1 -1
- package/dist/unstable/sql/SqlError.d.ts +2 -2
- package/dist/unstable/sql/SqlError.js +2 -2
- package/dist/unstable/sql/SqlError.js.map +1 -1
- package/dist/unstable/sql/Statement.d.ts.map +1 -1
- package/dist/unstable/sql/Statement.js +7 -6
- package/dist/unstable/sql/Statement.js.map +1 -1
- package/package.json +1 -1
- package/src/Array.ts +86 -25
- package/src/Channel.ts +32 -14
- package/src/Config.ts +6 -5
- package/src/ConfigProvider.ts +7 -7
- package/src/Data.ts +3 -2
- package/src/Effect.ts +70 -116
- package/src/FiberHandle.ts +3 -2
- package/src/Iterable.ts +2 -1
- package/src/JsonPatch.ts +4 -3
- package/src/JsonSchema.ts +9 -11
- package/src/Logger.ts +3 -2
- package/src/ManagedRuntime.ts +13 -0
- package/src/Metric.ts +4 -3
- package/src/Optic.ts +5 -4
- package/src/Option.ts +2 -1
- package/src/PartitionedSemaphore.ts +1 -4
- package/src/Record.ts +119 -22
- package/src/References.ts +0 -46
- package/src/Request.ts +5 -7
- package/src/Result.ts +2 -1
- package/src/Schema.ts +2537 -986
- package/src/SchemaAST.ts +228 -149
- package/src/SchemaError.ts +1 -1
- package/src/SchemaGetter.ts +36 -29
- package/src/SchemaIssue.ts +1 -1
- package/src/SchemaParser.ts +1 -25
- package/src/SchemaRepresentation.ts +697 -3398
- package/src/SchemaTransformation.ts +3 -3
- package/src/Semaphore.ts +5 -3
- package/src/Stream.ts +63 -19
- package/src/Struct.ts +5 -4
- package/src/Types.ts +1 -3
- package/src/index.ts +0 -5
- package/src/internal/core.ts +3 -2
- package/src/internal/effect.ts +67 -31
- package/src/internal/matcher.ts +1 -1
- package/src/internal/record.ts +11 -7
- package/src/internal/references.ts +0 -5
- package/src/internal/schema/annotations.ts +44 -0
- package/src/internal/schema/fromJsonSchemaDocument.ts +957 -0
- package/src/internal/schema/fromRepresentation.ts +345 -0
- package/src/internal/schema/schema.ts +45 -46
- package/src/internal/schema/{arbitrary.ts → toArbitrary.ts} +8 -10
- package/src/internal/schema/toCodeDocument.ts +572 -0
- package/src/internal/schema/{equivalence.ts → toEquivalence.ts} +12 -7
- package/src/internal/schema/toJsonSchemaDocument.ts +475 -0
- package/src/internal/schema/toRepresentation.ts +401 -0
- package/src/internal/stackTraceLimit.ts +3 -7
- package/src/testing/TestClock.ts +1 -1
- package/src/unstable/ai/AiError.ts +5 -4
- package/src/unstable/ai/AnthropicStructuredOutput.ts +102 -333
- package/src/unstable/ai/EmbeddingModel.ts +1 -1
- package/src/unstable/ai/LanguageModel.ts +30 -28
- package/src/unstable/ai/McpSchema.ts +15 -15
- package/src/unstable/ai/McpServer.ts +172 -56
- package/src/unstable/ai/OpenAiStructuredOutput.ts +230 -395
- package/src/unstable/ai/Response.ts +24 -24
- package/src/unstable/ai/Tool.ts +22 -4
- package/src/unstable/ai/Toolkit.ts +19 -7
- package/src/unstable/ai/internal/codec-transformer.ts +13 -7
- package/src/unstable/ai/internal/structured-output.ts +458 -0
- package/src/unstable/cli/CliError.ts +51 -5
- package/src/unstable/cli/Command.ts +4 -4
- package/src/unstable/cli/Param.ts +3 -3
- package/src/unstable/cli/Primitive.ts +1 -1
- package/src/unstable/cli/internal/command.ts +13 -5
- package/src/unstable/cli/internal/config.ts +8 -10
- package/src/unstable/cluster/ClusterWorkflowEngine.ts +3 -3
- package/src/unstable/cluster/Entity.ts +1 -1
- package/src/unstable/cluster/Envelope.ts +2 -1
- package/src/unstable/cluster/Reply.ts +1 -1
- package/src/unstable/cluster/Runner.ts +1 -1
- package/src/unstable/cluster/RunnerAddress.ts +1 -1
- package/src/unstable/cluster/ShardId.ts +1 -1
- package/src/unstable/cluster/Sharding.ts +161 -34
- package/src/unstable/cluster/ShardingConfig.ts +5 -1
- package/src/unstable/cluster/SingleRunner.ts +4 -2
- package/src/unstable/cluster/SqlMessageStorage.ts +83 -35
- package/src/unstable/cluster/SqlRunnerStorage.ts +186 -116
- package/src/unstable/cluster/internal/entityManager.ts +31 -10
- package/src/unstable/cluster/internal/shardLock.ts +9 -0
- package/src/unstable/devtools/DevToolsSchema.ts +10 -5
- package/src/unstable/eventlog/EventJournal.ts +1 -1
- package/src/unstable/eventlog/EventLog.ts +21 -11
- package/src/unstable/eventlog/EventLogEncryption.ts +1 -1
- package/src/unstable/eventlog/EventLogMessage.ts +10 -3
- package/src/unstable/eventlog/SqlEventJournal.ts +2 -2
- package/src/unstable/eventlog/SqlEventLogServerEncrypted.ts +1 -1
- package/src/unstable/eventlog/SqlEventLogServerUnencrypted.ts +6 -3
- package/src/unstable/http/Cookies.ts +29 -24
- package/src/unstable/http/Headers.ts +8 -8
- package/src/unstable/http/HttpClientRequest.ts +57 -0
- package/src/unstable/http/HttpServerRequest.ts +5 -4
- package/src/unstable/http/Multipart.ts +16 -13
- package/src/unstable/http/Template.ts +1 -1
- package/src/unstable/http/UrlParams.ts +17 -14
- package/src/unstable/httpapi/HttpApi.ts +3 -3
- package/src/unstable/httpapi/HttpApiClient.ts +5 -5
- package/src/unstable/httpapi/HttpApiGroup.ts +1 -1
- package/src/unstable/httpapi/OpenApi.ts +52 -28
- package/src/unstable/observability/OtlpExporter.ts +109 -5
- package/src/unstable/observability/OtlpLogger.ts +5 -5
- package/src/unstable/observability/OtlpMetrics.ts +8 -4
- package/src/unstable/observability/OtlpTracer.ts +8 -4
- package/src/unstable/persistence/Persistable.ts +3 -2
- package/src/unstable/persistence/RateLimiter.ts +2 -2
- package/src/unstable/persistence/Redis.ts +2 -2
- package/src/unstable/process/ChildProcessSpawner.ts +1 -1
- package/src/unstable/reactivity/AsyncResult.ts +4 -3
- package/src/unstable/reactivity/Atom.ts +92 -0
- package/src/unstable/reactivity/AtomRegistry.ts +1 -1
- package/src/unstable/rpc/RpcClient.ts +2 -1
- package/src/unstable/schema/VariantSchema.ts +14 -24
- package/src/unstable/socket/Socket.ts +1 -1
- package/src/unstable/sql/SqlError.ts +2 -2
- package/src/unstable/sql/Statement.ts +7 -6
- package/dist/SchemaUtils.d.ts +0 -28
- package/dist/SchemaUtils.d.ts.map +0 -1
- package/dist/SchemaUtils.js +0 -45
- package/dist/SchemaUtils.js.map +0 -1
- package/dist/internal/schema/arbitrary.d.ts.map +0 -1
- package/dist/internal/schema/arbitrary.js.map +0 -1
- package/dist/internal/schema/equivalence.d.ts +0 -2
- package/dist/internal/schema/equivalence.d.ts.map +0 -1
- package/dist/internal/schema/equivalence.js.map +0 -1
- package/dist/internal/schema/representation.d.ts +0 -2
- package/dist/internal/schema/representation.d.ts.map +0 -1
- package/dist/internal/schema/representation.js +0 -865
- package/dist/internal/schema/representation.js.map +0 -1
- package/src/SchemaUtils.ts +0 -51
- 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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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
|
-
|
|
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 `
|
|
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 =
|
|
74
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
},
|
|
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
|
-
`.
|
|
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
|
-
},
|
|
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
|
-
`.
|
|
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
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
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:
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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
|
|