effect 4.0.2 → 4.0.4
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/AGENTS.md +24 -0
- package/CLAUDE.md +24 -0
- package/ai-docs/package.json +2 -2
- package/ai-docs/src/52_graphql/10_basics.ts +111 -0
- package/ai-docs/src/52_graphql/20_testing.ts +45 -0
- package/ai-docs/src/52_graphql/30_batching.ts +116 -0
- package/ai-docs/src/52_graphql/40_aliased-batching.ts +122 -0
- package/ai-docs/src/52_graphql/50_errors-and-retries.ts +74 -0
- package/ai-docs/src/52_graphql/index.md +6 -0
- package/dist/Context.d.ts.map +1 -1
- package/dist/Context.js +12 -3
- package/dist/Context.js.map +1 -1
- package/dist/Crypto.d.ts +33 -5
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +8 -2
- package/dist/Crypto.js.map +1 -1
- package/dist/DateTime.d.ts +9 -6
- package/dist/DateTime.d.ts.map +1 -1
- package/dist/DateTime.js +9 -6
- package/dist/DateTime.js.map +1 -1
- package/dist/Duration.d.ts +6 -6
- package/dist/Duration.d.ts.map +1 -1
- package/dist/Duration.js +27 -8
- package/dist/Duration.js.map +1 -1
- package/dist/FileSystem.d.ts +44 -2
- package/dist/FileSystem.d.ts.map +1 -1
- package/dist/FileSystem.js.map +1 -1
- package/dist/RequestResolver.d.ts.map +1 -1
- package/dist/RequestResolver.js +4 -10
- package/dist/RequestResolver.js.map +1 -1
- package/dist/Scheduler.d.ts +9 -0
- package/dist/Scheduler.d.ts.map +1 -1
- package/dist/Scheduler.js +9 -0
- package/dist/Scheduler.js.map +1 -1
- package/dist/Schema.d.ts +481 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +362 -4
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaGetter.d.ts +4 -0
- package/dist/SchemaGetter.d.ts.map +1 -1
- package/dist/SchemaGetter.js +52 -33
- package/dist/SchemaGetter.js.map +1 -1
- package/dist/Sink.d.ts.map +1 -1
- package/dist/Sink.js +38 -17
- package/dist/Sink.js.map +1 -1
- package/dist/Stdio.d.ts +7 -1
- package/dist/Stdio.d.ts.map +1 -1
- package/dist/Stdio.js +1 -0
- package/dist/Stdio.js.map +1 -1
- package/dist/Stream.d.ts +22 -11
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +21 -6
- package/dist/Stream.js.map +1 -1
- package/dist/Utils.js +8 -3
- package/dist/Utils.js.map +1 -1
- package/dist/ai/AnthropicStructuredOutput.js +0 -2
- package/dist/ai/AnthropicStructuredOutput.js.map +1 -1
- package/dist/ai/Chat.d.ts +2 -2
- package/dist/ai/Chat.d.ts.map +1 -1
- package/dist/ai/LanguageModel.d.ts +38 -7
- package/dist/ai/LanguageModel.d.ts.map +1 -1
- package/dist/ai/LanguageModel.js +25 -7
- package/dist/ai/LanguageModel.js.map +1 -1
- package/dist/ai/McpServer.d.ts +61 -0
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +196 -44
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Prompt.d.ts.map +1 -1
- package/dist/ai/Prompt.js +28 -5
- package/dist/ai/Prompt.js.map +1 -1
- package/dist/ai/Response.d.ts +4 -3
- package/dist/ai/Response.d.ts.map +1 -1
- package/dist/ai/Response.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js +5 -0
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
- package/dist/ai/internal/mcpProtocol.js.map +1 -1
- package/dist/ai/internal/mcpRuntime.js +1 -0
- package/dist/ai/internal/mcpRuntime.js.map +1 -1
- package/dist/cli/CliOutput.d.ts +27 -0
- package/dist/cli/CliOutput.d.ts.map +1 -1
- package/dist/cli/CliOutput.js +33 -10
- package/dist/cli/CliOutput.js.map +1 -1
- package/dist/cli/Command.d.ts.map +1 -1
- package/dist/cli/Command.js +6 -3
- package/dist/cli/Command.js.map +1 -1
- package/dist/cli/Completions.d.ts +3 -3
- package/dist/cli/Completions.d.ts.map +1 -1
- package/dist/cli/Completions.js +8 -5
- package/dist/cli/Completions.js.map +1 -1
- package/dist/cli/GlobalFlag.d.ts +5 -4
- package/dist/cli/GlobalFlag.d.ts.map +1 -1
- package/dist/cli/GlobalFlag.js +3 -3
- package/dist/cli/GlobalFlag.js.map +1 -1
- package/dist/cli/Prompt.d.ts +17 -1
- package/dist/cli/Prompt.d.ts.map +1 -1
- package/dist/cli/Prompt.js +119 -114
- package/dist/cli/Prompt.js.map +1 -1
- package/dist/cli/internal/ansi.d.ts +0 -1
- package/dist/cli/internal/ansi.d.ts.map +1 -1
- package/dist/cli/internal/ansi.js +20 -3
- package/dist/cli/internal/ansi.js.map +1 -1
- package/dist/cli/internal/completions/powershell.d.ts +2 -0
- package/dist/cli/internal/completions/powershell.d.ts.map +1 -0
- package/dist/cli/internal/completions/powershell.js +273 -0
- package/dist/cli/internal/completions/powershell.js.map +1 -0
- package/dist/cli/internal/completions/zsh.js +3 -2
- package/dist/cli/internal/completions/zsh.js.map +1 -1
- package/dist/cli/internal/wizard.d.ts +3 -3
- package/dist/cli/internal/wizard.d.ts.map +1 -1
- package/dist/cli/internal/wizard.js +21 -18
- package/dist/cli/internal/wizard.js.map +1 -1
- package/dist/cluster/ClusterSchema.d.ts +28 -0
- package/dist/cluster/ClusterSchema.d.ts.map +1 -1
- package/dist/cluster/ClusterSchema.js +30 -0
- package/dist/cluster/ClusterSchema.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +56 -26
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/MessageStorage.d.ts +18 -3
- package/dist/cluster/MessageStorage.d.ts.map +1 -1
- package/dist/cluster/MessageStorage.js +31 -11
- package/dist/cluster/MessageStorage.js.map +1 -1
- package/dist/cluster/Runners.d.ts.map +1 -1
- package/dist/cluster/Runners.js +8 -2
- package/dist/cluster/Runners.js.map +1 -1
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +187 -66
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/SqlMessageStorage.d.ts +59 -19
- package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
- package/dist/cluster/SqlMessageStorage.js +84 -55
- package/dist/cluster/SqlMessageStorage.js.map +1 -1
- package/dist/cluster/SqlRunnerStorage.d.ts +68 -19
- package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/cluster/SqlRunnerStorage.js +191 -113
- package/dist/cluster/SqlRunnerStorage.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +104 -37
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/encoding/Sse.d.ts +6 -0
- package/dist/encoding/Sse.d.ts.map +1 -1
- package/dist/encoding/Sse.js +62 -70
- package/dist/encoding/Sse.js.map +1 -1
- package/dist/graphql/GraphQL.d.ts +349 -0
- package/dist/graphql/GraphQL.d.ts.map +1 -0
- package/dist/graphql/GraphQL.js +207 -0
- package/dist/graphql/GraphQL.js.map +1 -0
- package/dist/graphql/GraphQLClient.d.ts +562 -0
- package/dist/graphql/GraphQLClient.d.ts.map +1 -0
- package/dist/graphql/GraphQLClient.js +498 -0
- package/dist/graphql/GraphQLClient.js.map +1 -0
- package/dist/graphql/GraphQLClientError.d.ts +445 -0
- package/dist/graphql/GraphQLClientError.d.ts.map +1 -0
- package/dist/graphql/GraphQLClientError.js +479 -0
- package/dist/graphql/GraphQLClientError.js.map +1 -0
- package/dist/graphql/GraphQLGroup.d.ts +118 -0
- package/dist/graphql/GraphQLGroup.d.ts.map +1 -0
- package/dist/graphql/GraphQLGroup.js +109 -0
- package/dist/graphql/GraphQLGroup.js.map +1 -0
- package/dist/graphql/GraphQLMiddleware.d.ts +249 -0
- package/dist/graphql/GraphQLMiddleware.d.ts.map +1 -0
- package/dist/graphql/GraphQLMiddleware.js +130 -0
- package/dist/graphql/GraphQLMiddleware.js.map +1 -0
- package/dist/graphql/GraphQLProtocol.d.ts +731 -0
- package/dist/graphql/GraphQLProtocol.d.ts.map +1 -0
- package/dist/graphql/GraphQLProtocol.js +719 -0
- package/dist/graphql/GraphQLProtocol.js.map +1 -0
- package/dist/graphql/GraphQLResolver.d.ts +453 -0
- package/dist/graphql/GraphQLResolver.d.ts.map +1 -0
- package/dist/graphql/GraphQLResolver.js +552 -0
- package/dist/graphql/GraphQLResolver.js.map +1 -0
- package/dist/graphql/index.d.ts +40 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js +41 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/http/FindMyWay/internal/router.js +3 -6
- package/dist/http/FindMyWay/internal/router.js.map +1 -1
- package/dist/http/HttpClient.d.ts +21 -0
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +63 -12
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpEffect.d.ts.map +1 -1
- package/dist/http/HttpEffect.js +14 -7
- package/dist/http/HttpEffect.js.map +1 -1
- package/dist/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/http/HttpMiddleware.js +31 -32
- package/dist/http/HttpMiddleware.js.map +1 -1
- package/dist/http/HttpRouter.d.ts +35 -0
- package/dist/http/HttpRouter.d.ts.map +1 -1
- package/dist/http/HttpRouter.js +35 -0
- package/dist/http/HttpRouter.js.map +1 -1
- package/dist/http/HttpServerResponse.d.ts +8 -6
- package/dist/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/http/HttpServerResponse.js +27 -16
- package/dist/http/HttpServerResponse.js.map +1 -1
- package/dist/http/HttpTraceContext.d.ts.map +1 -1
- package/dist/http/HttpTraceContext.js +4 -2
- package/dist/http/HttpTraceContext.js.map +1 -1
- package/dist/http/Multipart.d.ts.map +1 -1
- package/dist/http/Multipart.js +15 -1
- package/dist/http/Multipart.js.map +1 -1
- package/dist/http-api/HttpApiScalar.d.ts +5 -0
- package/dist/http-api/HttpApiScalar.d.ts.map +1 -1
- package/dist/http-api/HttpApiScalar.js.map +1 -1
- package/dist/internal/dateTime.js +40 -35
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +19 -9
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/graphql.d.ts +2 -0
- package/dist/internal/graphql.d.ts.map +1 -0
- package/dist/internal/graphql.js +195 -0
- package/dist/internal/graphql.js.map +1 -0
- package/dist/internal/graphqlHeaders.d.ts +4 -0
- package/dist/internal/graphqlHeaders.d.ts.map +1 -0
- package/dist/internal/graphqlHeaders.js +11 -0
- package/dist/internal/graphqlHeaders.js.map +1 -0
- package/dist/internal/request.js +20 -1
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/schema/toCodeDocument.js +4 -1
- package/dist/internal/schema/toCodeDocument.js.map +1 -1
- package/dist/internal/schema/toJsonSchemaDocument.js +29 -5
- package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/net/AddressResolver.d.ts +145 -0
- package/dist/net/AddressResolver.d.ts.map +1 -0
- package/dist/net/AddressResolver.js +114 -0
- package/dist/net/AddressResolver.js.map +1 -0
- package/dist/net/Dns.d.ts +596 -0
- package/dist/net/Dns.d.ts.map +1 -0
- package/dist/net/Dns.js +549 -0
- package/dist/net/Dns.js.map +1 -0
- package/dist/net/Host.d.ts +369 -0
- package/dist/net/Host.d.ts.map +1 -0
- package/dist/net/Host.js +397 -0
- package/dist/net/Host.js.map +1 -0
- package/dist/net/IpInterface.d.ts +76 -3
- package/dist/net/IpInterface.d.ts.map +1 -1
- package/dist/net/IpInterface.js +53 -4
- package/dist/net/IpInterface.js.map +1 -1
- package/dist/net/IpNetwork.d.ts +82 -8
- package/dist/net/IpNetwork.d.ts.map +1 -1
- package/dist/net/IpNetwork.js +60 -4
- package/dist/net/IpNetwork.js.map +1 -1
- package/dist/net/NetAddress.d.ts +396 -35
- package/dist/net/NetAddress.d.ts.map +1 -1
- package/dist/net/NetAddress.js +358 -34
- package/dist/net/NetAddress.js.map +1 -1
- package/dist/net/index.d.ts +15 -0
- package/dist/net/index.d.ts.map +1 -1
- package/dist/net/index.js +15 -0
- package/dist/net/index.js.map +1 -1
- package/dist/observability/OtlpMetrics.d.ts.map +1 -1
- package/dist/observability/OtlpMetrics.js +15 -21
- package/dist/observability/OtlpMetrics.js.map +1 -1
- package/dist/observability/PrometheusMetrics.js +1 -0
- package/dist/observability/PrometheusMetrics.js.map +1 -1
- package/dist/persistence/PersistedQueue.d.ts +32 -3
- package/dist/persistence/PersistedQueue.d.ts.map +1 -1
- package/dist/persistence/PersistedQueue.js +75 -16
- package/dist/persistence/PersistedQueue.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts +22 -6
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +12 -5
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcServer.d.ts +6 -0
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +78 -29
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/socket/DatagramSocket.d.ts +456 -0
- package/dist/socket/DatagramSocket.d.ts.map +1 -0
- package/dist/socket/DatagramSocket.js +535 -0
- package/dist/socket/DatagramSocket.js.map +1 -0
- package/dist/socket/Socket.d.ts +20 -1
- package/dist/socket/Socket.d.ts.map +1 -1
- package/dist/socket/Socket.js +9 -1
- package/dist/socket/Socket.js.map +1 -1
- package/dist/socket/index.d.ts +5 -0
- package/dist/socket/index.d.ts.map +1 -1
- package/dist/socket/index.js +5 -0
- package/dist/socket/index.js.map +1 -1
- package/dist/sql/Migrator.d.ts.map +1 -1
- package/dist/sql/Migrator.js +7 -2
- package/dist/sql/Migrator.js.map +1 -1
- package/dist/sql/SqlClient.d.ts +7 -1
- package/dist/sql/SqlClient.d.ts.map +1 -1
- package/dist/sql/SqlClient.js +31 -6
- package/dist/sql/SqlClient.js.map +1 -1
- package/dist/testing/TestCrypto.d.ts +73 -0
- package/dist/testing/TestCrypto.d.ts.map +1 -0
- package/dist/testing/TestCrypto.js +87 -0
- package/dist/testing/TestCrypto.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/workflow/DurableDeferred.d.ts +54 -0
- package/dist/workflow/DurableDeferred.d.ts.map +1 -1
- package/dist/workflow/DurableDeferred.js +108 -50
- package/dist/workflow/DurableDeferred.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts +24 -2
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +13 -3
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +6 -3
- package/src/Context.ts +12 -3
- package/src/Crypto.ts +43 -9
- package/src/DateTime.ts +9 -6
- package/src/Duration.ts +36 -16
- package/src/FileSystem.ts +48 -2
- package/src/RequestResolver.ts +4 -10
- package/src/Scheduler.ts +9 -0
- package/src/Schema.ts +677 -5
- package/src/SchemaGetter.ts +47 -35
- package/src/Sink.ts +45 -18
- package/src/Stdio.ts +9 -2
- package/src/Stream.ts +44 -15
- package/src/Utils.ts +8 -5
- package/src/ai/AnthropicStructuredOutput.ts +2 -2
- package/src/ai/Chat.ts +2 -2
- package/src/ai/LanguageModel.ts +96 -24
- package/src/ai/McpServer.ts +288 -94
- package/src/ai/Prompt.ts +24 -10
- package/src/ai/Response.ts +6 -3
- package/src/ai/internal/mcpProtocol/v2026_07_28.ts +5 -0
- package/src/ai/internal/mcpProtocol.ts +3 -0
- package/src/ai/internal/mcpRuntime.ts +2 -0
- package/src/cli/CliOutput.ts +33 -16
- package/src/cli/Command.ts +4 -3
- package/src/cli/Completions.ts +9 -6
- package/src/cli/GlobalFlag.ts +19 -11
- package/src/cli/Prompt.ts +159 -149
- package/src/cli/internal/ansi.ts +26 -3
- package/src/cli/internal/completions/powershell.ts +322 -0
- package/src/cli/internal/completions/zsh.ts +4 -2
- package/src/cli/internal/wizard.ts +34 -26
- package/src/cluster/ClusterSchema.ts +32 -0
- package/src/cluster/ClusterWorkflowEngine.ts +64 -36
- package/src/cluster/MessageStorage.ts +45 -14
- package/src/cluster/Runners.ts +8 -2
- package/src/cluster/Sharding.ts +219 -58
- package/src/cluster/SqlMessageStorage.ts +118 -84
- package/src/cluster/SqlRunnerStorage.ts +224 -128
- package/src/cluster/internal/entityManager.ts +151 -55
- package/src/encoding/Sse.ts +69 -79
- package/src/graphql/GraphQL.ts +494 -0
- package/src/graphql/GraphQLClient.ts +912 -0
- package/src/graphql/GraphQLClientError.ts +542 -0
- package/src/graphql/GraphQLGroup.ts +167 -0
- package/src/graphql/GraphQLMiddleware.ts +253 -0
- package/src/graphql/GraphQLProtocol.ts +1286 -0
- package/src/graphql/GraphQLResolver.ts +1010 -0
- package/src/graphql/index.ts +48 -0
- package/src/http/FindMyWay/internal/router.ts +4 -7
- package/src/http/HttpClient.ts +110 -12
- package/src/http/HttpEffect.ts +11 -5
- package/src/http/HttpMiddleware.ts +33 -34
- package/src/http/HttpRouter.ts +35 -0
- package/src/http/HttpServerResponse.ts +28 -16
- package/src/http/HttpTraceContext.ts +8 -2
- package/src/http/Multipart.ts +17 -1
- package/src/http-api/HttpApiScalar.ts +5 -0
- package/src/internal/dateTime.ts +13 -10
- package/src/internal/effect.ts +22 -15
- package/src/internal/graphql.ts +263 -0
- package/src/internal/graphqlHeaders.ts +11 -0
- package/src/internal/request.ts +31 -3
- package/src/internal/schema/toCodeDocument.ts +7 -1
- package/src/internal/schema/toJsonSchemaDocument.ts +34 -2
- package/src/internal/version.ts +1 -1
- package/src/net/AddressResolver.ts +222 -0
- package/src/net/Dns.ts +1035 -0
- package/src/net/Host.ts +544 -0
- package/src/net/IpInterface.ts +117 -7
- package/src/net/IpNetwork.ts +116 -17
- package/src/net/NetAddress.ts +620 -76
- package/src/net/index.ts +18 -0
- package/src/observability/OtlpMetrics.ts +12 -23
- package/src/observability/PrometheusMetrics.ts +1 -0
- package/src/persistence/PersistedQueue.ts +146 -53
- package/src/rpc/RpcClient.ts +41 -19
- package/src/rpc/RpcServer.ts +115 -40
- package/src/socket/DatagramSocket.ts +919 -0
- package/src/socket/Socket.ts +28 -2
- package/src/socket/index.ts +6 -0
- package/src/sql/Migrator.ts +21 -5
- package/src/sql/SqlClient.ts +39 -15
- package/src/testing/TestCrypto.ts +94 -0
- package/src/testing/index.ts +6 -0
- package/src/workflow/DurableDeferred.ts +160 -47
- package/src/workflow/WorkflowEngine.ts +50 -5
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* storage constructor, layers, migrations, optional table prefixes, and the row
|
|
9
9
|
* mapping needed by encoded message storage.
|
|
10
10
|
*
|
|
11
|
+
* `layer`, `layerWith`, `make`, and `makeEncoded` run the migrations before
|
|
12
|
+
* building the storage. To run migrations with a different connection, such as
|
|
13
|
+
* a schema owner in a deploy step, use `layerMigrations` there and
|
|
14
|
+
* `layerStorage` in the runtime.
|
|
15
|
+
*
|
|
11
16
|
* Request deduplication keys that exceed the 255-character `message_id`
|
|
12
17
|
* column are hashed with the `Crypto` service before they are written, so
|
|
13
18
|
* composed keys of any length are supported; shorter keys are stored as
|
|
@@ -24,7 +29,6 @@ import * as Hex from "../encoding/Hex.ts"
|
|
|
24
29
|
import * as Layer from "../Layer.ts"
|
|
25
30
|
import * as Option from "../Option.ts"
|
|
26
31
|
import type * as PlatformError from "../PlatformError.ts"
|
|
27
|
-
import * as Schedule from "../Schedule.ts"
|
|
28
32
|
import * as Migrator from "../sql/Migrator.ts"
|
|
29
33
|
import * as SqlClient from "../sql/SqlClient.ts"
|
|
30
34
|
import type { Row } from "../sql/SqlConnection.ts"
|
|
@@ -73,19 +77,18 @@ export const makeEncoded: (options?: {
|
|
|
73
77
|
MessageStorage.Encoded,
|
|
74
78
|
never,
|
|
75
79
|
SqlClient.SqlClient | Crypto.Crypto
|
|
76
|
-
> = Effect.
|
|
80
|
+
> = (options) => Effect.andThen(runMessageMigrations(options), makeEncodedStorage(options))
|
|
81
|
+
|
|
82
|
+
const makeEncodedStorage = Effect.fnUntraced(function*(
|
|
83
|
+
options: {
|
|
84
|
+
readonly prefix?: string | undefined
|
|
85
|
+
} | undefined
|
|
86
|
+
) {
|
|
77
87
|
const sql = (yield* SqlClient.SqlClient).withoutTransforms()
|
|
78
88
|
const crypto = yield* Crypto.Crypto
|
|
79
89
|
const prefix = options?.prefix ?? "cluster"
|
|
80
90
|
const table = (name: string) => `${prefix}_${name}`
|
|
81
91
|
|
|
82
|
-
yield* Effect.orDie(
|
|
83
|
-
Migrator.make({})({
|
|
84
|
-
loader: migrations(options),
|
|
85
|
-
table: table("migrations")
|
|
86
|
-
})
|
|
87
|
-
)
|
|
88
|
-
|
|
89
92
|
const messageKindAckChunk = sql.literal(String(messageKind.AckChunk))
|
|
90
93
|
const messageKindInterrupt = sql.literal(String(messageKind.Interrupt))
|
|
91
94
|
const replyKindWithExit = sql.literal(String(replyKind.WithExit))
|
|
@@ -810,69 +813,27 @@ export const make: (options?: {
|
|
|
810
813
|
> = (options) => Effect.flatMap(makeEncoded(options), MessageStorage.makeEncoded)
|
|
811
814
|
|
|
812
815
|
/**
|
|
813
|
-
*
|
|
814
|
-
* and the default snowflake generator.
|
|
815
|
-
*
|
|
816
|
-
* **When to use**
|
|
817
|
-
*
|
|
818
|
-
* Use when a cluster should persist mailbox messages and replies in SQL using
|
|
819
|
-
* the default `cluster` table prefix and the standard snowflake generator.
|
|
816
|
+
* Migration loader for the SQL message storage tables.
|
|
820
817
|
*
|
|
821
818
|
* **Details**
|
|
822
819
|
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
* `SqlClient`, `ShardingConfig`, and `Crypto.Crypto`, which is used to hash
|
|
826
|
-
* message deduplication keys that would overflow the fixed-width
|
|
827
|
-
* `message_id` column.
|
|
828
|
-
*
|
|
829
|
-
* **Gotchas**
|
|
830
|
-
*
|
|
831
|
-
* This layer always uses the `cluster` table prefix. Use `layerWith` before
|
|
832
|
-
* deployment if you need a different stable prefix, because changing prefixes
|
|
833
|
-
* later points the runtime at a different set of tables.
|
|
834
|
-
*
|
|
835
|
-
* @see {@link layerWith} for the same SQL storage layer with a custom table prefix
|
|
836
|
-
* @see {@link make} for the lower-level service constructor that uses an existing `Snowflake.Generator`
|
|
820
|
+
* History is recorded in `<prefix>_migrations`; the default
|
|
821
|
+
* prefix is `cluster`.
|
|
837
822
|
*
|
|
838
823
|
* @stability unstable
|
|
839
|
-
* @category
|
|
840
|
-
* @since 4.
|
|
841
|
-
*/
|
|
842
|
-
export const layer: Layer.Layer<
|
|
843
|
-
MessageStorage.MessageStorage,
|
|
844
|
-
never,
|
|
845
|
-
SqlClient.SqlClient | ShardingConfig | Crypto.Crypto
|
|
846
|
-
> = Layer.effect(MessageStorage.MessageStorage, make()).pipe(
|
|
847
|
-
Layer.provide(Snowflake.layerGenerator)
|
|
848
|
-
)
|
|
849
|
-
|
|
850
|
-
/**
|
|
851
|
-
* Layer that provides SQL-backed `MessageStorage` using a custom table prefix.
|
|
852
|
-
*
|
|
853
|
-
* @stability unstable
|
|
854
|
-
* @category layers
|
|
855
|
-
* @since 4.0.0
|
|
824
|
+
* @category migrations
|
|
825
|
+
* @since 4.1.0
|
|
856
826
|
*/
|
|
857
|
-
export const
|
|
858
|
-
readonly prefix?: string | undefined
|
|
859
|
-
}): Layer.Layer<MessageStorage.MessageStorage, never, SqlClient.SqlClient | ShardingConfig | Crypto.Crypto> =>
|
|
860
|
-
Layer.effect(MessageStorage.MessageStorage, make(options)).pipe(
|
|
861
|
-
Layer.provide(Snowflake.layerGenerator)
|
|
862
|
-
)
|
|
863
|
-
|
|
864
|
-
// -------------------------------------------------------------------------------------------------
|
|
865
|
-
// internal
|
|
866
|
-
// -------------------------------------------------------------------------------------------------
|
|
867
|
-
|
|
868
|
-
const migrations = (options?: {
|
|
827
|
+
export const migrations = (options?: {
|
|
869
828
|
readonly prefix?: string | undefined
|
|
870
|
-
}) => {
|
|
829
|
+
}): Migrator.Loader => {
|
|
871
830
|
const prefix = options?.prefix ?? "cluster"
|
|
872
831
|
const table = (name: string) => `${prefix}_${name}`
|
|
873
832
|
const messagesTable = table("messages")
|
|
874
833
|
const repliesTable = table("replies")
|
|
875
834
|
|
|
835
|
+
// The migrator serializes PostgreSQL DDL. Propagate errors: retrying in an
|
|
836
|
+
// aborted transaction cannot succeed.
|
|
876
837
|
return Migrator.fromRecord({
|
|
877
838
|
"0001_create_tables": Effect.gen(function*() {
|
|
878
839
|
const sql = (yield* SqlClient.SqlClient).withoutTransforms()
|
|
@@ -956,7 +917,7 @@ const migrations = (options?: {
|
|
|
956
917
|
deliver_at BIGINT,
|
|
957
918
|
UNIQUE (message_id)
|
|
958
919
|
)
|
|
959
|
-
|
|
920
|
+
`,
|
|
960
921
|
orElse: () =>
|
|
961
922
|
// sqlite
|
|
962
923
|
sql`
|
|
@@ -1016,18 +977,7 @@ const migrations = (options?: {
|
|
|
1016
977
|
CREATE INDEX IF NOT EXISTS ${sql(requestIdLookupIndex)}
|
|
1017
978
|
ON ${messagesTableSql} (request_id)
|
|
1018
979
|
`
|
|
1019
|
-
})
|
|
1020
|
-
sql.withTransaction,
|
|
1021
|
-
Effect.tapDefect((error) =>
|
|
1022
|
-
Effect.annotateLogs(Effect.logDebug("Failed to create indexes", error), {
|
|
1023
|
-
package: "@effect/cluster",
|
|
1024
|
-
module: "SqlMessageStorage"
|
|
1025
|
-
})
|
|
1026
|
-
),
|
|
1027
|
-
Effect.retry({
|
|
1028
|
-
schedule: Schedule.spaced(1000)
|
|
1029
|
-
})
|
|
1030
|
-
),
|
|
980
|
+
}),
|
|
1031
981
|
orElse: () =>
|
|
1032
982
|
// sqlite
|
|
1033
983
|
Effect.all([
|
|
@@ -1121,17 +1071,7 @@ const migrations = (options?: {
|
|
|
1121
1071
|
sql`
|
|
1122
1072
|
CREATE INDEX IF NOT EXISTS ${sql(replyLookupIndex)}
|
|
1123
1073
|
ON ${repliesTableSql} (request_id, kind, acked);
|
|
1124
|
-
|
|
1125
|
-
Effect.tapDefect((error) =>
|
|
1126
|
-
Effect.annotateLogs(Effect.logDebug("Failed to create indexes", error), {
|
|
1127
|
-
package: "@effect/cluster",
|
|
1128
|
-
module: "SqlMessageStorage"
|
|
1129
|
-
})
|
|
1130
|
-
),
|
|
1131
|
-
Effect.retry({
|
|
1132
|
-
schedule: Schedule.spaced(1000)
|
|
1133
|
-
})
|
|
1134
|
-
),
|
|
1074
|
+
`,
|
|
1135
1075
|
orElse: () =>
|
|
1136
1076
|
// sqlite
|
|
1137
1077
|
sql`
|
|
@@ -1180,6 +1120,100 @@ const migrations = (options?: {
|
|
|
1180
1120
|
})
|
|
1181
1121
|
}
|
|
1182
1122
|
|
|
1123
|
+
const runMessageMigrations = (options?: {
|
|
1124
|
+
readonly prefix?: string | undefined
|
|
1125
|
+
}): Effect.Effect<void, never, SqlClient.SqlClient> =>
|
|
1126
|
+
Migrator.make({})({
|
|
1127
|
+
loader: migrations(options),
|
|
1128
|
+
table: `${options?.prefix ?? "cluster"}_migrations`
|
|
1129
|
+
}).pipe(Effect.asVoid, Effect.orDie)
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Runs the SQL message storage migrations without providing storage.
|
|
1133
|
+
*
|
|
1134
|
+
* **Details**
|
|
1135
|
+
*
|
|
1136
|
+
* Use an owner connection in a deploy step, then use `layerStorage` with a
|
|
1137
|
+
* DML-only runtime connection. History is recorded in `<prefix>_migrations`.
|
|
1138
|
+
* Migration errors become defects.
|
|
1139
|
+
*
|
|
1140
|
+
* On PostgreSQL, use the role's `search_path` to select a schema. A
|
|
1141
|
+
* schema-qualified prefix such as `app.cluster` produces an invalid index name.
|
|
1142
|
+
*
|
|
1143
|
+
* @stability unstable
|
|
1144
|
+
* @category layers
|
|
1145
|
+
* @since 4.1.0
|
|
1146
|
+
*/
|
|
1147
|
+
export const layerMigrations = (options: {
|
|
1148
|
+
readonly prefix?: string | undefined
|
|
1149
|
+
}): Layer.Layer<never, never, SqlClient.SqlClient> => Layer.effectDiscard(runMessageMigrations(options))
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Provides SQL-backed `MessageStorage` without DDL or startup schema checks.
|
|
1153
|
+
*
|
|
1154
|
+
* **Details**
|
|
1155
|
+
*
|
|
1156
|
+
* Run `layerMigrations` separately before using this layer.
|
|
1157
|
+
* This layer supplies `Snowflake.layerGenerator` internally.
|
|
1158
|
+
*
|
|
1159
|
+
* @stability unstable
|
|
1160
|
+
* @category layers
|
|
1161
|
+
* @since 4.1.0
|
|
1162
|
+
*/
|
|
1163
|
+
export const layerStorage = (options: {
|
|
1164
|
+
readonly prefix?: string | undefined
|
|
1165
|
+
}): Layer.Layer<MessageStorage.MessageStorage, never, SqlClient.SqlClient | ShardingConfig | Crypto.Crypto> =>
|
|
1166
|
+
Layer.effect(
|
|
1167
|
+
MessageStorage.MessageStorage,
|
|
1168
|
+
Effect.flatMap(makeEncodedStorage(options), MessageStorage.makeEncoded)
|
|
1169
|
+
).pipe(
|
|
1170
|
+
Layer.provide(Snowflake.layerGenerator)
|
|
1171
|
+
)
|
|
1172
|
+
|
|
1173
|
+
/**
|
|
1174
|
+
* Provides SQL-backed `MessageStorage` with a custom table prefix,
|
|
1175
|
+
* running migrations first.
|
|
1176
|
+
*
|
|
1177
|
+
* **Details**
|
|
1178
|
+
*
|
|
1179
|
+
* Migration errors become defects. Use `layerMigrations` and `layerStorage`
|
|
1180
|
+
* to migrate separately.
|
|
1181
|
+
*
|
|
1182
|
+
* @stability unstable
|
|
1183
|
+
* @category layers
|
|
1184
|
+
* @since 4.0.0
|
|
1185
|
+
*/
|
|
1186
|
+
export const layerWith = (options: {
|
|
1187
|
+
readonly prefix?: string | undefined
|
|
1188
|
+
}): Layer.Layer<MessageStorage.MessageStorage, never, SqlClient.SqlClient | ShardingConfig | Crypto.Crypto> =>
|
|
1189
|
+
layerStorage(options).pipe(
|
|
1190
|
+
Layer.provide(layerMigrations(options))
|
|
1191
|
+
)
|
|
1192
|
+
|
|
1193
|
+
/**
|
|
1194
|
+
* Provides SQL-backed `MessageStorage` with the `cluster` table prefix,
|
|
1195
|
+
* running migrations first and supplying `Snowflake.layerGenerator`.
|
|
1196
|
+
*
|
|
1197
|
+
* **Details**
|
|
1198
|
+
*
|
|
1199
|
+
* The connection needs DDL permissions. PostgreSQL takes an exclusive lock
|
|
1200
|
+
* on the migration history table. Use `layerWith` for a custom prefix or
|
|
1201
|
+
* `layerMigrations` and `layerStorage` to migrate separately.
|
|
1202
|
+
*
|
|
1203
|
+
* @stability unstable
|
|
1204
|
+
* @category layers
|
|
1205
|
+
* @since 4.0.0
|
|
1206
|
+
*/
|
|
1207
|
+
export const layer: Layer.Layer<
|
|
1208
|
+
MessageStorage.MessageStorage,
|
|
1209
|
+
never,
|
|
1210
|
+
SqlClient.SqlClient | ShardingConfig | Crypto.Crypto
|
|
1211
|
+
> = layerWith({})
|
|
1212
|
+
|
|
1213
|
+
// -------------------------------------------------------------------------------------------------
|
|
1214
|
+
// internal
|
|
1215
|
+
// -------------------------------------------------------------------------------------------------
|
|
1216
|
+
|
|
1183
1217
|
const messageKind = {
|
|
1184
1218
|
"Request": 0,
|
|
1185
1219
|
"AckChunk": 1,
|
|
@@ -3,10 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The SQL-backed `RunnerStorage` records runners, health flags, machine ids,
|
|
5
5
|
* and shard locks so multiple processes can coordinate which runner owns each
|
|
6
|
-
* shard. This module
|
|
6
|
+
* shard. This module migrates the required runner and lock tables, supports an
|
|
7
7
|
* optional table prefix, uses advisory locks for PostgreSQL and MySQL when
|
|
8
8
|
* enabled, and provides constructors and layers for the storage service.
|
|
9
9
|
*
|
|
10
|
+
* `layer`, `layerWith`, and `make` run the migrations before building the
|
|
11
|
+
* storage. To run migrations with a different connection, such as a schema
|
|
12
|
+
* owner in a deploy step, use `layerMigrations` there and `layerStorage` in the
|
|
13
|
+
* runtime.
|
|
14
|
+
*
|
|
10
15
|
* @stability unstable
|
|
11
16
|
* @since 4.0.0
|
|
12
17
|
*/
|
|
@@ -17,6 +22,7 @@ import * as Effect from "../Effect.ts"
|
|
|
17
22
|
import * as Fiber from "../Fiber.ts"
|
|
18
23
|
import * as Layer from "../Layer.ts"
|
|
19
24
|
import * as Scope from "../Scope.ts"
|
|
25
|
+
import * as Migrator from "../sql/Migrator.ts"
|
|
20
26
|
import * as SqlClient from "../sql/SqlClient.ts"
|
|
21
27
|
import type { Connection } from "../sql/SqlConnection.ts"
|
|
22
28
|
import type { SqlError } from "../sql/SqlError.ts"
|
|
@@ -41,36 +47,7 @@ const postgresLockNamespace = (prefix: string): number => {
|
|
|
41
47
|
return hash | 0
|
|
42
48
|
}
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
* Creates a SQL-backed `RunnerStorage` implementation for registered runners and
|
|
46
|
-
* shard locks, using the configured table prefix and advisory locks where
|
|
47
|
-
* supported and enabled.
|
|
48
|
-
*
|
|
49
|
-
* **When to use**
|
|
50
|
-
*
|
|
51
|
-
* Use to create a SQL-backed `RunnerStorage` value directly when building
|
|
52
|
-
* custom service or layer composition around the storage implementation.
|
|
53
|
-
*
|
|
54
|
-
* **Details**
|
|
55
|
-
*
|
|
56
|
-
* When `prefix` is omitted, `make` uses the `cluster` prefix, creating
|
|
57
|
-
* `cluster_runners` and `cluster_locks`. PostgreSQL and MySQL use advisory
|
|
58
|
-
* locks unless `ShardingConfig.shardLockDisableAdvisory` is enabled; other
|
|
59
|
-
* dialects use rows in the locks table.
|
|
60
|
-
*
|
|
61
|
-
* **Gotchas**
|
|
62
|
-
*
|
|
63
|
-
* Changing `prefix` changes both generated table names, so runners using
|
|
64
|
-
* different prefixes do not share registrations or shard locks.
|
|
65
|
-
*
|
|
66
|
-
* @see {@link layer} for the default SQL-backed storage layer
|
|
67
|
-
* @see {@link layerWith} for a SQL-backed storage layer with a custom table prefix
|
|
68
|
-
*
|
|
69
|
-
* @stability unstable
|
|
70
|
-
* @category constructors
|
|
71
|
-
* @since 4.0.0
|
|
72
|
-
*/
|
|
73
|
-
export const make = Effect.fnUntraced(function*(options: {
|
|
50
|
+
const makeStorage = Effect.fnUntraced(function*(options: {
|
|
74
51
|
readonly prefix?: string | undefined
|
|
75
52
|
}) {
|
|
76
53
|
const config = yield* ShardingConfig.ShardingConfig
|
|
@@ -183,99 +160,9 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
183
160
|
const runnersTable = table("runners")
|
|
184
161
|
const runnersTableSql = sql(runnersTable)
|
|
185
162
|
|
|
186
|
-
yield* sql.onDialectOrElse({
|
|
187
|
-
mssql: () =>
|
|
188
|
-
sql`
|
|
189
|
-
IF OBJECT_ID(N'${runnersTableSql}', N'U') IS NULL
|
|
190
|
-
CREATE TABLE ${runnersTableSql} (
|
|
191
|
-
machine_id INT IDENTITY PRIMARY KEY,
|
|
192
|
-
address VARCHAR(255) NOT NULL,
|
|
193
|
-
runner TEXT NOT NULL,
|
|
194
|
-
healthy BIT NOT NULL DEFAULT 1,
|
|
195
|
-
last_heartbeat DATETIME NOT NULL DEFAULT GETDATE(),
|
|
196
|
-
UNIQUE(address)
|
|
197
|
-
)
|
|
198
|
-
`,
|
|
199
|
-
mysql: () =>
|
|
200
|
-
sql`
|
|
201
|
-
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
202
|
-
machine_id INT AUTO_INCREMENT PRIMARY KEY,
|
|
203
|
-
address VARCHAR(255) NOT NULL,
|
|
204
|
-
runner TEXT NOT NULL,
|
|
205
|
-
healthy BOOLEAN NOT NULL DEFAULT TRUE,
|
|
206
|
-
last_heartbeat DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
207
|
-
UNIQUE(address)
|
|
208
|
-
)
|
|
209
|
-
`,
|
|
210
|
-
pg: () =>
|
|
211
|
-
sql`
|
|
212
|
-
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
213
|
-
machine_id SERIAL PRIMARY KEY,
|
|
214
|
-
address VARCHAR(255) NOT NULL,
|
|
215
|
-
runner TEXT NOT NULL,
|
|
216
|
-
healthy BOOLEAN NOT NULL DEFAULT TRUE,
|
|
217
|
-
last_heartbeat TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
218
|
-
UNIQUE(address)
|
|
219
|
-
)
|
|
220
|
-
`,
|
|
221
|
-
orElse: () =>
|
|
222
|
-
// sqlite
|
|
223
|
-
sql`
|
|
224
|
-
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
225
|
-
machine_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
226
|
-
address TEXT NOT NULL,
|
|
227
|
-
runner TEXT NOT NULL,
|
|
228
|
-
healthy INTEGER NOT NULL DEFAULT 1,
|
|
229
|
-
last_heartbeat DATETIME NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
|
230
|
-
UNIQUE(address)
|
|
231
|
-
)
|
|
232
|
-
`
|
|
233
|
-
})
|
|
234
|
-
|
|
235
163
|
const locksTable = table("locks")
|
|
236
164
|
const locksTableSql = sql(locksTable)
|
|
237
165
|
|
|
238
|
-
yield* sql.onDialectOrElse({
|
|
239
|
-
mssql: () =>
|
|
240
|
-
sql`
|
|
241
|
-
IF OBJECT_ID(N'${locksTableSql}', N'U') IS NULL
|
|
242
|
-
CREATE TABLE ${locksTableSql} (
|
|
243
|
-
shard_id VARCHAR(50) PRIMARY KEY,
|
|
244
|
-
address VARCHAR(255) NOT NULL,
|
|
245
|
-
acquired_at DATETIME NOT NULL
|
|
246
|
-
)
|
|
247
|
-
`,
|
|
248
|
-
mysql: () =>
|
|
249
|
-
disableAdvisoryLocks ?
|
|
250
|
-
sql`
|
|
251
|
-
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
252
|
-
shard_id VARCHAR(50) PRIMARY KEY,
|
|
253
|
-
address VARCHAR(255) NOT NULL,
|
|
254
|
-
acquired_at DATETIME NOT NULL
|
|
255
|
-
)
|
|
256
|
-
` :
|
|
257
|
-
Effect.void,
|
|
258
|
-
pg: () =>
|
|
259
|
-
disableAdvisoryLocks ?
|
|
260
|
-
sql`
|
|
261
|
-
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
262
|
-
shard_id VARCHAR(50) PRIMARY KEY,
|
|
263
|
-
address VARCHAR(255) NOT NULL,
|
|
264
|
-
acquired_at TIMESTAMP NOT NULL
|
|
265
|
-
)
|
|
266
|
-
` :
|
|
267
|
-
Effect.void,
|
|
268
|
-
orElse: () =>
|
|
269
|
-
// sqlite
|
|
270
|
-
sql`
|
|
271
|
-
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
272
|
-
shard_id TEXT PRIMARY KEY,
|
|
273
|
-
address TEXT NOT NULL,
|
|
274
|
-
acquired_at DATETIME NOT NULL
|
|
275
|
-
)
|
|
276
|
-
`
|
|
277
|
-
})
|
|
278
|
-
|
|
279
166
|
const sqlNowString = sql.onDialectOrElse({
|
|
280
167
|
pg: () => "NOW()",
|
|
281
168
|
mysql: () => "NOW()",
|
|
@@ -765,20 +652,213 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
765
652
|
}, withTracerDisabled)
|
|
766
653
|
|
|
767
654
|
/**
|
|
768
|
-
*
|
|
655
|
+
* Creates a SQL-backed `RunnerStorage` implementation for registered runners and
|
|
656
|
+
* shard locks, using the configured table prefix and advisory locks where
|
|
657
|
+
* supported and enabled.
|
|
658
|
+
*
|
|
659
|
+
* **When to use**
|
|
660
|
+
*
|
|
661
|
+
* Use to create a SQL-backed `RunnerStorage` value directly when building
|
|
662
|
+
* custom service or layer composition around the storage implementation.
|
|
663
|
+
*
|
|
664
|
+
* **Details**
|
|
665
|
+
*
|
|
666
|
+
* `make` first runs the runner storage migrations, so the connection needs
|
|
667
|
+
* permission to create tables. When `prefix` is omitted, `make` uses the
|
|
668
|
+
* `cluster` prefix, creating `cluster_runners`, `cluster_locks`, and the
|
|
669
|
+
* `cluster_runner_migrations` history table. PostgreSQL and MySQL use advisory
|
|
670
|
+
* locks unless `ShardingConfig.shardLockDisableAdvisory` is enabled; other
|
|
671
|
+
* dialects use rows in the locks table.
|
|
672
|
+
*
|
|
673
|
+
* **Gotchas**
|
|
674
|
+
*
|
|
675
|
+
* Changing `prefix` changes all generated table names, so runners using
|
|
676
|
+
* different prefixes do not share registrations or shard locks.
|
|
677
|
+
*
|
|
678
|
+
* @see {@link layer} for the default SQL-backed storage layer
|
|
679
|
+
* @see {@link layerWith} for a SQL-backed storage layer with a custom table prefix
|
|
680
|
+
* @see {@link layerStorage} for a storage layer that does not run migrations
|
|
769
681
|
*
|
|
770
682
|
* @stability unstable
|
|
771
|
-
* @category
|
|
683
|
+
* @category constructors
|
|
772
684
|
* @since 4.0.0
|
|
773
685
|
*/
|
|
774
|
-
export const
|
|
775
|
-
|
|
686
|
+
export const make = (options: {
|
|
687
|
+
readonly prefix?: string | undefined
|
|
688
|
+
}): Effect.Effect<
|
|
689
|
+
RunnerStorage.RunnerStorage["Service"],
|
|
776
690
|
SqlError,
|
|
777
|
-
SqlClient.SqlClient | ShardingConfig.ShardingConfig
|
|
778
|
-
>
|
|
691
|
+
SqlClient.SqlClient | ShardingConfig.ShardingConfig | Scope.Scope
|
|
692
|
+
> => Effect.andThen(runRunnerMigrations(options), makeStorage(options))
|
|
779
693
|
|
|
780
694
|
/**
|
|
781
|
-
*
|
|
695
|
+
* Migration loader for the SQL runner storage tables.
|
|
696
|
+
*
|
|
697
|
+
* **Details**
|
|
698
|
+
*
|
|
699
|
+
* History is recorded in `<prefix>_runner_migrations`; the default
|
|
700
|
+
* prefix is `cluster`. The locks table is created regardless of advisory lock settings.
|
|
701
|
+
*
|
|
702
|
+
* @stability unstable
|
|
703
|
+
* @category migrations
|
|
704
|
+
* @since 4.1.0
|
|
705
|
+
*/
|
|
706
|
+
export const migrations = (options: {
|
|
707
|
+
readonly prefix?: string | undefined
|
|
708
|
+
}): Migrator.Loader => {
|
|
709
|
+
const prefix = options.prefix ?? "cluster"
|
|
710
|
+
const table = (name: string) => `${prefix}_${name}`
|
|
711
|
+
const runnersTable = table("runners")
|
|
712
|
+
const locksTable = table("locks")
|
|
713
|
+
|
|
714
|
+
return Migrator.fromRecord({
|
|
715
|
+
// Existing deployments may have these tables but no migration history.
|
|
716
|
+
"0001_create_tables": Effect.gen(function*() {
|
|
717
|
+
const sql = (yield* SqlClient.SqlClient).withoutTransforms()
|
|
718
|
+
const runnersTableSql = sql(runnersTable)
|
|
719
|
+
const locksTableSql = sql(locksTable)
|
|
720
|
+
|
|
721
|
+
yield* sql.onDialectOrElse({
|
|
722
|
+
mssql: () =>
|
|
723
|
+
sql`
|
|
724
|
+
IF OBJECT_ID(N'${runnersTableSql}', N'U') IS NULL
|
|
725
|
+
CREATE TABLE ${runnersTableSql} (
|
|
726
|
+
machine_id INT IDENTITY PRIMARY KEY,
|
|
727
|
+
address VARCHAR(255) NOT NULL,
|
|
728
|
+
runner TEXT NOT NULL,
|
|
729
|
+
healthy BIT NOT NULL DEFAULT 1,
|
|
730
|
+
last_heartbeat DATETIME NOT NULL DEFAULT GETDATE(),
|
|
731
|
+
UNIQUE(address)
|
|
732
|
+
)
|
|
733
|
+
`,
|
|
734
|
+
mysql: () =>
|
|
735
|
+
sql`
|
|
736
|
+
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
737
|
+
machine_id INT AUTO_INCREMENT PRIMARY KEY,
|
|
738
|
+
address VARCHAR(255) NOT NULL,
|
|
739
|
+
runner TEXT NOT NULL,
|
|
740
|
+
healthy BOOLEAN NOT NULL DEFAULT TRUE,
|
|
741
|
+
last_heartbeat DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
742
|
+
UNIQUE(address)
|
|
743
|
+
)
|
|
744
|
+
`,
|
|
745
|
+
pg: () =>
|
|
746
|
+
sql`
|
|
747
|
+
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
748
|
+
machine_id SERIAL PRIMARY KEY,
|
|
749
|
+
address VARCHAR(255) NOT NULL,
|
|
750
|
+
runner TEXT NOT NULL,
|
|
751
|
+
healthy BOOLEAN NOT NULL DEFAULT TRUE,
|
|
752
|
+
last_heartbeat TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
753
|
+
UNIQUE(address)
|
|
754
|
+
)
|
|
755
|
+
`,
|
|
756
|
+
orElse: () =>
|
|
757
|
+
// sqlite
|
|
758
|
+
sql`
|
|
759
|
+
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
760
|
+
machine_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
761
|
+
address TEXT NOT NULL,
|
|
762
|
+
runner TEXT NOT NULL,
|
|
763
|
+
healthy INTEGER NOT NULL DEFAULT 1,
|
|
764
|
+
last_heartbeat DATETIME NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
|
765
|
+
UNIQUE(address)
|
|
766
|
+
)
|
|
767
|
+
`
|
|
768
|
+
})
|
|
769
|
+
|
|
770
|
+
yield* sql.onDialectOrElse({
|
|
771
|
+
mssql: () =>
|
|
772
|
+
sql`
|
|
773
|
+
IF OBJECT_ID(N'${locksTableSql}', N'U') IS NULL
|
|
774
|
+
CREATE TABLE ${locksTableSql} (
|
|
775
|
+
shard_id VARCHAR(50) PRIMARY KEY,
|
|
776
|
+
address VARCHAR(255) NOT NULL,
|
|
777
|
+
acquired_at DATETIME NOT NULL
|
|
778
|
+
)
|
|
779
|
+
`,
|
|
780
|
+
mysql: () =>
|
|
781
|
+
sql`
|
|
782
|
+
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
783
|
+
shard_id VARCHAR(50) PRIMARY KEY,
|
|
784
|
+
address VARCHAR(255) NOT NULL,
|
|
785
|
+
acquired_at DATETIME NOT NULL
|
|
786
|
+
)
|
|
787
|
+
`,
|
|
788
|
+
pg: () =>
|
|
789
|
+
sql`
|
|
790
|
+
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
791
|
+
shard_id VARCHAR(50) PRIMARY KEY,
|
|
792
|
+
address VARCHAR(255) NOT NULL,
|
|
793
|
+
acquired_at TIMESTAMP NOT NULL
|
|
794
|
+
)
|
|
795
|
+
`,
|
|
796
|
+
orElse: () =>
|
|
797
|
+
// sqlite
|
|
798
|
+
sql`
|
|
799
|
+
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
800
|
+
shard_id TEXT PRIMARY KEY,
|
|
801
|
+
address TEXT NOT NULL,
|
|
802
|
+
acquired_at DATETIME NOT NULL
|
|
803
|
+
)
|
|
804
|
+
`
|
|
805
|
+
})
|
|
806
|
+
})
|
|
807
|
+
})
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const runRunnerMigrations = (options: {
|
|
811
|
+
readonly prefix?: string | undefined
|
|
812
|
+
}): Effect.Effect<void, never, SqlClient.SqlClient> =>
|
|
813
|
+
Migrator.make({})({
|
|
814
|
+
loader: migrations(options),
|
|
815
|
+
// Message and runner migration ids overlap, so keep separate histories.
|
|
816
|
+
table: `${options.prefix ?? "cluster"}_runner_migrations`
|
|
817
|
+
}).pipe(Effect.asVoid, Effect.orDie)
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Runs the SQL runner storage migrations without providing storage.
|
|
821
|
+
*
|
|
822
|
+
* **Details**
|
|
823
|
+
*
|
|
824
|
+
* Use an owner connection in a deploy step, then use `layerStorage` with a
|
|
825
|
+
* DML-only runtime connection. History is recorded in `<prefix>_runner_migrations`.
|
|
826
|
+
* Migration errors become defects.
|
|
827
|
+
* This layer does not require `ShardingConfig`.
|
|
828
|
+
*
|
|
829
|
+
* @stability unstable
|
|
830
|
+
* @category layers
|
|
831
|
+
* @since 4.1.0
|
|
832
|
+
*/
|
|
833
|
+
export const layerMigrations = (options: {
|
|
834
|
+
readonly prefix?: string | undefined
|
|
835
|
+
}): Layer.Layer<never, never, SqlClient.SqlClient> => Layer.effectDiscard(runRunnerMigrations(options))
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Provides SQL-backed `RunnerStorage` without DDL or startup schema checks.
|
|
839
|
+
*
|
|
840
|
+
* **Details**
|
|
841
|
+
*
|
|
842
|
+
* Run `layerMigrations` separately before using this layer.
|
|
843
|
+
*
|
|
844
|
+
* @stability unstable
|
|
845
|
+
* @category layers
|
|
846
|
+
* @since 4.1.0
|
|
847
|
+
*/
|
|
848
|
+
export const layerStorage = (options: {
|
|
849
|
+
readonly prefix?: string | undefined
|
|
850
|
+
}): Layer.Layer<RunnerStorage.RunnerStorage, never, SqlClient.SqlClient | ShardingConfig.ShardingConfig> =>
|
|
851
|
+
Layer.effect(RunnerStorage.RunnerStorage)(makeStorage(options))
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* Provides SQL-backed `RunnerStorage` with a custom table prefix,
|
|
855
|
+
* running migrations first.
|
|
856
|
+
*
|
|
857
|
+
* **Details**
|
|
858
|
+
*
|
|
859
|
+
* The connection needs DDL permissions. PostgreSQL takes an exclusive lock
|
|
860
|
+
* on the migration history table. Use `layerMigrations` and `layerStorage`
|
|
861
|
+
* to migrate separately.
|
|
782
862
|
*
|
|
783
863
|
* @stability unstable
|
|
784
864
|
* @category layers
|
|
@@ -788,3 +868,19 @@ export const layerWith = (options: {
|
|
|
788
868
|
readonly prefix?: string | undefined
|
|
789
869
|
}): Layer.Layer<RunnerStorage.RunnerStorage, SqlError, SqlClient.SqlClient | ShardingConfig.ShardingConfig> =>
|
|
790
870
|
Layer.effect(RunnerStorage.RunnerStorage)(make(options))
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* Layer that provides SQL-backed `RunnerStorage` using the default table prefix,
|
|
874
|
+
* running the runner storage migrations first.
|
|
875
|
+
*
|
|
876
|
+
* @see {@link layerWith} for the same layer with a custom table prefix
|
|
877
|
+
*
|
|
878
|
+
* @stability unstable
|
|
879
|
+
* @category layers
|
|
880
|
+
* @since 4.0.0
|
|
881
|
+
*/
|
|
882
|
+
export const layer: Layer.Layer<
|
|
883
|
+
RunnerStorage.RunnerStorage,
|
|
884
|
+
SqlError,
|
|
885
|
+
SqlClient.SqlClient | ShardingConfig.ShardingConfig
|
|
886
|
+
> = layerWith({})
|