effect 4.0.0-beta.93 → 4.0.0-beta.94
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/Config.d.ts +1 -1
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js.map +1 -1
- package/dist/Effect.d.ts +130 -0
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +43 -0
- package/dist/Effect.js.map +1 -1
- package/dist/FileSystem.d.ts +7 -0
- package/dist/FileSystem.d.ts.map +1 -1
- package/dist/FileSystem.js +3 -0
- package/dist/FileSystem.js.map +1 -1
- package/dist/Layer.d.ts +1 -1
- package/dist/Layer.d.ts.map +1 -1
- package/dist/Layer.js +6 -3
- package/dist/Layer.js.map +1 -1
- package/dist/LayerMap.js +1 -1
- package/dist/LayerMap.js.map +1 -1
- package/dist/LayerRef.d.ts +252 -0
- package/dist/LayerRef.d.ts.map +1 -0
- package/dist/LayerRef.js +171 -0
- package/dist/LayerRef.js.map +1 -0
- package/dist/Schema.d.ts +74 -30
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaParser.d.ts +1 -1
- package/dist/SchemaParser.d.ts.map +1 -1
- package/dist/SchemaParser.js.map +1 -1
- package/dist/internal/effect.js +2 -0
- package/dist/internal/effect.js.map +1 -1
- package/dist/testing/TestSchema.d.ts +2 -2
- package/dist/testing/TestSchema.d.ts.map +1 -1
- package/dist/testing/TestSchema.js.map +1 -1
- package/dist/unstable/ai/Chat.d.ts +1 -1
- package/dist/unstable/ai/Chat.d.ts.map +1 -1
- package/dist/unstable/ai/LanguageModel.d.ts +2 -2
- package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
- package/dist/unstable/cli/Argument.d.ts +2 -2
- package/dist/unstable/cli/Argument.d.ts.map +1 -1
- package/dist/unstable/cli/Argument.js.map +1 -1
- package/dist/unstable/cli/Flag.d.ts +2 -2
- package/dist/unstable/cli/Flag.d.ts.map +1 -1
- package/dist/unstable/cli/Flag.js.map +1 -1
- package/dist/unstable/cli/Param.d.ts +2 -2
- package/dist/unstable/cli/Param.d.ts.map +1 -1
- package/dist/unstable/cli/Param.js.map +1 -1
- package/dist/unstable/cli/Primitive.js.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.js +1 -0
- package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/unstable/cluster/Entity.d.ts.map +1 -1
- package/dist/unstable/cluster/Entity.js +5 -3
- package/dist/unstable/cluster/Entity.js.map +1 -1
- package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
- package/dist/unstable/cluster/Sharding.js +3 -1
- package/dist/unstable/cluster/Sharding.js.map +1 -1
- package/dist/unstable/cluster/internal/entityManager.js +3 -2
- package/dist/unstable/cluster/internal/entityManager.js.map +1 -1
- package/dist/unstable/cluster/internal/resourceMap.js +39 -14
- package/dist/unstable/cluster/internal/resourceMap.js.map +1 -1
- package/dist/unstable/encoding/Sse.d.ts +2 -2
- package/dist/unstable/encoding/Sse.d.ts.map +1 -1
- package/dist/unstable/http/HttpClientResponse.d.ts +1 -1
- package/dist/unstable/http/HttpClientResponse.d.ts.map +1 -1
- package/dist/unstable/http/HttpClientResponse.js.map +1 -1
- package/dist/unstable/http/HttpIncomingMessage.d.ts +2 -2
- package/dist/unstable/http/HttpIncomingMessage.d.ts.map +1 -1
- package/dist/unstable/http/HttpIncomingMessage.js.map +1 -1
- package/dist/unstable/http/HttpRouter.d.ts +4 -4
- package/dist/unstable/http/HttpRouter.d.ts.map +1 -1
- package/dist/unstable/http/HttpRouter.js.map +1 -1
- package/dist/unstable/http/HttpServerRequest.d.ts +8 -8
- package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerRequest.js.map +1 -1
- package/dist/unstable/http/HttpServerResponse.d.ts +1 -1
- package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerResponse.js.map +1 -1
- package/dist/unstable/http/Multipart.d.ts +2 -2
- package/dist/unstable/http/Multipart.d.ts.map +1 -1
- package/dist/unstable/http/Multipart.js.map +1 -1
- package/dist/unstable/httpapi/HttpApi.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApi.js +2 -4
- package/dist/unstable/httpapi/HttpApi.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +7 -7
- package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiSchema.d.ts +1 -1
- package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
- package/dist/unstable/reactivity/Atom.d.ts +4 -4
- package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
- package/dist/unstable/reactivity/Atom.js.map +1 -1
- package/package.json +1 -1
- package/src/Config.ts +1 -1
- package/src/Effect.ts +131 -0
- package/src/FileSystem.ts +13 -0
- package/src/Layer.ts +6 -6
- package/src/LayerMap.ts +1 -1
- package/src/LayerRef.ts +379 -0
- package/src/Schema.ts +80 -33
- package/src/SchemaParser.ts +2 -2
- package/src/internal/effect.ts +19 -0
- package/src/testing/TestSchema.ts +2 -2
- package/src/unstable/ai/Chat.ts +1 -1
- package/src/unstable/ai/LanguageModel.ts +3 -3
- package/src/unstable/cli/Argument.ts +14 -7
- package/src/unstable/cli/Flag.ts +6 -3
- package/src/unstable/cli/Param.ts +6 -3
- package/src/unstable/cli/Primitive.ts +2 -2
- package/src/unstable/cluster/ClusterWorkflowEngine.ts +1 -0
- package/src/unstable/cluster/Entity.ts +13 -14
- package/src/unstable/cluster/Sharding.ts +134 -131
- package/src/unstable/cluster/internal/entityManager.ts +11 -9
- package/src/unstable/cluster/internal/resourceMap.ts +59 -25
- package/src/unstable/encoding/Sse.ts +3 -3
- package/src/unstable/http/HttpClientResponse.ts +2 -3
- package/src/unstable/http/HttpIncomingMessage.ts +4 -5
- package/src/unstable/http/HttpRouter.ts +8 -10
- package/src/unstable/http/HttpServerRequest.ts +20 -19
- package/src/unstable/http/HttpServerResponse.ts +2 -2
- package/src/unstable/http/Multipart.ts +3 -3
- package/src/unstable/httpapi/HttpApi.ts +2 -4
- package/src/unstable/httpapi/HttpApiClient.ts +2 -2
- package/src/unstable/httpapi/HttpApiEndpoint.ts +7 -7
- package/src/unstable/httpapi/HttpApiSchema.ts +1 -1
- package/src/unstable/reactivity/Atom.ts +10 -7
package/src/unstable/cli/Flag.ts
CHANGED
|
@@ -1782,7 +1782,7 @@ export const withSchema: {
|
|
|
1782
1782
|
* @category schemas
|
|
1783
1783
|
* @since 4.0.0
|
|
1784
1784
|
*/
|
|
1785
|
-
<A, B>(schema: Schema.
|
|
1785
|
+
<A, B>(schema: Schema.ConstraintCodec<B, A, Environment, unknown>): (self: Flag<A>) => Flag<B>
|
|
1786
1786
|
/**
|
|
1787
1787
|
* Validates and transforms a flag value using a Schema codec.
|
|
1788
1788
|
*
|
|
@@ -1820,5 +1820,8 @@ export const withSchema: {
|
|
|
1820
1820
|
* @category schemas
|
|
1821
1821
|
* @since 4.0.0
|
|
1822
1822
|
*/
|
|
1823
|
-
<A, B>(self: Flag<A>, schema: Schema.
|
|
1824
|
-
} = dual(
|
|
1823
|
+
<A, B>(self: Flag<A>, schema: Schema.ConstraintCodec<B, A, Environment, unknown>): Flag<B>
|
|
1824
|
+
} = dual(
|
|
1825
|
+
2,
|
|
1826
|
+
<A, B>(self: Flag<A>, schema: Schema.ConstraintCodec<B, A, Environment, unknown>) => Param.withSchema(self, schema)
|
|
1827
|
+
)
|
|
@@ -2430,7 +2430,7 @@ export const withSchema: {
|
|
|
2430
2430
|
* @category combinators
|
|
2431
2431
|
* @since 4.0.0
|
|
2432
2432
|
*/
|
|
2433
|
-
<A, B>(schema: Schema.
|
|
2433
|
+
<A, B>(schema: Schema.ConstraintCodec<B, A, Environment, unknown>): <Kind extends ParamKind>(
|
|
2434
2434
|
self: Param<Kind, A>
|
|
2435
2435
|
) => Param<Kind, B>
|
|
2436
2436
|
/**
|
|
@@ -2455,10 +2455,13 @@ export const withSchema: {
|
|
|
2455
2455
|
* @category combinators
|
|
2456
2456
|
* @since 4.0.0
|
|
2457
2457
|
*/
|
|
2458
|
-
<Kind extends ParamKind, A, B>(
|
|
2458
|
+
<Kind extends ParamKind, A, B>(
|
|
2459
|
+
self: Param<Kind, A>,
|
|
2460
|
+
schema: Schema.ConstraintCodec<B, A, Environment, unknown>
|
|
2461
|
+
): Param<Kind, B>
|
|
2459
2462
|
} = dual(2, <Kind extends ParamKind, A, B>(
|
|
2460
2463
|
self: Param<Kind, A>,
|
|
2461
|
-
schema: Schema.
|
|
2464
|
+
schema: Schema.ConstraintCodec<B, A, Environment, unknown>
|
|
2462
2465
|
) => {
|
|
2463
2466
|
const decodeParam = Schema.decodeUnknownEffect(schema)
|
|
2464
2467
|
return mapEffect(self, (value) =>
|
|
@@ -105,9 +105,9 @@ const makePrimitive = <A>(
|
|
|
105
105
|
parse
|
|
106
106
|
})
|
|
107
107
|
|
|
108
|
-
const makeSchemaPrimitive = <T
|
|
108
|
+
const makeSchemaPrimitive = <T>(
|
|
109
109
|
tag: string,
|
|
110
|
-
schema: Schema.
|
|
110
|
+
schema: Schema.ConstraintDecoder<T, Environment>
|
|
111
111
|
): Primitive<T> => {
|
|
112
112
|
const toCodecStringTree = Schema.toCodecStringTree(schema)
|
|
113
113
|
const decode = Schema.decodeUnknownEffect(toCodecStringTree)
|
|
@@ -133,6 +133,7 @@ export const make = Effect.gen(function*() {
|
|
|
133
133
|
if (!entity) {
|
|
134
134
|
return yield* Effect.die(`Workflow ${workflowName} not registered`)
|
|
135
135
|
}
|
|
136
|
+
yield* RcMap.invalidate(clientsPartial, workflowName)
|
|
136
137
|
return yield* entity.client
|
|
137
138
|
}),
|
|
138
139
|
idleTimeToLive: "5 minutes"
|
|
@@ -618,11 +618,7 @@ export const makeTestClient: <Type extends string, Rpcs extends Rpc.Any, LA, LE,
|
|
|
618
618
|
Rpc.ServicesClient<Rpcs> | Rpc.ServicesServer<Rpcs> | Rpc.Middleware<Rpcs> | LR
|
|
619
619
|
>
|
|
620
620
|
readonly concurrency: number | "unbounded"
|
|
621
|
-
readonly build: Effect.Effect<
|
|
622
|
-
Context.Context<Rpc.ToHandler<Rpcs>>,
|
|
623
|
-
never,
|
|
624
|
-
Scope | CurrentAddress
|
|
625
|
-
>
|
|
621
|
+
readonly build: Effect.Effect<Context.Context<Rpc.ToHandler<Rpcs>>>
|
|
626
622
|
}>()
|
|
627
623
|
const sharding = shardingTag.of({
|
|
628
624
|
...({} as Sharding["Service"]),
|
|
@@ -631,13 +627,7 @@ export const makeTestClient: <Type extends string, Rpcs extends Rpc.Any, LA, LE,
|
|
|
631
627
|
entityMap.set(entity.type, {
|
|
632
628
|
context: context as any,
|
|
633
629
|
concurrency: options?.concurrency ?? 1,
|
|
634
|
-
build: entity.protocol.toHandlers(handlers as any)
|
|
635
|
-
Effect.provideContext(Context.mutate(context, (context) =>
|
|
636
|
-
context.pipe(
|
|
637
|
-
Context.add(CurrentRunnerAddress, runnerAddress),
|
|
638
|
-
Context.omit(Scope)
|
|
639
|
-
)))
|
|
640
|
-
) as any
|
|
630
|
+
build: entity.protocol.toHandlers(handlers as any) as any
|
|
641
631
|
})
|
|
642
632
|
return Effect.void
|
|
643
633
|
})
|
|
@@ -654,8 +644,15 @@ export const makeTestClient: <Type extends string, Rpcs extends Rpc.Any, LA, LE,
|
|
|
654
644
|
entityId: entityId as EntityId,
|
|
655
645
|
shardId: makeShardId(entityId)
|
|
656
646
|
})
|
|
647
|
+
const scope = yield* Effect.scope
|
|
648
|
+
const handlerContext = Context.mutate(entityEntry.context, (context) =>
|
|
649
|
+
context.pipe(
|
|
650
|
+
Context.add(CurrentRunnerAddress, runnerAddress),
|
|
651
|
+
Context.add(CurrentAddress, address),
|
|
652
|
+
Context.add(Scope, scope)
|
|
653
|
+
))
|
|
657
654
|
const handlers = yield* entityEntry.build.pipe(
|
|
658
|
-
Effect.
|
|
655
|
+
Effect.setContext(handlerContext as Context.Context<any>)
|
|
659
656
|
)
|
|
660
657
|
|
|
661
658
|
// oxlint-disable-next-line prefer-const
|
|
@@ -665,7 +662,9 @@ export const makeTestClient: <Type extends string, Rpcs extends Rpc.Any, LA, LE,
|
|
|
665
662
|
onFromServer(response) {
|
|
666
663
|
return client.write(response)
|
|
667
664
|
}
|
|
668
|
-
}).pipe(
|
|
665
|
+
}).pipe(
|
|
666
|
+
Effect.setContext(Context.merge(handlerContext, handlers))
|
|
667
|
+
)
|
|
669
668
|
|
|
670
669
|
client = yield* RpcClient.makeNoSerialization(entity.protocol, {
|
|
671
670
|
supportsAck: true,
|
|
@@ -1034,148 +1034,151 @@ const make = Effect.gen(function*() {
|
|
|
1034
1034
|
MailboxFull | AlreadyProcessingMessage
|
|
1035
1035
|
>,
|
|
1036
1036
|
never
|
|
1037
|
-
> = yield* ResourceMap.make(
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
rpc.annotations,
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1037
|
+
> = yield* ResourceMap.make(
|
|
1038
|
+
Effect.fnUntraced(function*(entity: Entity<string, any>) {
|
|
1039
|
+
const client = yield* RpcClient.makeNoSerialization(entity.protocol, {
|
|
1040
|
+
spanPrefix: `${entity.type}.client`,
|
|
1041
|
+
disableTracing: !Context.get(entity.protocol.annotations, ClusterSchema.ClientTracingEnabled),
|
|
1042
|
+
supportsAck: true,
|
|
1043
|
+
generateRequestId: () => RequestId(snowflakeGen.nextUnsafe()),
|
|
1044
|
+
flatten: true,
|
|
1045
|
+
onFromClient(options): Effect.Effect<
|
|
1046
|
+
void,
|
|
1047
|
+
MailboxFull | AlreadyProcessingMessage | PersistenceError
|
|
1048
|
+
> {
|
|
1049
|
+
const address = Context.getUnsafe(options.context, ClientAddressTag)
|
|
1050
|
+
switch (options.message._tag) {
|
|
1051
|
+
case "Request": {
|
|
1052
|
+
const fiber = Fiber.getCurrent()!
|
|
1053
|
+
const id = Snowflake.Snowflake(options.message.id)
|
|
1054
|
+
const rpc = entity.protocol.requests.get(options.message.tag)!
|
|
1055
|
+
let respond: (reply: Reply.Reply<any>) => Effect.Effect<void>
|
|
1056
|
+
const envelope = Envelope.makeRequest<any>({
|
|
1057
|
+
requestId: id,
|
|
1058
|
+
address,
|
|
1059
|
+
tag: options.message.tag,
|
|
1060
|
+
payload: options.message.payload,
|
|
1061
|
+
headers: options.message.headers,
|
|
1062
|
+
traceId: options.message.traceId,
|
|
1063
|
+
spanId: options.message.spanId,
|
|
1064
|
+
sampled: options.message.sampled
|
|
1065
|
+
})
|
|
1066
|
+
const message = new Message.OutgoingRequest({
|
|
1067
|
+
envelope,
|
|
1068
|
+
lastReceivedReply: Option.none(),
|
|
1069
|
+
rpc,
|
|
1070
|
+
context: fiber.context as Context.Context<any>,
|
|
1071
|
+
respond: (reply) => respond(reply),
|
|
1072
|
+
annotations: Context.get(rpc.annotations, ClusterSchema.Dynamic)(
|
|
1073
|
+
rpc.annotations,
|
|
1074
|
+
envelope as any
|
|
1075
|
+
)
|
|
1076
|
+
})
|
|
1077
|
+
if (!options.discard) {
|
|
1078
|
+
const entry: ClientRequestEntry = {
|
|
1079
|
+
rpc: rpc as any,
|
|
1080
|
+
context: fiber.currentContext,
|
|
1081
|
+
message
|
|
1082
|
+
}
|
|
1083
|
+
clientRequests.set(id, entry)
|
|
1084
|
+
respond = makeClientRespond(entry, client.write)
|
|
1085
|
+
} else {
|
|
1086
|
+
respond = clientRespondDiscard
|
|
1081
1087
|
}
|
|
1082
|
-
|
|
1083
|
-
respond = makeClientRespond(entry, client.write)
|
|
1084
|
-
} else {
|
|
1085
|
-
respond = clientRespondDiscard
|
|
1088
|
+
return sendOutgoing(message, options.discard)
|
|
1086
1089
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1090
|
+
case "Ack": {
|
|
1091
|
+
const requestId = Snowflake.Snowflake(options.message.requestId)
|
|
1092
|
+
const entry = clientRequests.get(requestId)
|
|
1093
|
+
if (!entry) return Effect.void
|
|
1094
|
+
return sendOutgoing(
|
|
1095
|
+
new Message.OutgoingEnvelope({
|
|
1096
|
+
envelope: new Envelope.AckChunk({
|
|
1097
|
+
id: snowflakeGen.nextUnsafe(),
|
|
1098
|
+
address,
|
|
1099
|
+
requestId,
|
|
1100
|
+
replyId: entry.lastChunkId!
|
|
1101
|
+
}),
|
|
1102
|
+
rpc: entry.rpc
|
|
1100
1103
|
}),
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
false
|
|
1104
|
-
)
|
|
1105
|
-
}
|
|
1106
|
-
case "Interrupt": {
|
|
1107
|
-
const requestId = Snowflake.Snowflake(options.message.requestId)
|
|
1108
|
-
const entry = clientRequests.get(requestId)!
|
|
1109
|
-
if (!entry) return Effect.void
|
|
1110
|
-
clientRequests.delete(requestId)
|
|
1111
|
-
if (ClusterSchema.isUninterruptibleForClient(entry.message.annotations)) {
|
|
1112
|
-
return Effect.void
|
|
1113
|
-
}
|
|
1114
|
-
// for durable messages, we ignore interrupts on shutdown or as a
|
|
1115
|
-
// result of a shard being resassigned
|
|
1116
|
-
const isTransientInterrupt = MutableRef.get(isShutdown) ||
|
|
1117
|
-
options.message.interruptors.some((id) => internalInterruptors.has(id))
|
|
1118
|
-
if (isTransientInterrupt && Context.get(entry.message.annotations, Persisted)) {
|
|
1119
|
-
return Effect.void
|
|
1104
|
+
false
|
|
1105
|
+
)
|
|
1120
1106
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1107
|
+
case "Interrupt": {
|
|
1108
|
+
const requestId = Snowflake.Snowflake(options.message.requestId)
|
|
1109
|
+
const entry = clientRequests.get(requestId)!
|
|
1110
|
+
if (!entry) return Effect.void
|
|
1111
|
+
clientRequests.delete(requestId)
|
|
1112
|
+
if (ClusterSchema.isUninterruptibleForClient(entry.message.annotations)) {
|
|
1113
|
+
return Effect.void
|
|
1114
|
+
}
|
|
1115
|
+
// for durable messages, we ignore interrupts on shutdown or as a
|
|
1116
|
+
// result of a shard being resassigned
|
|
1117
|
+
const isTransientInterrupt = MutableRef.get(isShutdown) ||
|
|
1118
|
+
options.message.interruptors.some((id) => internalInterruptors.has(id))
|
|
1119
|
+
if (isTransientInterrupt && Context.get(entry.message.annotations, Persisted)) {
|
|
1120
|
+
return Effect.void
|
|
1121
|
+
}
|
|
1122
|
+
return Effect.ignore(sendOutgoing(
|
|
1123
|
+
new Message.OutgoingEnvelope({
|
|
1124
|
+
envelope: new Envelope.Interrupt({
|
|
1125
|
+
id: snowflakeGen.nextUnsafe(),
|
|
1126
|
+
address,
|
|
1127
|
+
requestId
|
|
1128
|
+
}),
|
|
1129
|
+
rpc: entry.rpc
|
|
1127
1130
|
}),
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
))
|
|
1131
|
+
false,
|
|
1132
|
+
3
|
|
1133
|
+
))
|
|
1134
|
+
}
|
|
1133
1135
|
}
|
|
1136
|
+
return Effect.void
|
|
1134
1137
|
}
|
|
1135
|
-
return Effect.void
|
|
1136
|
-
}
|
|
1137
|
-
})
|
|
1138
|
-
|
|
1139
|
-
yield* Scope.addFinalizer(
|
|
1140
|
-
yield* Effect.scope,
|
|
1141
|
-
Effect.withFiber((fiber) => {
|
|
1142
|
-
internalInterruptors.add(fiber.id)
|
|
1143
|
-
return Effect.void
|
|
1144
1138
|
})
|
|
1145
|
-
)
|
|
1146
1139
|
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
entityType: entity.type
|
|
1153
|
-
}))
|
|
1154
|
-
const clientFn = function(tag: string, payload: any, options?: {
|
|
1155
|
-
readonly context?: Context.Context<never>
|
|
1156
|
-
}) {
|
|
1157
|
-
const context = options?.context ? Context.merge(options.context, address) : address
|
|
1158
|
-
return client.client(tag, payload, {
|
|
1159
|
-
...options,
|
|
1160
|
-
context
|
|
1140
|
+
yield* Scope.addFinalizer(
|
|
1141
|
+
yield* Effect.scope,
|
|
1142
|
+
Effect.withFiber((fiber) => {
|
|
1143
|
+
internalInterruptors.add(fiber.id)
|
|
1144
|
+
return Effect.void
|
|
1161
1145
|
})
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
return
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1146
|
+
)
|
|
1147
|
+
|
|
1148
|
+
return (entityId: string) => {
|
|
1149
|
+
const id = makeEntityId(entityId)
|
|
1150
|
+
const address = ClientAddressTag.context(makeEntityAddress({
|
|
1151
|
+
shardId: getShardId(id, entity.getShardGroup(entityId as EntityId)),
|
|
1152
|
+
entityId: id,
|
|
1153
|
+
entityType: entity.type
|
|
1154
|
+
}))
|
|
1155
|
+
const clientFn = function(tag: string, payload: any, options?: {
|
|
1156
|
+
readonly context?: Context.Context<never>
|
|
1157
|
+
}) {
|
|
1158
|
+
const context = options?.context ? Context.merge(options.context, address) : address
|
|
1159
|
+
return client.client(tag, payload, {
|
|
1160
|
+
...options,
|
|
1161
|
+
context
|
|
1162
|
+
})
|
|
1175
1163
|
}
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1164
|
+
const proxyClient: any = {}
|
|
1165
|
+
return new Proxy(proxyClient, {
|
|
1166
|
+
has(_, p) {
|
|
1167
|
+
return entity.protocol.requests.has(p as string)
|
|
1168
|
+
},
|
|
1169
|
+
get(target, p) {
|
|
1170
|
+
if (p in target) {
|
|
1171
|
+
return target[p]
|
|
1172
|
+
} else if (!entity.protocol.requests.has(p as string)) {
|
|
1173
|
+
return undefined
|
|
1174
|
+
}
|
|
1175
|
+
return target[p] = (payload: any, options?: {}) => clientFn(p as string, payload, options)
|
|
1176
|
+
}
|
|
1177
|
+
})
|
|
1178
|
+
}
|
|
1179
|
+
}),
|
|
1180
|
+
{ referential: true }
|
|
1181
|
+
)
|
|
1179
1182
|
|
|
1180
1183
|
const makeClient = <Type extends string, Rpcs extends Rpc.Any>(entity: Entity<Type, Rpcs>): Effect.Effect<
|
|
1181
1184
|
(
|
|
@@ -155,16 +155,18 @@ export const make = Effect.fnUntraced(function*<
|
|
|
155
155
|
Effect.fnUntraced(function*(scope) {
|
|
156
156
|
let isShuttingDown = false
|
|
157
157
|
|
|
158
|
+
const handlerContext = Context.mutate(context, (context) =>
|
|
159
|
+
context.pipe(
|
|
160
|
+
Context.add(CurrentAddress, address),
|
|
161
|
+
Context.add(CurrentRunnerAddress, options.runnerAddress),
|
|
162
|
+
Context.add(KeepAliveLatch, keepAliveLatch),
|
|
163
|
+
Context.add(Scope.Scope, scope),
|
|
164
|
+
Context.add(CurrentLogAnnotations, {})
|
|
165
|
+
))
|
|
166
|
+
|
|
158
167
|
// Initiate the behavior for the entity
|
|
159
168
|
const handlers = yield* (entity.protocol.toHandlers(buildHandlers as any).pipe(
|
|
160
|
-
Effect.
|
|
161
|
-
Effect.provideContext(Context.mutate(context, (context) =>
|
|
162
|
-
context.pipe(
|
|
163
|
-
Context.add(CurrentAddress, address),
|
|
164
|
-
Context.add(CurrentRunnerAddress, options.runnerAddress),
|
|
165
|
-
Context.add(KeepAliveLatch, keepAliveLatch),
|
|
166
|
-
Context.add(Scope.Scope, scope)
|
|
167
|
-
))),
|
|
169
|
+
Effect.setContext(handlerContext as Context.Context<any>),
|
|
168
170
|
Effect.sandbox,
|
|
169
171
|
Effect.tapError((cause) => Effect.logError("Defect building entity handlers", cause)),
|
|
170
172
|
Effect.retry(defectRetryPolicy)
|
|
@@ -280,7 +282,7 @@ export const make = Effect.fnUntraced(function*<
|
|
|
280
282
|
}
|
|
281
283
|
}).pipe(
|
|
282
284
|
Scope.provide(scope),
|
|
283
|
-
Effect.
|
|
285
|
+
Effect.setContext(Context.merge(handlerContext, handlers))
|
|
284
286
|
)
|
|
285
287
|
|
|
286
288
|
yield* Scope.addFinalizer(
|
|
@@ -4,23 +4,16 @@ import * as Effect from "../../../Effect.ts"
|
|
|
4
4
|
import * as Exit from "../../../Exit.ts"
|
|
5
5
|
import * as MutableHashMap from "../../../MutableHashMap.ts"
|
|
6
6
|
import * as MutableRef from "../../../MutableRef.ts"
|
|
7
|
-
import * as Option from "../../../Option.ts"
|
|
8
7
|
import * as Scope from "../../../Scope.ts"
|
|
9
8
|
|
|
10
9
|
/** @internal */
|
|
11
10
|
export class ResourceMap<K, A, E> {
|
|
12
11
|
readonly lookup: (key: K, scope: Scope.Scope) => Effect.Effect<A, E>
|
|
13
|
-
readonly entries:
|
|
14
|
-
readonly scope: Scope.Closeable
|
|
15
|
-
readonly deferred: Deferred.Deferred<A, E>
|
|
16
|
-
}>
|
|
12
|
+
readonly entries: BackingMap<K, A, E>
|
|
17
13
|
readonly isClosed: MutableRef.MutableRef<boolean>
|
|
18
14
|
constructor(
|
|
19
15
|
lookup: (key: K, scope: Scope.Scope) => Effect.Effect<A, E>,
|
|
20
|
-
entries:
|
|
21
|
-
readonly scope: Scope.Closeable
|
|
22
|
-
readonly deferred: Deferred.Deferred<A, E>
|
|
23
|
-
}>,
|
|
16
|
+
entries: BackingMap<K, A, E>,
|
|
24
17
|
isClosed: MutableRef.MutableRef<boolean>
|
|
25
18
|
) {
|
|
26
19
|
this.lookup = lookup
|
|
@@ -28,22 +21,29 @@ export class ResourceMap<K, A, E> {
|
|
|
28
21
|
this.isClosed = isClosed
|
|
29
22
|
}
|
|
30
23
|
|
|
31
|
-
static make = Effect.fnUntraced(function*<K, A, E, R>(lookup: (key: K) => Effect.Effect<A, E, R
|
|
24
|
+
static make = Effect.fnUntraced(function*<K, A, E, R>(lookup: (key: K) => Effect.Effect<A, E, R>, options?: {
|
|
25
|
+
readonly referential?: boolean | undefined
|
|
26
|
+
}) {
|
|
32
27
|
const scope = yield* Effect.scope
|
|
33
28
|
const services = yield* Effect.context<R>()
|
|
34
29
|
const isClosed = MutableRef.make(false)
|
|
35
30
|
|
|
36
|
-
const entries
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
const entries: BackingMap<K, A, E> = options?.referential ?
|
|
32
|
+
{
|
|
33
|
+
_tag: "Referential",
|
|
34
|
+
map: new Map()
|
|
35
|
+
} :
|
|
36
|
+
{
|
|
37
|
+
_tag: "Equal",
|
|
38
|
+
map: MutableHashMap.empty()
|
|
39
|
+
}
|
|
40
40
|
|
|
41
41
|
yield* Scope.addFinalizerExit(
|
|
42
42
|
scope,
|
|
43
43
|
(exit) => {
|
|
44
44
|
MutableRef.set(isClosed, true)
|
|
45
|
-
return Effect.forEach(entries, ([key, { scope }]) => {
|
|
46
|
-
|
|
45
|
+
return Effect.forEach(entries.map, ([key, { scope }]) => {
|
|
46
|
+
backingDelete(entries, key)
|
|
47
47
|
return Effect.exit(Scope.close(scope, exit))
|
|
48
48
|
}, { concurrency: "unbounded", discard: true })
|
|
49
49
|
}
|
|
@@ -61,18 +61,18 @@ export class ResourceMap<K, A, E> {
|
|
|
61
61
|
if (MutableRef.get(this.isClosed)) {
|
|
62
62
|
return Effect.interrupt
|
|
63
63
|
}
|
|
64
|
-
const existing =
|
|
65
|
-
if (
|
|
66
|
-
return Deferred.await(existing.
|
|
64
|
+
const existing = backingGet(this.entries, key)
|
|
65
|
+
if (existing) {
|
|
66
|
+
return Deferred.await(existing.deferred)
|
|
67
67
|
}
|
|
68
68
|
const scope = Effect.runSync(Scope.make())
|
|
69
69
|
const deferred = Deferred.makeUnsafe<A, E>()
|
|
70
|
-
|
|
70
|
+
backingSet(this.entries, key, { scope, deferred })
|
|
71
71
|
return Effect.onExit(this.lookup(key, scope), (exit) => {
|
|
72
72
|
if (exit._tag === "Success") {
|
|
73
73
|
return Deferred.done(deferred, exit)
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
backingDelete(this.entries, key)
|
|
76
76
|
return Deferred.done(deferred, exit)
|
|
77
77
|
})
|
|
78
78
|
})
|
|
@@ -80,12 +80,12 @@ export class ResourceMap<K, A, E> {
|
|
|
80
80
|
|
|
81
81
|
remove(key: K): Effect.Effect<void> {
|
|
82
82
|
return Effect.suspend(() => {
|
|
83
|
-
const entry =
|
|
84
|
-
if (
|
|
83
|
+
const entry = backingGet(this.entries, key)
|
|
84
|
+
if (!entry) {
|
|
85
85
|
return Effect.void
|
|
86
86
|
}
|
|
87
|
-
|
|
88
|
-
return Scope.close(entry.
|
|
87
|
+
backingDelete(this.entries, key)
|
|
88
|
+
return Scope.close(entry.scope, Exit.void)
|
|
89
89
|
})
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -98,3 +98,37 @@ export class ResourceMap<K, A, E> {
|
|
|
98
98
|
}))
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
+
|
|
102
|
+
type BackingMap<K, A, E> = {
|
|
103
|
+
readonly _tag: "Equal"
|
|
104
|
+
readonly map: MutableHashMap.MutableHashMap<K, Entry<A, E>>
|
|
105
|
+
} | {
|
|
106
|
+
readonly _tag: "Referential"
|
|
107
|
+
readonly map: Map<K, Entry<A, E>>
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
type Entry<A, E> = {
|
|
111
|
+
readonly scope: Scope.Closeable
|
|
112
|
+
readonly deferred: Deferred.Deferred<A, E>
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const backingGet = <K, A, E>(map: BackingMap<K, A, E>, key: K): Entry<A, E> | undefined => {
|
|
116
|
+
if (map._tag === "Equal") {
|
|
117
|
+
return MutableHashMap.get(map.map, key).valueOrUndefined
|
|
118
|
+
}
|
|
119
|
+
return map.map.get(key)
|
|
120
|
+
}
|
|
121
|
+
const backingSet = <K, A, E>(map: BackingMap<K, A, E>, key: K, entry: Entry<A, E>): void => {
|
|
122
|
+
if (map._tag === "Equal") {
|
|
123
|
+
MutableHashMap.set(map.map, key, entry)
|
|
124
|
+
} else {
|
|
125
|
+
map.map.set(key, entry)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const backingDelete = <K, A, E>(map: BackingMap<K, A, E>, key: K): void => {
|
|
129
|
+
if (map._tag === "Equal") {
|
|
130
|
+
MutableHashMap.remove(map.map, key)
|
|
131
|
+
} else {
|
|
132
|
+
map.map.delete(key)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -80,15 +80,15 @@ export const decode = <IE, Done>(): Channel.Channel<
|
|
|
80
80
|
* @since 4.0.0
|
|
81
81
|
*/
|
|
82
82
|
export interface EventCodec extends
|
|
83
|
-
Schema.
|
|
83
|
+
Schema.ConstraintCodec<
|
|
84
84
|
any,
|
|
85
85
|
{
|
|
86
86
|
readonly id?: string | undefined
|
|
87
87
|
readonly event?: string | undefined
|
|
88
88
|
readonly data: string
|
|
89
89
|
},
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
unknown,
|
|
91
|
+
unknown
|
|
92
92
|
>
|
|
93
93
|
{}
|
|
94
94
|
|
|
@@ -93,10 +93,9 @@ export const schemaJson = <
|
|
|
93
93
|
readonly headers?: Readonly<Record<string, string | undefined>> | undefined
|
|
94
94
|
readonly body?: unknown
|
|
95
95
|
},
|
|
96
|
-
RD
|
|
97
|
-
RE
|
|
96
|
+
RD
|
|
98
97
|
>(
|
|
99
|
-
schema: Schema.
|
|
98
|
+
schema: Schema.ConstraintCodec<A, I, RD, unknown>,
|
|
100
99
|
options?: ParseOptions | undefined
|
|
101
100
|
) => {
|
|
102
101
|
const decode = Schema.decodeEffect(Schema.toCodecJson(schema).annotate({ options }))
|
|
@@ -78,10 +78,9 @@ export const schemaBodyJson = <S extends Schema.Constraint>(schema: S, options?:
|
|
|
78
78
|
export const schemaBodyUrlParams = <
|
|
79
79
|
A,
|
|
80
80
|
I extends Readonly<Record<string, string | ReadonlyArray<string> | undefined>>,
|
|
81
|
-
RD
|
|
82
|
-
RE
|
|
81
|
+
RD
|
|
83
82
|
>(
|
|
84
|
-
schema: Schema.
|
|
83
|
+
schema: Schema.ConstraintCodec<A, I, RD, unknown>,
|
|
85
84
|
options?: ParseOptions | undefined
|
|
86
85
|
) => {
|
|
87
86
|
const decode = UrlParams.schemaRecord.pipe(
|
|
@@ -98,8 +97,8 @@ export const schemaBodyUrlParams = <
|
|
|
98
97
|
* @category schemas
|
|
99
98
|
* @since 4.0.0
|
|
100
99
|
*/
|
|
101
|
-
export const schemaHeaders = <A, I extends Readonly<Record<string, string | undefined>>, RD
|
|
102
|
-
schema: Schema.
|
|
100
|
+
export const schemaHeaders = <A, I extends Readonly<Record<string, string | undefined>>, RD>(
|
|
101
|
+
schema: Schema.ConstraintCodec<A, I, RD, unknown>,
|
|
103
102
|
options?: ParseOptions | undefined
|
|
104
103
|
) => {
|
|
105
104
|
const decode = Schema.decodeUnknownEffect(schema)
|