effect 4.1.0 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/THIRD_PARTY_NOTICES.md +62 -0
- package/dist/BigDecimal.d.ts +139 -7
- package/dist/BigDecimal.d.ts.map +1 -1
- package/dist/BigDecimal.js +83 -14
- package/dist/BigDecimal.js.map +1 -1
- package/dist/Equal.d.ts +2 -2
- package/dist/Equal.d.ts.map +1 -1
- package/dist/Equal.js +3 -3
- package/dist/Equal.js.map +1 -1
- package/dist/Hash.d.ts +3 -2
- package/dist/Hash.d.ts.map +1 -1
- package/dist/Hash.js +5 -4
- package/dist/Hash.js.map +1 -1
- package/dist/Iterable.d.ts.map +1 -1
- package/dist/Iterable.js +11 -8
- package/dist/Iterable.js.map +1 -1
- package/dist/Path.d.ts.map +1 -1
- package/dist/Path.js +5 -1
- package/dist/Path.js.map +1 -1
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js +2 -1
- package/dist/Pool.js.map +1 -1
- package/dist/Schema.d.ts +2 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +2 -1
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +4 -2
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +4 -2
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/SchemaTransformation.d.ts +2 -2
- package/dist/SchemaTransformation.js +2 -2
- package/dist/ai/McpClient.d.ts +171 -19
- package/dist/ai/McpClient.d.ts.map +1 -1
- package/dist/ai/McpClient.js +277 -66
- package/dist/ai/McpClient.js.map +1 -1
- package/dist/ai/McpSchema.d.ts +108 -0
- package/dist/ai/McpSchema.d.ts.map +1 -1
- package/dist/ai/McpSchema.js +99 -0
- package/dist/ai/McpSchema.js.map +1 -1
- package/dist/ai/McpServer.d.ts +120 -6
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +215 -34
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Prompt.d.ts.map +1 -1
- package/dist/ai/Prompt.js +20 -11
- package/dist/ai/Prompt.js.map +1 -1
- package/dist/ai/Tool.d.ts.map +1 -1
- package/dist/ai/Tool.js +5 -7
- package/dist/ai/Tool.js.map +1 -1
- package/dist/ai/internal/mcpCore.js +72 -3
- package/dist/ai/internal/mcpCore.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js +42 -7
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
- package/dist/ai/internal/mcpProtocol.js +12 -0
- package/dist/ai/internal/mcpProtocol.js.map +1 -1
- package/dist/ai/internal/mcpRuntime.js +3 -3
- package/dist/ai/internal/mcpRuntime.js.map +1 -1
- package/dist/ai/internal/mcpSkills.d.ts +2 -0
- package/dist/ai/internal/mcpSkills.d.ts.map +1 -0
- package/dist/ai/internal/mcpSkills.js +428 -0
- package/dist/ai/internal/mcpSkills.js.map +1 -0
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +15 -5
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/Reply.d.ts +1 -1
- package/dist/cluster/Reply.d.ts.map +1 -1
- package/dist/cluster/Reply.js.map +1 -1
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +4 -1
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +15 -7
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/crypto/Aead.d.ts +2 -1
- package/dist/crypto/Aead.d.ts.map +1 -1
- package/dist/crypto/Aead.js +2 -2
- package/dist/crypto/Aead.js.map +1 -1
- package/dist/crypto/Cipher.d.ts +2 -1
- package/dist/crypto/Cipher.d.ts.map +1 -1
- package/dist/crypto/Cipher.js +2 -2
- package/dist/crypto/Cipher.js.map +1 -1
- package/dist/crypto/KeyAgreement.d.ts +3 -2
- package/dist/crypto/KeyAgreement.d.ts.map +1 -1
- package/dist/crypto/KeyAgreement.js +2 -2
- package/dist/crypto/KeyAgreement.js.map +1 -1
- package/dist/crypto/KeyFormat.d.ts +33 -1
- package/dist/crypto/KeyFormat.d.ts.map +1 -1
- package/dist/crypto/KeyFormat.js.map +1 -1
- package/dist/crypto/KeyWrap.d.ts +4 -3
- package/dist/crypto/KeyWrap.d.ts.map +1 -1
- package/dist/crypto/KeyWrap.js +2 -2
- package/dist/crypto/KeyWrap.js.map +1 -1
- package/dist/crypto/Mac.d.ts +2 -1
- package/dist/crypto/Mac.d.ts.map +1 -1
- package/dist/crypto/Mac.js +2 -2
- package/dist/crypto/Mac.js.map +1 -1
- package/dist/crypto/Signature.d.ts +3 -2
- package/dist/crypto/Signature.d.ts.map +1 -1
- package/dist/crypto/Signature.js +2 -2
- package/dist/crypto/Signature.js.map +1 -1
- package/dist/crypto/WebCrypto.d.ts +19 -0
- package/dist/crypto/WebCrypto.d.ts.map +1 -1
- package/dist/crypto/WebCrypto.js.map +1 -1
- package/dist/crypto/internal/asymmetric.js.map +1 -1
- package/dist/crypto/internal/key.js +3 -2
- package/dist/crypto/internal/key.js.map +1 -1
- package/dist/encoding/Base64Url.d.ts.map +1 -1
- package/dist/encoding/Base64Url.js +26 -3
- package/dist/encoding/Base64Url.js.map +1 -1
- package/dist/encoding/Ndjson.d.ts +5 -4
- package/dist/encoding/Ndjson.d.ts.map +1 -1
- package/dist/encoding/Ndjson.js +6 -5
- package/dist/encoding/Ndjson.js.map +1 -1
- package/dist/encoding/Sse.d.ts +3 -1
- package/dist/encoding/Sse.d.ts.map +1 -1
- package/dist/encoding/Sse.js +5 -3
- package/dist/encoding/Sse.js.map +1 -1
- package/dist/eventlog/EventLog.d.ts +7 -0
- package/dist/eventlog/EventLog.d.ts.map +1 -1
- package/dist/eventlog/EventLog.js +7 -0
- package/dist/eventlog/EventLog.js.map +1 -1
- package/dist/eventlog/EventLogServer.d.ts +7 -1
- package/dist/eventlog/EventLogServer.d.ts.map +1 -1
- package/dist/eventlog/EventLogServer.js +27 -12
- package/dist/eventlog/EventLogServer.js.map +1 -1
- package/dist/eventlog/EventLogServerEncrypted.d.ts +10 -0
- package/dist/eventlog/EventLogServerEncrypted.d.ts.map +1 -1
- package/dist/eventlog/EventLogServerEncrypted.js.map +1 -1
- package/dist/eventlog/EventLogServerUnencrypted.d.ts +17 -0
- package/dist/eventlog/EventLogServerUnencrypted.d.ts.map +1 -1
- package/dist/eventlog/EventLogServerUnencrypted.js +14 -2
- package/dist/eventlog/EventLogServerUnencrypted.js.map +1 -1
- package/dist/eventlog/EventLogSessionAuth.d.ts +21 -0
- package/dist/eventlog/EventLogSessionAuth.d.ts.map +1 -1
- package/dist/eventlog/EventLogSessionAuth.js +22 -0
- package/dist/eventlog/EventLogSessionAuth.js.map +1 -1
- package/dist/graphql/GraphQLClient.d.ts +3 -1
- package/dist/graphql/GraphQLClient.d.ts.map +1 -1
- package/dist/graphql/GraphQLClient.js.map +1 -1
- package/dist/graphql/GraphQLClientError.d.ts +14 -9
- package/dist/graphql/GraphQLClientError.d.ts.map +1 -1
- package/dist/graphql/GraphQLClientError.js +14 -21
- package/dist/graphql/GraphQLClientError.js.map +1 -1
- package/dist/graphql/GraphQLProtocol.d.ts +12 -3
- package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
- package/dist/graphql/GraphQLProtocol.js +4 -1
- package/dist/graphql/GraphQLProtocol.js.map +1 -1
- package/dist/http/HttpClient.d.ts +189 -7
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +75 -2
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/http/HttpServerRequest.js +38 -22
- package/dist/http/HttpServerRequest.js.map +1 -1
- package/dist/http/internal/mimeTypes.d.ts +4 -1
- package/dist/http/internal/mimeTypes.d.ts.map +1 -1
- package/dist/http/internal/mimeTypes.js +4 -1
- package/dist/http/internal/mimeTypes.js.map +1 -1
- package/dist/http-api/HttpApiSchema.js +1 -1
- package/dist/http-api/HttpApiSchema.js.map +1 -1
- package/dist/internal/dateTime.js +49 -24
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +10 -0
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/glob.js +234 -56
- package/dist/internal/glob.js.map +1 -1
- package/dist/internal/graphql.js +21 -7
- package/dist/internal/graphql.js.map +1 -1
- package/dist/internal/graphqlHeaders.d.ts +7 -0
- package/dist/internal/graphqlHeaders.d.ts.map +1 -1
- package/dist/internal/graphqlHeaders.js +11 -0
- package/dist/internal/graphqlHeaders.js.map +1 -1
- package/dist/internal/request.js +29 -42
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.js +7 -8
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/jose/JoseError.d.ts +285 -0
- package/dist/jose/JoseError.d.ts.map +1 -0
- package/dist/jose/JoseError.js +269 -0
- package/dist/jose/JoseError.js.map +1 -0
- package/dist/jose/Jwe.d.ts +128 -0
- package/dist/jose/Jwe.d.ts.map +1 -0
- package/dist/jose/Jwe.js +134 -0
- package/dist/jose/Jwe.js.map +1 -0
- package/dist/jose/Jwk.d.ts +597 -0
- package/dist/jose/Jwk.d.ts.map +1 -0
- package/dist/jose/Jwk.js +503 -0
- package/dist/jose/Jwk.js.map +1 -0
- package/dist/jose/Jwks.d.ts +236 -0
- package/dist/jose/Jwks.d.ts.map +1 -0
- package/dist/jose/Jwks.js +306 -0
- package/dist/jose/Jwks.js.map +1 -0
- package/dist/jose/Jws.d.ts +177 -0
- package/dist/jose/Jws.d.ts.map +1 -0
- package/dist/jose/Jws.js +183 -0
- package/dist/jose/Jws.js.map +1 -0
- package/dist/jose/Jwt.d.ts +270 -0
- package/dist/jose/Jwt.d.ts.map +1 -0
- package/dist/jose/Jwt.js +293 -0
- package/dist/jose/Jwt.js.map +1 -0
- package/dist/jose/index.d.ts +51 -0
- package/dist/jose/index.d.ts.map +1 -0
- package/dist/jose/index.js +52 -0
- package/dist/jose/index.js.map +1 -0
- package/dist/jose/internal/compact.d.ts +2 -0
- package/dist/jose/internal/compact.d.ts.map +1 -0
- package/dist/jose/internal/compact.js +179 -0
- package/dist/jose/internal/compact.js.map +1 -0
- package/dist/net/Host.d.ts.map +1 -1
- package/dist/net/Host.js +5 -10
- package/dist/net/Host.js.map +1 -1
- package/dist/observability/OtlpSerialization.d.ts +1 -1
- package/dist/observability/OtlpSerialization.d.ts.map +1 -1
- package/dist/observability/OtlpSerialization.js +10 -4
- package/dist/observability/OtlpSerialization.js.map +1 -1
- package/dist/observability/internal/otlpProtobuf.js +3 -3
- package/dist/observability/internal/otlpProtobuf.js.map +1 -1
- package/dist/observability/internal/protobuf.js +6 -0
- package/dist/observability/internal/protobuf.js.map +1 -1
- package/dist/persistence/CircuitBreaker.d.ts +98 -38
- package/dist/persistence/CircuitBreaker.d.ts.map +1 -1
- package/dist/persistence/CircuitBreaker.js +67 -29
- package/dist/persistence/CircuitBreaker.js.map +1 -1
- package/dist/persistence/RateLimiter.d.ts +8 -0
- package/dist/persistence/RateLimiter.d.ts.map +1 -1
- package/dist/persistence/RateLimiter.js +63 -12
- package/dist/persistence/RateLimiter.js.map +1 -1
- package/dist/persistence/index.d.ts +1 -1
- package/dist/persistence/index.js +1 -1
- package/dist/reactivity/AtomRegistry.js +17 -7
- package/dist/reactivity/AtomRegistry.js.map +1 -1
- package/dist/rpc/Rpc.d.ts +1 -1
- package/dist/rpc/Rpc.d.ts.map +1 -1
- package/dist/rpc/Rpc.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts +14 -2
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +38 -21
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcMessage.d.ts +3 -2
- package/dist/rpc/RpcMessage.d.ts.map +1 -1
- package/dist/rpc/RpcMessage.js.map +1 -1
- package/dist/sql/Migrator.d.ts +9 -1
- package/dist/sql/Migrator.d.ts.map +1 -1
- package/dist/sql/Migrator.js +18 -6
- package/dist/sql/Migrator.js.map +1 -1
- package/dist/sql/SqlClient.d.ts +38 -3
- package/dist/sql/SqlClient.d.ts.map +1 -1
- package/dist/sql/SqlClient.js +4 -3
- package/dist/sql/SqlClient.js.map +1 -1
- package/dist/sql/Statement.d.ts +41 -3
- package/dist/sql/Statement.d.ts.map +1 -1
- package/dist/sql/Statement.js +24 -20
- package/dist/sql/Statement.js.map +1 -1
- package/dist/workflow/Workflow.d.ts +4 -0
- package/dist/workflow/Workflow.d.ts.map +1 -1
- package/dist/workflow/Workflow.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +5 -0
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +5 -1
- package/src/BigDecimal.ts +170 -16
- package/src/Equal.ts +3 -3
- package/src/Hash.ts +5 -4
- package/src/Iterable.ts +8 -5
- package/src/Path.ts +6 -1
- package/src/Pool.ts +2 -1
- package/src/Schema.ts +3 -2
- package/src/SchemaRepresentation.ts +4 -2
- package/src/SchemaTransformation.ts +2 -2
- package/src/ai/McpClient.ts +488 -91
- package/src/ai/McpSchema.ts +119 -0
- package/src/ai/McpServer.ts +261 -38
- package/src/ai/Prompt.ts +16 -11
- package/src/ai/Tool.ts +5 -10
- package/src/ai/internal/mcpCore.ts +165 -12
- package/src/ai/internal/mcpProtocol/v2024_11_05.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_03_26.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_06_18.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_11_25.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2026_07_28.ts +41 -7
- package/src/ai/internal/mcpProtocol.ts +15 -0
- package/src/ai/internal/mcpRuntime.ts +6 -3
- package/src/ai/internal/mcpSkills.ts +480 -0
- package/src/cluster/ClusterWorkflowEngine.ts +22 -8
- package/src/cluster/Reply.ts +1 -1
- package/src/cluster/Sharding.ts +4 -1
- package/src/cluster/internal/entityManager.ts +24 -10
- package/src/crypto/Aead.ts +3 -3
- package/src/crypto/Cipher.ts +3 -3
- package/src/crypto/KeyAgreement.ts +4 -4
- package/src/crypto/KeyFormat.ts +30 -1
- package/src/crypto/KeyWrap.ts +6 -6
- package/src/crypto/Mac.ts +3 -3
- package/src/crypto/Signature.ts +4 -4
- package/src/crypto/WebCrypto.ts +20 -0
- package/src/crypto/internal/asymmetric.ts +2 -1
- package/src/crypto/internal/key.ts +12 -5
- package/src/encoding/Base64Url.ts +27 -3
- package/src/encoding/Ndjson.ts +6 -5
- package/src/encoding/Sse.ts +5 -3
- package/src/eventlog/EventLog.ts +7 -0
- package/src/eventlog/EventLogServer.ts +31 -12
- package/src/eventlog/EventLogServerEncrypted.ts +5 -0
- package/src/eventlog/EventLogServerUnencrypted.ts +19 -2
- package/src/eventlog/EventLogSessionAuth.ts +26 -0
- package/src/graphql/GraphQLClient.ts +3 -1
- package/src/graphql/GraphQLClientError.ts +15 -22
- package/src/graphql/GraphQLProtocol.ts +12 -3
- package/src/http/HttpClient.ts +210 -11
- package/src/http/HttpServerRequest.ts +61 -23
- package/src/http/internal/mimeTypes.ts +4 -1
- package/src/http-api/HttpApiSchema.ts +1 -1
- package/src/internal/dateTime.ts +54 -24
- package/src/internal/effect.ts +6 -0
- package/src/internal/glob.ts +279 -63
- package/src/internal/graphql.ts +27 -9
- package/src/internal/graphqlHeaders.ts +13 -0
- package/src/internal/request.ts +51 -58
- package/src/internal/schema/fromJsonSchemaDocument.ts +11 -10
- package/src/internal/version.ts +1 -1
- package/src/jose/JoseError.ts +329 -0
- package/src/jose/Jwe.ts +196 -0
- package/src/jose/Jwk.ts +777 -0
- package/src/jose/Jwks.ts +418 -0
- package/src/jose/Jws.ts +312 -0
- package/src/jose/Jwt.ts +493 -0
- package/src/jose/index.ts +58 -0
- package/src/jose/internal/compact.ts +195 -0
- package/src/net/Host.ts +5 -10
- package/src/observability/OtlpSerialization.ts +13 -5
- package/src/observability/internal/otlpProtobuf.ts +6 -6
- package/src/observability/internal/protobuf.ts +10 -0
- package/src/persistence/CircuitBreaker.ts +113 -48
- package/src/persistence/RateLimiter.ts +84 -15
- package/src/persistence/index.ts +1 -1
- package/src/reactivity/AtomRegistry.ts +19 -8
- package/src/rpc/Rpc.ts +3 -1
- package/src/rpc/RpcClient.ts +44 -24
- package/src/rpc/RpcMessage.ts +3 -2
- package/src/sql/Migrator.ts +35 -18
- package/src/sql/SqlClient.ts +43 -8
- package/src/sql/Statement.ts +52 -22
- package/src/workflow/Workflow.ts +4 -0
- package/src/workflow/WorkflowEngine.ts +5 -0
|
@@ -553,9 +553,15 @@ class RegistryImpl implements AtomRegistry {
|
|
|
553
553
|
const node = this.ensureNode(atom)
|
|
554
554
|
if (options?.immediate) {
|
|
555
555
|
f(node.value())
|
|
556
|
-
} else
|
|
557
|
-
//
|
|
558
|
-
|
|
556
|
+
} else {
|
|
557
|
+
// build the node so the listener hears its next change. A failed build
|
|
558
|
+
// is left for the next read to report; an error raised after the value
|
|
559
|
+
// is committed has no later read to report it, so it is rethrown
|
|
560
|
+
try {
|
|
561
|
+
node.value()
|
|
562
|
+
} catch (error) {
|
|
563
|
+
if ((node.state & NodeFlags.waitingForValue) === 0) throw error
|
|
564
|
+
}
|
|
559
565
|
}
|
|
560
566
|
const remove = node.subscribe(function() {
|
|
561
567
|
f(node._value)
|
|
@@ -842,11 +848,15 @@ class NodeImpl<A> {
|
|
|
842
848
|
}
|
|
843
849
|
|
|
844
850
|
build(): void {
|
|
845
|
-
// a lifetime still attached to a node that needs a value belongs to a
|
|
846
|
-
// build that failed, or to one that is running and is now superseded
|
|
847
|
-
this.disposeLifetime()
|
|
848
|
-
this.invalidatedDuringBuild = false
|
|
849
851
|
const lifetime = makeLifetime(this)
|
|
852
|
+
// release a failed or superseded build; its finalizers run only once, so
|
|
853
|
+
// their failure is rethrown once this build commits
|
|
854
|
+
try {
|
|
855
|
+
this.disposeLifetime()
|
|
856
|
+
} catch (error) {
|
|
857
|
+
lifetime.failure = error
|
|
858
|
+
}
|
|
859
|
+
this.invalidatedDuringBuild = false
|
|
850
860
|
this.lifetime = lifetime
|
|
851
861
|
let value: A
|
|
852
862
|
let read = false
|
|
@@ -1126,7 +1136,8 @@ interface Lifetime<A> extends Atom.AtomContext {
|
|
|
1126
1136
|
readonly node: NodeImpl<A>
|
|
1127
1137
|
// the parents read so far by the build; `undefined` once the build has returned
|
|
1128
1138
|
reads: Set<NodeImpl<any>> | undefined
|
|
1129
|
-
//
|
|
1139
|
+
// rethrown once the build commits: a failure from releasing the previous
|
|
1140
|
+
// lifetime, or from reading a parent that still produced its value
|
|
1130
1141
|
failure: unknown
|
|
1131
1142
|
finalizers: Array<() => void> | undefined
|
|
1132
1143
|
disposed: boolean
|
package/src/rpc/Rpc.ts
CHANGED
|
@@ -363,7 +363,9 @@ export type SuccessExit<R> = Success<R> extends infer T ? T extends Stream<infer
|
|
|
363
363
|
* @category utility types
|
|
364
364
|
* @since 4.0.0
|
|
365
365
|
*/
|
|
366
|
-
export type SuccessChunk<R> =
|
|
366
|
+
export type SuccessChunk<R> = R extends Any ?
|
|
367
|
+
SuccessSchema<R> extends RpcSchema.Stream<infer _A, infer _E> ? _A["Type"] : never
|
|
368
|
+
: never
|
|
367
369
|
|
|
368
370
|
/**
|
|
369
371
|
* Extracts the RPC error schema, including error schemas contributed by
|
package/src/rpc/RpcClient.ts
CHANGED
|
@@ -113,7 +113,8 @@ export declare namespace RpcClient {
|
|
|
113
113
|
* handler's result and error are not returned, but transport errors,
|
|
114
114
|
* middleware errors and failures before the handler starts still fail the
|
|
115
115
|
* call. Over HTTP and workers the call completes after the handler has
|
|
116
|
-
* finished.
|
|
116
|
+
* finished. A protocol that only delivers requests acknowledges the call
|
|
117
|
+
* itself once it has delivered the request.
|
|
117
118
|
*/
|
|
118
119
|
readonly discard?: Discard | undefined
|
|
119
120
|
}
|
|
@@ -188,7 +189,8 @@ export declare namespace RpcClient {
|
|
|
188
189
|
* handler's result and error are not returned, but transport errors,
|
|
189
190
|
* middleware errors and failures before the handler starts still fail the
|
|
190
191
|
* call. Over HTTP and workers the call completes after the handler has
|
|
191
|
-
* finished.
|
|
192
|
+
* finished. A protocol that only delivers requests acknowledges the call
|
|
193
|
+
* itself once it has delivered the request.
|
|
192
194
|
*/
|
|
193
195
|
readonly discard?: Discard | undefined
|
|
194
196
|
}
|
|
@@ -418,19 +420,18 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any, E, const Flatten extend
|
|
|
418
420
|
let fiber: Fiber.Fiber<any, any>
|
|
419
421
|
return Effect.onInterrupt(
|
|
420
422
|
Effect.callback<any, any>((resume) => {
|
|
421
|
-
|
|
422
|
-
let ack: Exit.Exit<any, any> | undefined
|
|
423
|
+
let acked = false
|
|
423
424
|
const entry: ClientEntry = {
|
|
424
425
|
_tag: "Effect",
|
|
425
426
|
rpc,
|
|
426
427
|
context,
|
|
427
428
|
resume(exit) {
|
|
428
|
-
if (discard) {
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
//
|
|
432
|
-
|
|
433
|
-
if (fiber?.pollUnsafe()) resume(
|
|
429
|
+
if (discard && exit._tag === "Success") {
|
|
430
|
+
// A successful acknowledgement waits for the send to finish, as
|
|
431
|
+
// interrupting the send could cancel the call: an HTTP handler
|
|
432
|
+
// is scoped to its request. Failures complete the call at once.
|
|
433
|
+
acked = true
|
|
434
|
+
if (fiber?.pollUnsafe()) resume(Exit.void)
|
|
434
435
|
return
|
|
435
436
|
}
|
|
436
437
|
resume(exit)
|
|
@@ -450,8 +451,8 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any, E, const Flatten extend
|
|
|
450
451
|
if (exit._tag === "Failure") {
|
|
451
452
|
entries.delete(id)
|
|
452
453
|
return resume(exit)
|
|
453
|
-
} else if (
|
|
454
|
-
return resume(
|
|
454
|
+
} else if (acked) {
|
|
455
|
+
return resume(Exit.void)
|
|
455
456
|
}
|
|
456
457
|
})
|
|
457
458
|
}),
|
|
@@ -604,8 +605,10 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any, E, const Flatten extend
|
|
|
604
605
|
if (!entry || entry._tag !== "Queue") return Effect.void
|
|
605
606
|
return Queue.offerAll(entry.queue, message.values).pipe(
|
|
606
607
|
supportsAck
|
|
607
|
-
? Effect.flatMap(() =>
|
|
608
|
-
|
|
608
|
+
? Effect.flatMap((dropped) =>
|
|
609
|
+
// values are dropped when the queue was shutdown by an interrupted
|
|
610
|
+
// consumer, so the server should not be asked for more
|
|
611
|
+
dropped.length > 0 ? Effect.void : options.onFromClient({
|
|
609
612
|
message: { _tag: "Ack", requestId: message.requestId },
|
|
610
613
|
context: entry.context
|
|
611
614
|
})
|
|
@@ -831,8 +834,10 @@ export const make: <Rpcs extends Rpc.Any, const Flatten extends boolean = false>
|
|
|
831
834
|
}
|
|
832
835
|
case "ClientProtocolError": {
|
|
833
836
|
const exit = Exit.fail(message.error)
|
|
834
|
-
const requestIds =
|
|
835
|
-
|
|
837
|
+
const requestIds = message.requestIds === undefined
|
|
838
|
+
? Array.from(entries.keys())
|
|
839
|
+
: message.requestIds.map(RequestId).filter((requestId) => entries.has(requestId))
|
|
840
|
+
for (const requestId of requestIds) entries.delete(requestId)
|
|
836
841
|
return Effect.forEach(
|
|
837
842
|
requestIds,
|
|
838
843
|
(requestId) => write({ _tag: "Exit", clientId: 0, requestId, exit: exit as any })
|
|
@@ -953,6 +958,16 @@ export const withHeaders: {
|
|
|
953
958
|
* Use to provide the transport boundary for RPC clients over HTTP, WebSocket,
|
|
954
959
|
* workers, sockets, or custom protocols.
|
|
955
960
|
*
|
|
961
|
+
* **Details**
|
|
962
|
+
*
|
|
963
|
+
* A `Request` that `send` accepts stays pending until a reply names its id: an
|
|
964
|
+
* `Exit`, or a `ClientProtocolError` that lists it in `requestIds`. Until then
|
|
965
|
+
* the client keeps the request and the caller's context, unless the caller is
|
|
966
|
+
* interrupted, the client closes or the connection fails. A transport that
|
|
967
|
+
* only delivers requests, such as a message queue, writes a void `Exit` for a
|
|
968
|
+
* `discard` request once the request is delivered, and fails `send` with an
|
|
969
|
+
* `RpcClientError` for any other request.
|
|
970
|
+
*
|
|
956
971
|
* @stability unstable
|
|
957
972
|
* @category services
|
|
958
973
|
* @since 4.0.0
|
|
@@ -1599,21 +1614,26 @@ export const makeProtocolWorker = (
|
|
|
1599
1614
|
undefined
|
|
1600
1615
|
}).pipe(
|
|
1601
1616
|
Effect.tapCause((cause) => {
|
|
1617
|
+
const requestIdsByClient = new Map<number, Array<string | number>>()
|
|
1602
1618
|
for (const [requestId, entry] of entries) {
|
|
1603
1619
|
if (entry.worker !== backing) continue
|
|
1604
1620
|
entries.delete(requestId)
|
|
1605
1621
|
entry.latch.openUnsafe()
|
|
1622
|
+
const requestIds = requestIdsByClient.get(entry.clientId)
|
|
1623
|
+
if (requestIds) requestIds.push(requestId)
|
|
1624
|
+
else requestIdsByClient.set(entry.clientId, [requestId])
|
|
1606
1625
|
}
|
|
1607
|
-
const
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
message: "Error in worker",
|
|
1613
|
-
cause: Cause.squash(cause)
|
|
1614
|
-
})
|
|
1626
|
+
const found = Cause.findError(cause)
|
|
1627
|
+
const error = new RpcClientError({
|
|
1628
|
+
reason: Result.isSuccess(found) ? found.success.reason : new RpcClientDefect({
|
|
1629
|
+
message: "Error in worker",
|
|
1630
|
+
cause: Cause.squash(cause)
|
|
1615
1631
|
})
|
|
1616
1632
|
})
|
|
1633
|
+
return Effect.forEach(
|
|
1634
|
+
requestIdsByClient,
|
|
1635
|
+
([clientId, requestIds]) => writeResponse(clientId, { _tag: "ClientProtocolError", error, requestIds })
|
|
1636
|
+
)
|
|
1617
1637
|
}),
|
|
1618
1638
|
Effect.retry(Schedule.spaced(1000)),
|
|
1619
1639
|
Effect.annotateLogs({
|
package/src/rpc/RpcMessage.ts
CHANGED
|
@@ -325,8 +325,8 @@ export interface ResponseExitEncoded {
|
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
/**
|
|
328
|
-
* A server-to-client protocol message
|
|
329
|
-
*
|
|
328
|
+
* A server-to-client protocol message failing in-flight requests with a client
|
|
329
|
+
* protocol error: those in `requestIds`, or all of them when it is omitted.
|
|
330
330
|
*
|
|
331
331
|
* @stability unstable
|
|
332
332
|
* @category models
|
|
@@ -335,6 +335,7 @@ export interface ResponseExitEncoded {
|
|
|
335
335
|
export interface ClientProtocolError {
|
|
336
336
|
readonly _tag: "ClientProtocolError"
|
|
337
337
|
readonly error: RpcClientError
|
|
338
|
+
readonly requestIds?: ReadonlyArray<string | number>
|
|
338
339
|
}
|
|
339
340
|
|
|
340
341
|
/**
|
package/src/sql/Migrator.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import * as Arr from "../Array.ts"
|
|
13
13
|
import * as Data from "../Data.ts"
|
|
14
14
|
import * as Effect from "../Effect.ts"
|
|
15
|
-
import { pipe } from "../Function.ts"
|
|
15
|
+
import { identity, pipe } from "../Function.ts"
|
|
16
16
|
import * as Option from "../Option.ts"
|
|
17
17
|
import * as Order from "../Order.ts"
|
|
18
18
|
import * as Client from "./SqlClient.ts"
|
|
@@ -99,13 +99,22 @@ export class MigrationError extends Data.TaggedError("MigrationError")<{
|
|
|
99
99
|
* migrations. ClickHouse runs without a transaction and records each migration
|
|
100
100
|
* only after it succeeds.
|
|
101
101
|
*
|
|
102
|
+
* **Details**
|
|
103
|
+
*
|
|
104
|
+
* `transformWrites` transforms only the effects that create the migrations
|
|
105
|
+
* table and insert into it, for clients such as ClickHouse that run row-less
|
|
106
|
+
* statements differently from queries. Reads of the migrations table and the
|
|
107
|
+
* migrations themselves are not transformed. It defaults to `identity`.
|
|
108
|
+
*
|
|
102
109
|
* @stability unstable
|
|
103
110
|
* @category constructors
|
|
104
111
|
* @since 4.0.0
|
|
105
112
|
*/
|
|
106
113
|
export const make = <RD = never>({
|
|
114
|
+
transformWrites = identity,
|
|
107
115
|
dumpSchema = () => Effect.void
|
|
108
116
|
}: {
|
|
117
|
+
transformWrites?: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
|
|
109
118
|
dumpSchema?: (
|
|
110
119
|
path: string,
|
|
111
120
|
migrationsTable: string
|
|
@@ -123,7 +132,7 @@ export const make = <RD = never>({
|
|
|
123
132
|
Effect.gen(function*() {
|
|
124
133
|
const sql = yield* Client.SqlClient
|
|
125
134
|
|
|
126
|
-
const
|
|
135
|
+
const createMigrationsTable = transformWrites(sql.onDialectOrElse({
|
|
127
136
|
mssql: () =>
|
|
128
137
|
sql`IF OBJECT_ID(N'${sql.literal(table)}', N'U') IS NULL
|
|
129
138
|
CREATE TABLE ${sql(table)} (
|
|
@@ -147,14 +156,25 @@ export const make = <RD = never>({
|
|
|
147
156
|
) ENGINE = MergeTree
|
|
148
157
|
ORDER BY migration_id`,
|
|
149
158
|
pg: () =>
|
|
150
|
-
|
|
151
|
-
migrationsTableExists(sql, table),
|
|
152
|
-
(exists) =>
|
|
153
|
-
exists ? Effect.void : Effect.asVoid(sql`CREATE TABLE ${sql(table)} (
|
|
159
|
+
sql`CREATE TABLE ${sql(table)} (
|
|
154
160
|
migration_id integer primary key,
|
|
155
161
|
created_at timestamp with time zone not null default now(),
|
|
156
162
|
name text not null
|
|
157
|
-
)
|
|
163
|
+
)`,
|
|
164
|
+
orElse: () =>
|
|
165
|
+
sql`CREATE TABLE IF NOT EXISTS ${sql(table)} (
|
|
166
|
+
migration_id integer PRIMARY KEY NOT NULL,
|
|
167
|
+
created_at datetime NOT NULL DEFAULT current_timestamp,
|
|
168
|
+
name VARCHAR(255) NOT NULL
|
|
169
|
+
)`
|
|
170
|
+
}))
|
|
171
|
+
|
|
172
|
+
const ensureMigrationsTable = sql.onDialectOrElse({
|
|
173
|
+
pg: () =>
|
|
174
|
+
Effect.flatMap(
|
|
175
|
+
migrationsTableExists(sql, table),
|
|
176
|
+
(exists) =>
|
|
177
|
+
exists ? Effect.void : Effect.asVoid(createMigrationsTable).pipe(
|
|
158
178
|
Effect.catch((error) =>
|
|
159
179
|
Effect.flatMap(
|
|
160
180
|
migrationsTableExists(sql, table),
|
|
@@ -163,22 +183,19 @@ ORDER BY migration_id`,
|
|
|
163
183
|
)
|
|
164
184
|
)
|
|
165
185
|
),
|
|
166
|
-
orElse: () =>
|
|
167
|
-
sql`CREATE TABLE IF NOT EXISTS ${sql(table)} (
|
|
168
|
-
migration_id integer PRIMARY KEY NOT NULL,
|
|
169
|
-
created_at datetime NOT NULL DEFAULT current_timestamp,
|
|
170
|
-
name VARCHAR(255) NOT NULL
|
|
171
|
-
)`
|
|
186
|
+
orElse: () => createMigrationsTable
|
|
172
187
|
})
|
|
173
188
|
|
|
174
189
|
const insertMigrations = (
|
|
175
190
|
rows: Arr.NonEmptyReadonlyArray<[id: number, name: string]>
|
|
176
191
|
) =>
|
|
177
|
-
|
|
178
|
-
sql
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
transformWrites(
|
|
193
|
+
sql`INSERT INTO ${sql(table)} ${
|
|
194
|
+
sql.insert(
|
|
195
|
+
Arr.map(rows, ([migration_id, name]) => ({ migration_id, name }))
|
|
196
|
+
)
|
|
197
|
+
}`.withoutTransform
|
|
198
|
+
)
|
|
182
199
|
|
|
183
200
|
const latestMigration = Effect.map(
|
|
184
201
|
sql<{ migration_id: number; name: string; created_at: Date }>`SELECT migration_id, name, created_at FROM ${
|
package/src/sql/SqlClient.ts
CHANGED
|
@@ -81,6 +81,10 @@ export interface SqlClient extends Constructor {
|
|
|
81
81
|
* client's, such as one that sets its isolation level, provide
|
|
82
82
|
* `BeginTransaction`.
|
|
83
83
|
*
|
|
84
|
+
* To retry serialization failures or deadlocks, wrap the outermost
|
|
85
|
+
* `withTransaction` in `Effect.retry`. Each attempt starts a fresh
|
|
86
|
+
* transaction and re-runs the whole effect, including `COMMIT`.
|
|
87
|
+
*
|
|
84
88
|
* **Gotchas**
|
|
85
89
|
*
|
|
86
90
|
* Deferred invalidations run individually after the commit and don't join an
|
|
@@ -88,6 +92,35 @@ export interface SqlClient extends Constructor {
|
|
|
88
92
|
* the transaction's context defers, and a fiber that outlives the
|
|
89
93
|
* transaction can't defer through it, as with `afterCommit`. Transactions
|
|
90
94
|
* that don't go through `makeWithTransaction` invalidate immediately.
|
|
95
|
+
*
|
|
96
|
+
* Retrying a nested transaction only retries its savepoint, which can't
|
|
97
|
+
* recover an outer transaction the database has aborted. Since a retried
|
|
98
|
+
* effect runs more than once, keep non-transactional side effects in
|
|
99
|
+
* `afterCommit`, which discards the callbacks of a failed attempt but
|
|
100
|
+
* doesn't guarantee they run exactly once. Don't retry `ConnectionError`: a
|
|
101
|
+
* `COMMIT` that lost its connection may have committed, and retrying would
|
|
102
|
+
* apply its writes twice.
|
|
103
|
+
*
|
|
104
|
+
* **Example** (Retrying serialization failures and deadlocks)
|
|
105
|
+
*
|
|
106
|
+
* ```ts
|
|
107
|
+
* import { Effect, Schedule } from "effect"
|
|
108
|
+
* import { SqlClient } from "effect/sql"
|
|
109
|
+
*
|
|
110
|
+
* const program = Effect.gen(function*() {
|
|
111
|
+
* const sql = yield* SqlClient.SqlClient
|
|
112
|
+
* return yield* sql.withTransaction(
|
|
113
|
+
* sql`UPDATE accounts SET balance = balance - 10 WHERE id = 1`
|
|
114
|
+
* ).pipe(
|
|
115
|
+
* Effect.provideService(SqlClient.BeginTransaction, "BEGIN ISOLATION LEVEL SERIALIZABLE"),
|
|
116
|
+
* Effect.retry({
|
|
117
|
+
* while: (error) => error.reason._tag === "SerializationError" || error.reason._tag === "DeadlockError",
|
|
118
|
+
* times: 5,
|
|
119
|
+
* schedule: Schedule.exponential("10 millis").pipe(Schedule.jittered)
|
|
120
|
+
* })
|
|
121
|
+
* )
|
|
122
|
+
* })
|
|
123
|
+
* ```
|
|
91
124
|
*/
|
|
92
125
|
readonly withTransaction: <R, E, A>(
|
|
93
126
|
self: Effect.Effect<A, E, R>
|
|
@@ -206,9 +239,8 @@ export declare namespace SqlClient {
|
|
|
206
239
|
readonly spanAttributes: ReadonlyArray<readonly [string, unknown]>
|
|
207
240
|
readonly transactionService?: Context.Service<TransactionConnection, TransactionConnection.Service>
|
|
208
241
|
/**
|
|
209
|
-
* Whether the transaction control statements - `BEGIN`, `COMMIT
|
|
210
|
-
* `
|
|
211
|
-
* statement.
|
|
242
|
+
* Whether the transaction control statements - `BEGIN`, `COMMIT` and
|
|
243
|
+
* `SAVEPOINT` - can be prepared like any other statement.
|
|
212
244
|
*
|
|
213
245
|
* **Details**
|
|
214
246
|
*
|
|
@@ -216,6 +248,9 @@ export declare namespace SqlClient {
|
|
|
216
248
|
* prepare them stops parsing them again each time. Off by default,
|
|
217
249
|
* because several databases refuse to prepare transaction control at all;
|
|
218
250
|
* a driver has to say that its own does not.
|
|
251
|
+
*
|
|
252
|
+
* Rollbacks and savepoint releases always run unprepared, so a prepared
|
|
253
|
+
* statement the backend has dropped cannot stop cleanup.
|
|
219
254
|
*/
|
|
220
255
|
readonly prepareTransactionControls?: boolean | undefined
|
|
221
256
|
readonly beginTransaction?: string | undefined
|
|
@@ -274,20 +309,20 @@ export const make = Effect.fnUntraced(function*(options: SqlClient.MakeOptions)
|
|
|
274
309
|
const rollback = options.rollback ?? "ROLLBACK"
|
|
275
310
|
const rollbackSavepoint = options.rollbackSavepoint ?? ((name: string) => `ROLLBACK TO SAVEPOINT ${name}`)
|
|
276
311
|
const transactionAcquirer = options.transactionAcquirer ?? options.acquirer
|
|
312
|
+
const unprepared = (conn: Connection.Connection, sql: string) => conn.executeUnprepared(sql, [], undefined)
|
|
277
313
|
const control = options.prepareTransactionControls === true
|
|
278
314
|
? (conn: Connection.Connection, sql: string) => conn.execute(sql, [], undefined)
|
|
279
|
-
:
|
|
315
|
+
: unprepared
|
|
280
316
|
const isTransaction = options.isTransaction
|
|
281
317
|
const cleanup = isTransaction
|
|
282
|
-
? (conn: Connection.Connection, sql: string) => isTransaction(conn) ?
|
|
283
|
-
:
|
|
318
|
+
? (conn: Connection.Connection, sql: string) => isTransaction(conn) ? unprepared(conn, sql) : Effect.void
|
|
319
|
+
: unprepared
|
|
284
320
|
const withTransaction = makeWithTransaction({
|
|
285
321
|
transactionService,
|
|
286
322
|
spanAttributes: options.spanAttributes,
|
|
287
323
|
acquireConnection: (restore) => restore(transactionAcquirer!),
|
|
288
324
|
// Unlike the client's own, a provided statement isn't fixed, so it isn't prepared.
|
|
289
|
-
begin: (conn, statement) =>
|
|
290
|
-
statement === undefined ? control(conn, beginTransaction) : conn.executeUnprepared(statement, [], undefined),
|
|
325
|
+
begin: (conn, statement) => statement === undefined ? control(conn, beginTransaction) : unprepared(conn, statement),
|
|
291
326
|
savepoint: (conn, id) => control(conn, savepoint(`effect_sql_${id}`)),
|
|
292
327
|
releaseSavepoint: releaseSavepoint
|
|
293
328
|
? (conn, id) => cleanup(conn, releaseSavepoint(`effect_sql_${id}`))
|
package/src/sql/Statement.ts
CHANGED
|
@@ -27,7 +27,41 @@ import * as Tracer from "../Tracer.ts"
|
|
|
27
27
|
import type { Acquirer, Borrower, Connection, Row } from "./SqlConnection.ts"
|
|
28
28
|
import type { SqlError } from "./SqlError.ts"
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Runtime type identifier for SQL `Fragment` values.
|
|
32
|
+
*
|
|
33
|
+
* @stability unstable
|
|
34
|
+
* @category Type ID
|
|
35
|
+
* @since 4.1.1
|
|
36
|
+
*/
|
|
37
|
+
export const FragmentTypeId: unique symbol = Symbol.for("~effect/sql/Statement/Fragment")
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Type of the unique symbol used to brand SQL `Fragment` values.
|
|
41
|
+
*
|
|
42
|
+
* @stability unstable
|
|
43
|
+
* @category Type ID
|
|
44
|
+
* @since 4.1.1
|
|
45
|
+
*/
|
|
46
|
+
export type FragmentTypeId = typeof FragmentTypeId
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Runtime type identifier for SQL `Segment` values.
|
|
50
|
+
*
|
|
51
|
+
* @stability unstable
|
|
52
|
+
* @category Type ID
|
|
53
|
+
* @since 4.1.1
|
|
54
|
+
*/
|
|
55
|
+
export const SegmentTypeId: unique symbol = Symbol.for("~effect/sql/Statement/Segment")
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Type of the unique symbol used to brand SQL `Segment` values.
|
|
59
|
+
*
|
|
60
|
+
* @stability unstable
|
|
61
|
+
* @category Type ID
|
|
62
|
+
* @since 4.1.1
|
|
63
|
+
*/
|
|
64
|
+
export type SegmentTypeId = typeof SegmentTypeId
|
|
31
65
|
|
|
32
66
|
/**
|
|
33
67
|
* Composable SQL fragment represented as low-level segments that can be
|
|
@@ -38,7 +72,7 @@ const FragmentTypeId = "~effect/sql/Statement/Fragment"
|
|
|
38
72
|
* @since 4.0.0
|
|
39
73
|
*/
|
|
40
74
|
export interface Fragment {
|
|
41
|
-
readonly [FragmentTypeId]:
|
|
75
|
+
readonly [FragmentTypeId]: FragmentTypeId
|
|
42
76
|
readonly segments: ReadonlyArray<Segment>
|
|
43
77
|
}
|
|
44
78
|
|
|
@@ -147,7 +181,7 @@ export const isFragment = (u: unknown): u is Fragment => hasProperty(u, Fragment
|
|
|
147
181
|
export const isCustom = <A extends Custom<any, any, any, any>>(
|
|
148
182
|
kind: A["kind"]
|
|
149
183
|
) =>
|
|
150
|
-
(u: unknown): u is A =>
|
|
184
|
+
(u: unknown): u is A => isSegment(u) && u._tag === "Custom" && u.kind === kind
|
|
151
185
|
|
|
152
186
|
/**
|
|
153
187
|
* Union of low-level segment types that make up a SQL `Fragment`.
|
|
@@ -175,6 +209,7 @@ export type Segment =
|
|
|
175
209
|
* @since 4.0.0
|
|
176
210
|
*/
|
|
177
211
|
export interface Literal {
|
|
212
|
+
readonly [SegmentTypeId]: SegmentTypeId
|
|
178
213
|
readonly _tag: "Literal"
|
|
179
214
|
readonly value: string
|
|
180
215
|
readonly params?: ReadonlyArray<unknown> | undefined
|
|
@@ -189,6 +224,7 @@ export interface Literal {
|
|
|
189
224
|
* @since 4.0.0
|
|
190
225
|
*/
|
|
191
226
|
export const literal = (value: string, params?: ReadonlyArray<unknown> | undefined): Literal => ({
|
|
227
|
+
[SegmentTypeId]: SegmentTypeId,
|
|
192
228
|
_tag: "Literal",
|
|
193
229
|
value,
|
|
194
230
|
params
|
|
@@ -202,6 +238,7 @@ export const literal = (value: string, params?: ReadonlyArray<unknown> | undefin
|
|
|
202
238
|
* @since 4.0.0
|
|
203
239
|
*/
|
|
204
240
|
export interface Identifier {
|
|
241
|
+
readonly [SegmentTypeId]: SegmentTypeId
|
|
205
242
|
readonly _tag: "Identifier"
|
|
206
243
|
readonly value: string
|
|
207
244
|
}
|
|
@@ -215,6 +252,7 @@ export interface Identifier {
|
|
|
215
252
|
* @since 4.0.0
|
|
216
253
|
*/
|
|
217
254
|
export const identifier = (value: string): Identifier => ({
|
|
255
|
+
[SegmentTypeId]: SegmentTypeId,
|
|
218
256
|
_tag: "Identifier",
|
|
219
257
|
value
|
|
220
258
|
})
|
|
@@ -228,6 +266,7 @@ export const identifier = (value: string): Identifier => ({
|
|
|
228
266
|
* @since 4.0.0
|
|
229
267
|
*/
|
|
230
268
|
export interface Parameter {
|
|
269
|
+
readonly [SegmentTypeId]: SegmentTypeId
|
|
231
270
|
readonly _tag: "Parameter"
|
|
232
271
|
readonly value: unknown
|
|
233
272
|
}
|
|
@@ -240,6 +279,7 @@ export interface Parameter {
|
|
|
240
279
|
* @since 4.0.0
|
|
241
280
|
*/
|
|
242
281
|
export const parameter = (value: unknown): Parameter => ({
|
|
282
|
+
[SegmentTypeId]: SegmentTypeId,
|
|
243
283
|
_tag: "Parameter",
|
|
244
284
|
value
|
|
245
285
|
})
|
|
@@ -253,6 +293,7 @@ export const parameter = (value: unknown): Parameter => ({
|
|
|
253
293
|
* @since 4.0.0
|
|
254
294
|
*/
|
|
255
295
|
export interface ArrayHelper {
|
|
296
|
+
readonly [SegmentTypeId]: SegmentTypeId
|
|
256
297
|
readonly _tag: "ArrayHelper"
|
|
257
298
|
readonly value: ReadonlyArray<unknown | Fragment>
|
|
258
299
|
}
|
|
@@ -265,6 +306,7 @@ export interface ArrayHelper {
|
|
|
265
306
|
* @since 4.0.0
|
|
266
307
|
*/
|
|
267
308
|
export const arrayHelper = (value: ReadonlyArray<unknown | Fragment>): ArrayHelper => ({
|
|
309
|
+
[SegmentTypeId]: SegmentTypeId,
|
|
268
310
|
_tag: "ArrayHelper",
|
|
269
311
|
value
|
|
270
312
|
})
|
|
@@ -278,6 +320,7 @@ export const arrayHelper = (value: ReadonlyArray<unknown | Fragment>): ArrayHelp
|
|
|
278
320
|
* @since 4.0.0
|
|
279
321
|
*/
|
|
280
322
|
export interface RecordInsertHelper {
|
|
323
|
+
readonly [SegmentTypeId]: SegmentTypeId
|
|
281
324
|
readonly _tag: "RecordInsertHelper"
|
|
282
325
|
readonly value: Arr.NonEmptyReadonlyArray<Record<string, unknown>>
|
|
283
326
|
/**
|
|
@@ -288,6 +331,7 @@ export interface RecordInsertHelper {
|
|
|
288
331
|
}
|
|
289
332
|
|
|
290
333
|
const RecordInsertHelperProto = {
|
|
334
|
+
[SegmentTypeId]: SegmentTypeId,
|
|
291
335
|
_tag: "RecordInsertHelper" as const,
|
|
292
336
|
returning(this: RecordInsertHelper, sql: string | Identifier | Fragment) {
|
|
293
337
|
const self = Object.create(Object.getPrototypeOf(this))
|
|
@@ -322,6 +366,7 @@ export const recordInsertHelper = (
|
|
|
322
366
|
* @since 4.0.0
|
|
323
367
|
*/
|
|
324
368
|
export interface RecordUpdateHelper {
|
|
369
|
+
readonly [SegmentTypeId]: SegmentTypeId
|
|
325
370
|
readonly _tag: "RecordUpdateHelper"
|
|
326
371
|
readonly value: Arr.NonEmptyReadonlyArray<Record<string, unknown>>
|
|
327
372
|
readonly alias: string
|
|
@@ -364,6 +409,7 @@ export const recordUpdateHelper = (
|
|
|
364
409
|
* @since 4.0.0
|
|
365
410
|
*/
|
|
366
411
|
export interface RecordUpdateHelperSingle {
|
|
412
|
+
readonly [SegmentTypeId]: SegmentTypeId
|
|
367
413
|
readonly _tag: "RecordUpdateHelperSingle"
|
|
368
414
|
readonly value: Record<string, unknown>
|
|
369
415
|
readonly omit: ReadonlyArray<string>
|
|
@@ -411,6 +457,7 @@ export interface Custom<
|
|
|
411
457
|
B = void,
|
|
412
458
|
C = void
|
|
413
459
|
> {
|
|
460
|
+
readonly [SegmentTypeId]: SegmentTypeId
|
|
414
461
|
readonly _tag: "Custom"
|
|
415
462
|
readonly kind: T
|
|
416
463
|
readonly paramA: A
|
|
@@ -433,7 +480,7 @@ export const custom = <C extends Custom<any, any, any, any>>(
|
|
|
433
480
|
paramA: C["paramA"],
|
|
434
481
|
paramB: C["paramB"],
|
|
435
482
|
paramC: C["paramC"]
|
|
436
|
-
): C => ({ _tag: "Custom", kind, paramA, paramB, paramC } as C)
|
|
483
|
+
): C => ({ [SegmentTypeId]: SegmentTypeId, _tag: "Custom", kind, paramA, paramB, paramC } as C)
|
|
437
484
|
|
|
438
485
|
/**
|
|
439
486
|
* Names the primitive value categories recognized by SQL statement helpers and
|
|
@@ -1613,24 +1660,7 @@ const withStatement = <A, X, E, R>(
|
|
|
1613
1660
|
)
|
|
1614
1661
|
})
|
|
1615
1662
|
|
|
1616
|
-
const isSegment = (u: unknown): u is Segment =>
|
|
1617
|
-
if (!hasProperty(u, "_tag")) {
|
|
1618
|
-
return false
|
|
1619
|
-
}
|
|
1620
|
-
switch (u._tag) {
|
|
1621
|
-
case "Literal":
|
|
1622
|
-
case "Parameter":
|
|
1623
|
-
case "ArrayHelper":
|
|
1624
|
-
case "RecordInsertHelper":
|
|
1625
|
-
case "RecordUpdateHelper":
|
|
1626
|
-
case "RecordUpdateHelperSingle":
|
|
1627
|
-
case "Identifier":
|
|
1628
|
-
case "Custom":
|
|
1629
|
-
return true
|
|
1630
|
-
default:
|
|
1631
|
-
return false
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1663
|
+
const isSegment = (u: unknown): u is Segment => hasProperty(u, SegmentTypeId)
|
|
1634
1664
|
|
|
1635
1665
|
function convertLiteralOrFragment(clause: string | Fragment): Array<Segment> {
|
|
1636
1666
|
if (typeof clause === "string") {
|
package/src/workflow/Workflow.ts
CHANGED
|
@@ -88,6 +88,10 @@ export interface Workflow<
|
|
|
88
88
|
* nor gets interrupted with it. The cluster engine retains the parent for
|
|
89
89
|
* observability.
|
|
90
90
|
*
|
|
91
|
+
* Inside a workflow, an awaited child that is interrupted fails the parent
|
|
92
|
+
* with a defect rather than an interrupt, so the parent can recover with
|
|
93
|
+
* `Effect.catchDefect` or `Effect.exit`.
|
|
94
|
+
*
|
|
91
95
|
* **Gotchas**
|
|
92
96
|
*
|
|
93
97
|
* Do not await a detached execution later. Executing the same payload joins
|
|
@@ -583,6 +583,11 @@ export const makeUnsafe = (options: Encoded): WorkflowEngine["Service"] =>
|
|
|
583
583
|
if (wrapped._tag === "Suspended") {
|
|
584
584
|
return yield* Workflow.suspend(parentInstance.value)
|
|
585
585
|
}
|
|
586
|
+
// A child's interrupt is an outcome for the parent, not an interrupt of
|
|
587
|
+
// the parent's run, so surface it as a defect the parent can observe.
|
|
588
|
+
if (Exit.isFailure(wrapped.exit) && Cause.hasInterruptsOnly(wrapped.exit.cause)) {
|
|
589
|
+
return yield* Effect.die(`${self._tag}.execute: execution "${executionId}" was interrupted`)
|
|
590
|
+
}
|
|
586
591
|
return yield* wrapped.exit
|
|
587
592
|
}
|
|
588
593
|
|