@effect/cluster 0.52.0 → 0.52.2

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/src/Sharding.ts CHANGED
@@ -122,7 +122,10 @@ export class Sharding extends Context.Tag("@effect/cluster/Sharding")<Sharding,
122
122
  ) => Effect.Effect<
123
123
  void,
124
124
  never,
125
- Rpc.Context<Rpcs> | Rpc.Middleware<Rpcs> | Exclude<RX, Scope.Scope | CurrentAddress | CurrentRunnerAddress>
125
+ | Scope.Scope
126
+ | Rpc.Context<Rpcs>
127
+ | Rpc.Middleware<Rpcs>
128
+ | Exclude<RX, Scope.Scope | CurrentAddress | CurrentRunnerAddress>
126
129
  >
127
130
 
128
131
  /**
@@ -134,7 +137,7 @@ export class Sharding extends Context.Tag("@effect/cluster/Sharding")<Sharding,
134
137
  options?: {
135
138
  readonly shardGroup?: string | undefined
136
139
  }
137
- ) => Effect.Effect<void, never, Exclude<R, Scope.Scope>>
140
+ ) => Effect.Effect<void, never, R | Scope.Scope>
138
141
 
139
142
  /**
140
143
  * Sends a message to the specified entity.
@@ -187,9 +190,8 @@ export class Sharding extends Context.Tag("@effect/cluster/Sharding")<Sharding,
187
190
 
188
191
  interface EntityManagerState {
189
192
  readonly entity: Entity<any, any>
190
- readonly scope: Scope.CloseableScope
191
193
  readonly manager: EntityManager.EntityManager
192
- closed: boolean
194
+ status: "alive" | "closing" | "closed"
193
195
  }
194
196
 
195
197
  const make = Effect.gen(function*() {
@@ -421,12 +423,6 @@ const make = Effect.gen(function*() {
421
423
  const send = Effect.catchAllCause(
422
424
  Effect.suspend(() => {
423
425
  const message = messages[index]
424
- // if we are shutting down, we don't accept new requests
425
- if (message._tag === "IncomingRequest" && isShutdown.current) {
426
- if (isShutdown.current) {
427
- return Effect.void
428
- }
429
- }
430
426
  const address = message.envelope.address
431
427
  if (!MutableHashSet.has(acquiredShards, address.shardId)) {
432
428
  return Effect.void
@@ -436,17 +432,19 @@ const make = Effect.gen(function*() {
436
432
  // reset address in the case that the entity is slow to register
437
433
  MutableHashSet.add(resetAddresses, address)
438
434
  return Effect.void
439
- } else if (state.closed) {
435
+ } else if (state.status === "closed") {
440
436
  return Effect.void
441
437
  }
442
438
 
443
439
  const isProcessing = state.manager.isProcessingFor(message)
444
440
 
445
- // If the message might affect a currently processing request, we
446
- // send it to the entity manager to be processed.
447
441
  if (message._tag === "IncomingEnvelope" && isProcessing) {
442
+ // If the message might affect a currently processing request, we
443
+ // send it to the entity manager to be processed.
448
444
  return state.manager.send(message)
449
- } else if (isProcessing) {
445
+ } else if (isProcessing || state.status === "closing") {
446
+ // If the request is already processing, we skip it.
447
+ // Or if the entity is closing, we skip all incoming messages.
450
448
  return Effect.void
451
449
  } else if (message._tag === "IncomingRequest" && pendingNotifications.has(message.envelope.requestId)) {
452
450
  const entry = pendingNotifications.get(message.envelope.requestId)!
@@ -691,7 +689,7 @@ const make = Effect.gen(function*() {
691
689
  const state = entityManagers.get(address.entityType)
692
690
  if (!state) {
693
691
  return Effect.flatMap(waitForEntityManager(address.entityType), loop)
694
- } else if (state.closed || (isShutdown.current && message._tag === "IncomingRequest")) {
692
+ } else if (state.status === "closed" || (state.status === "closing" && message._tag === "IncomingRequest")) {
695
693
  // if we are shutting down, we don't accept new requests
696
694
  return Effect.fail(new EntityNotAssignedToRunner({ address }))
697
695
  }
@@ -727,7 +725,7 @@ const make = Effect.gen(function*() {
727
725
  const state = entityManagers.get(address.entityType)
728
726
  if (!state) {
729
727
  return Effect.flatMap(waitForEntityManager(address.entityType), loop)
730
- } else if (state.closed || !isEntityOnLocalShards(address)) {
728
+ } else if (state.status === "closed" || !isEntityOnLocalShards(address)) {
731
729
  return Effect.fail(new EntityNotAssignedToRunner({ address }))
732
730
  }
733
731
 
@@ -1180,6 +1178,12 @@ const make = Effect.gen(function*() {
1180
1178
  yield* Effect.logDebug("Starting singleton", address)
1181
1179
  yield* FiberMap.run(singletonFibers, address, wrappedRun)
1182
1180
  }
1181
+
1182
+ yield* Effect.addFinalizer(() => {
1183
+ const map = singletons.get(address.shardId)!
1184
+ MutableHashMap.remove(map, address)
1185
+ return FiberMap.remove(singletonFibers, address)
1186
+ })
1183
1187
  },
1184
1188
  withSingletonLock
1185
1189
  )
@@ -1214,11 +1218,11 @@ const make = Effect.gen(function*() {
1214
1218
  const registerEntity: Sharding["Type"]["registerEntity"] = Effect.fnUntraced(
1215
1219
  function*(entity, build, options) {
1216
1220
  if (Option.isNone(config.runnerAddress) || entityManagers.has(entity.type)) return
1217
- const scope = yield* Scope.make()
1221
+ const scope = yield* Effect.scope
1218
1222
  yield* Scope.addFinalizer(
1219
1223
  scope,
1220
1224
  Effect.sync(() => {
1221
- state.closed = true
1225
+ state.status = "closed"
1222
1226
  })
1223
1227
  )
1224
1228
  const manager = yield* EntityManager.make(entity, build, {
@@ -1235,10 +1239,17 @@ const make = Effect.gen(function*() {
1235
1239
  ) as Effect.Effect<EntityManager.EntityManager>
1236
1240
  const state: EntityManagerState = {
1237
1241
  entity,
1238
- scope,
1239
- closed: false,
1242
+ status: "alive",
1240
1243
  manager
1241
1244
  }
1245
+ yield* Scope.addFinalizer(
1246
+ scope,
1247
+ Effect.fiberIdWith((id) => {
1248
+ state.status = "closing"
1249
+ internalInterruptors.add(id)
1250
+ return Effect.void
1251
+ })
1252
+ )
1242
1253
 
1243
1254
  // register entities while storage is idle
1244
1255
  // this ensures message order is preserved
@@ -1254,20 +1265,6 @@ const make = Effect.gen(function*() {
1254
1265
  }
1255
1266
  )
1256
1267
 
1257
- yield* Scope.addFinalizerExit(
1258
- shardingScope,
1259
- (exit) =>
1260
- Effect.forEach(
1261
- entityManagers.values(),
1262
- (state) =>
1263
- Effect.catchAllCause(Scope.close(state.scope, exit), (cause) =>
1264
- Effect.annotateLogs(Effect.logError("Error closing entity manager", cause), {
1265
- entity: state.entity.type
1266
- })),
1267
- { concurrency: "unbounded", discard: true }
1268
- )
1269
- )
1270
-
1271
1268
  const waitForEntityManager = (entityType: string) => {
1272
1269
  let latch = entityManagerLatches.get(entityType)
1273
1270
  if (!latch) {
package/src/Singleton.ts CHANGED
@@ -17,7 +17,7 @@ export const make = <E, R>(
17
17
  readonly shardGroup?: string | undefined
18
18
  }
19
19
  ): Layer.Layer<never, never, Sharding | Exclude<R, Scope>> =>
20
- Layer.effectDiscard(Effect.gen(function*() {
20
+ Layer.scopedDiscard(Effect.gen(function*() {
21
21
  const sharding = yield* Sharding
22
22
  yield* sharding.registerSingleton(name, run, options)
23
23
  }))