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.
Files changed (124) hide show
  1. package/dist/Config.d.ts +1 -1
  2. package/dist/Config.d.ts.map +1 -1
  3. package/dist/Config.js.map +1 -1
  4. package/dist/Effect.d.ts +130 -0
  5. package/dist/Effect.d.ts.map +1 -1
  6. package/dist/Effect.js +43 -0
  7. package/dist/Effect.js.map +1 -1
  8. package/dist/FileSystem.d.ts +7 -0
  9. package/dist/FileSystem.d.ts.map +1 -1
  10. package/dist/FileSystem.js +3 -0
  11. package/dist/FileSystem.js.map +1 -1
  12. package/dist/Layer.d.ts +1 -1
  13. package/dist/Layer.d.ts.map +1 -1
  14. package/dist/Layer.js +6 -3
  15. package/dist/Layer.js.map +1 -1
  16. package/dist/LayerMap.js +1 -1
  17. package/dist/LayerMap.js.map +1 -1
  18. package/dist/LayerRef.d.ts +252 -0
  19. package/dist/LayerRef.d.ts.map +1 -0
  20. package/dist/LayerRef.js +171 -0
  21. package/dist/LayerRef.js.map +1 -0
  22. package/dist/Schema.d.ts +74 -30
  23. package/dist/Schema.d.ts.map +1 -1
  24. package/dist/Schema.js.map +1 -1
  25. package/dist/SchemaParser.d.ts +1 -1
  26. package/dist/SchemaParser.d.ts.map +1 -1
  27. package/dist/SchemaParser.js.map +1 -1
  28. package/dist/internal/effect.js +2 -0
  29. package/dist/internal/effect.js.map +1 -1
  30. package/dist/testing/TestSchema.d.ts +2 -2
  31. package/dist/testing/TestSchema.d.ts.map +1 -1
  32. package/dist/testing/TestSchema.js.map +1 -1
  33. package/dist/unstable/ai/Chat.d.ts +1 -1
  34. package/dist/unstable/ai/Chat.d.ts.map +1 -1
  35. package/dist/unstable/ai/LanguageModel.d.ts +2 -2
  36. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  37. package/dist/unstable/cli/Argument.d.ts +2 -2
  38. package/dist/unstable/cli/Argument.d.ts.map +1 -1
  39. package/dist/unstable/cli/Argument.js.map +1 -1
  40. package/dist/unstable/cli/Flag.d.ts +2 -2
  41. package/dist/unstable/cli/Flag.d.ts.map +1 -1
  42. package/dist/unstable/cli/Flag.js.map +1 -1
  43. package/dist/unstable/cli/Param.d.ts +2 -2
  44. package/dist/unstable/cli/Param.d.ts.map +1 -1
  45. package/dist/unstable/cli/Param.js.map +1 -1
  46. package/dist/unstable/cli/Primitive.js.map +1 -1
  47. package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  48. package/dist/unstable/cluster/ClusterWorkflowEngine.js +1 -0
  49. package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
  50. package/dist/unstable/cluster/Entity.d.ts.map +1 -1
  51. package/dist/unstable/cluster/Entity.js +5 -3
  52. package/dist/unstable/cluster/Entity.js.map +1 -1
  53. package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
  54. package/dist/unstable/cluster/Sharding.js +3 -1
  55. package/dist/unstable/cluster/Sharding.js.map +1 -1
  56. package/dist/unstable/cluster/internal/entityManager.js +3 -2
  57. package/dist/unstable/cluster/internal/entityManager.js.map +1 -1
  58. package/dist/unstable/cluster/internal/resourceMap.js +39 -14
  59. package/dist/unstable/cluster/internal/resourceMap.js.map +1 -1
  60. package/dist/unstable/encoding/Sse.d.ts +2 -2
  61. package/dist/unstable/encoding/Sse.d.ts.map +1 -1
  62. package/dist/unstable/http/HttpClientResponse.d.ts +1 -1
  63. package/dist/unstable/http/HttpClientResponse.d.ts.map +1 -1
  64. package/dist/unstable/http/HttpClientResponse.js.map +1 -1
  65. package/dist/unstable/http/HttpIncomingMessage.d.ts +2 -2
  66. package/dist/unstable/http/HttpIncomingMessage.d.ts.map +1 -1
  67. package/dist/unstable/http/HttpIncomingMessage.js.map +1 -1
  68. package/dist/unstable/http/HttpRouter.d.ts +4 -4
  69. package/dist/unstable/http/HttpRouter.d.ts.map +1 -1
  70. package/dist/unstable/http/HttpRouter.js.map +1 -1
  71. package/dist/unstable/http/HttpServerRequest.d.ts +8 -8
  72. package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
  73. package/dist/unstable/http/HttpServerRequest.js.map +1 -1
  74. package/dist/unstable/http/HttpServerResponse.d.ts +1 -1
  75. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  76. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  77. package/dist/unstable/http/Multipart.d.ts +2 -2
  78. package/dist/unstable/http/Multipart.d.ts.map +1 -1
  79. package/dist/unstable/http/Multipart.js.map +1 -1
  80. package/dist/unstable/httpapi/HttpApi.d.ts.map +1 -1
  81. package/dist/unstable/httpapi/HttpApi.js +2 -4
  82. package/dist/unstable/httpapi/HttpApi.js.map +1 -1
  83. package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
  84. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +7 -7
  85. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
  86. package/dist/unstable/httpapi/HttpApiSchema.d.ts +1 -1
  87. package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
  88. package/dist/unstable/reactivity/Atom.d.ts +4 -4
  89. package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
  90. package/dist/unstable/reactivity/Atom.js.map +1 -1
  91. package/package.json +1 -1
  92. package/src/Config.ts +1 -1
  93. package/src/Effect.ts +131 -0
  94. package/src/FileSystem.ts +13 -0
  95. package/src/Layer.ts +6 -6
  96. package/src/LayerMap.ts +1 -1
  97. package/src/LayerRef.ts +379 -0
  98. package/src/Schema.ts +80 -33
  99. package/src/SchemaParser.ts +2 -2
  100. package/src/internal/effect.ts +19 -0
  101. package/src/testing/TestSchema.ts +2 -2
  102. package/src/unstable/ai/Chat.ts +1 -1
  103. package/src/unstable/ai/LanguageModel.ts +3 -3
  104. package/src/unstable/cli/Argument.ts +14 -7
  105. package/src/unstable/cli/Flag.ts +6 -3
  106. package/src/unstable/cli/Param.ts +6 -3
  107. package/src/unstable/cli/Primitive.ts +2 -2
  108. package/src/unstable/cluster/ClusterWorkflowEngine.ts +1 -0
  109. package/src/unstable/cluster/Entity.ts +13 -14
  110. package/src/unstable/cluster/Sharding.ts +134 -131
  111. package/src/unstable/cluster/internal/entityManager.ts +11 -9
  112. package/src/unstable/cluster/internal/resourceMap.ts +59 -25
  113. package/src/unstable/encoding/Sse.ts +3 -3
  114. package/src/unstable/http/HttpClientResponse.ts +2 -3
  115. package/src/unstable/http/HttpIncomingMessage.ts +4 -5
  116. package/src/unstable/http/HttpRouter.ts +8 -10
  117. package/src/unstable/http/HttpServerRequest.ts +20 -19
  118. package/src/unstable/http/HttpServerResponse.ts +2 -2
  119. package/src/unstable/http/Multipart.ts +3 -3
  120. package/src/unstable/httpapi/HttpApi.ts +2 -4
  121. package/src/unstable/httpapi/HttpApiClient.ts +2 -2
  122. package/src/unstable/httpapi/HttpApiEndpoint.ts +7 -7
  123. package/src/unstable/httpapi/HttpApiSchema.ts +1 -1
  124. package/src/unstable/reactivity/Atom.ts +10 -7
@@ -1782,7 +1782,7 @@ export const withSchema: {
1782
1782
  * @category schemas
1783
1783
  * @since 4.0.0
1784
1784
  */
1785
- <A, B>(schema: Schema.Codec<B, A, Environment, Environment>): (self: Flag<A>) => Flag<B>
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.Codec<B, A, Environment, Environment>): Flag<B>
1824
- } = dual(2, <A, B>(self: Flag<A>, schema: Schema.Codec<B, A>) => Param.withSchema(self, schema))
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.Codec<B, A, Environment, Environment>): <Kind extends ParamKind>(
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>(self: Param<Kind, A>, schema: Schema.Codec<B, A, Environment, Environment>): Param<Kind, 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.Codec<B, A>
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, E>(
108
+ const makeSchemaPrimitive = <T>(
109
109
  tag: string,
110
- schema: Schema.Codec<T, E, Environment, Environment>
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).pipe(
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.provideService(CurrentAddress, address)
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(Effect.provide(handlers))
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(Effect.fnUntraced(function*(entity: Entity<string, any>) {
1038
- const client = yield* RpcClient.makeNoSerialization(entity.protocol, {
1039
- spanPrefix: `${entity.type}.client`,
1040
- disableTracing: !Context.get(entity.protocol.annotations, ClusterSchema.ClientTracingEnabled),
1041
- supportsAck: true,
1042
- generateRequestId: () => RequestId(snowflakeGen.nextUnsafe()),
1043
- flatten: true,
1044
- onFromClient(options): Effect.Effect<
1045
- void,
1046
- MailboxFull | AlreadyProcessingMessage | PersistenceError
1047
- > {
1048
- const address = Context.getUnsafe(options.context, ClientAddressTag)
1049
- switch (options.message._tag) {
1050
- case "Request": {
1051
- const fiber = Fiber.getCurrent()!
1052
- const id = Snowflake.Snowflake(options.message.id)
1053
- const rpc = entity.protocol.requests.get(options.message.tag)!
1054
- let respond: (reply: Reply.Reply<any>) => Effect.Effect<void>
1055
- const envelope = Envelope.makeRequest<any>({
1056
- requestId: id,
1057
- address,
1058
- tag: options.message.tag,
1059
- payload: options.message.payload,
1060
- headers: options.message.headers,
1061
- traceId: options.message.traceId,
1062
- spanId: options.message.spanId,
1063
- sampled: options.message.sampled
1064
- })
1065
- const message = new Message.OutgoingRequest({
1066
- envelope,
1067
- lastReceivedReply: Option.none(),
1068
- rpc,
1069
- context: fiber.context as Context.Context<any>,
1070
- respond: (reply) => respond(reply),
1071
- annotations: Context.get(rpc.annotations, ClusterSchema.Dynamic)(
1072
- rpc.annotations,
1073
- envelope as any
1074
- )
1075
- })
1076
- if (!options.discard) {
1077
- const entry: ClientRequestEntry = {
1078
- rpc: rpc as any,
1079
- context: fiber.currentContext,
1080
- message
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
- clientRequests.set(id, entry)
1083
- respond = makeClientRespond(entry, client.write)
1084
- } else {
1085
- respond = clientRespondDiscard
1088
+ return sendOutgoing(message, options.discard)
1086
1089
  }
1087
- return sendOutgoing(message, options.discard)
1088
- }
1089
- case "Ack": {
1090
- const requestId = Snowflake.Snowflake(options.message.requestId)
1091
- const entry = clientRequests.get(requestId)
1092
- if (!entry) return Effect.void
1093
- return sendOutgoing(
1094
- new Message.OutgoingEnvelope({
1095
- envelope: new Envelope.AckChunk({
1096
- id: snowflakeGen.nextUnsafe(),
1097
- address,
1098
- requestId,
1099
- replyId: entry.lastChunkId!
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
- rpc: entry.rpc
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
- return Effect.ignore(sendOutgoing(
1122
- new Message.OutgoingEnvelope({
1123
- envelope: new Envelope.Interrupt({
1124
- id: snowflakeGen.nextUnsafe(),
1125
- address,
1126
- requestId
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
- rpc: entry.rpc
1129
- }),
1130
- false,
1131
- 3
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
- return (entityId: string) => {
1148
- const id = makeEntityId(entityId)
1149
- const address = ClientAddressTag.context(makeEntityAddress({
1150
- shardId: getShardId(id, entity.getShardGroup(entityId as EntityId)),
1151
- entityId: id,
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
- const proxyClient: any = {}
1164
- return new Proxy(proxyClient, {
1165
- has(_, p) {
1166
- return entity.protocol.requests.has(p as string)
1167
- },
1168
- get(target, p) {
1169
- if (p in target) {
1170
- return target[p]
1171
- } else if (!entity.protocol.requests.has(p as string)) {
1172
- return undefined
1173
- }
1174
- return target[p] = (payload: any, options?: {}) => clientFn(p as string, payload, options)
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.provideService(CurrentLogAnnotations, {}),
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.provideContext(handlers)
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: MutableHashMap.MutableHashMap<K, {
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: MutableHashMap.MutableHashMap<K, {
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 = MutableHashMap.empty<K, {
37
- scope: Scope.Closeable
38
- deferred: Deferred.Deferred<A, E>
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
- MutableHashMap.remove(entries, key)
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 = MutableHashMap.get(this.entries, key)
65
- if (Option.isSome(existing)) {
66
- return Deferred.await(existing.value.deferred)
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
- MutableHashMap.set(this.entries, key, { scope, deferred })
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
- MutableHashMap.remove(this.entries, key)
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 = MutableHashMap.get(this.entries, key)
84
- if (Option.isNone(entry)) {
83
+ const entry = backingGet(this.entries, key)
84
+ if (!entry) {
85
85
  return Effect.void
86
86
  }
87
- MutableHashMap.remove(this.entries, key)
88
- return Scope.close(entry.value.scope, Exit.void)
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.Codec<
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
- any,
91
- any
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.Codec<A, I, RD, RE>,
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.Codec<A, I, RD, RE>,
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, RE>(
102
- schema: Schema.Codec<A, I, RD, RE>,
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)