@effect/cluster 0.52.6 → 0.52.7
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/cjs/Sharding.js +13 -20
- package/dist/cjs/Sharding.js.map +1 -1
- package/dist/cjs/internal/entityManager.js +18 -25
- package/dist/cjs/internal/entityManager.js.map +1 -1
- package/dist/cjs/internal/fiber.js +40 -0
- package/dist/cjs/internal/fiber.js.map +1 -0
- package/dist/dts/Sharding.d.ts.map +1 -1
- package/dist/dts/internal/fiber.d.ts +2 -0
- package/dist/dts/internal/fiber.d.ts.map +1 -0
- package/dist/esm/Sharding.js +13 -20
- package/dist/esm/Sharding.js.map +1 -1
- package/dist/esm/internal/entityManager.js +18 -25
- package/dist/esm/internal/entityManager.js.map +1 -1
- package/dist/esm/internal/fiber.js +32 -0
- package/dist/esm/internal/fiber.js.map +1 -0
- package/package.json +3 -3
- package/src/Sharding.ts +23 -31
- package/src/internal/entityManager.ts +25 -36
- package/src/internal/fiber.ts +35 -0
package/src/Sharding.ts
CHANGED
|
@@ -42,6 +42,7 @@ import { make as makeEntityId } from "./EntityId.js"
|
|
|
42
42
|
import * as Envelope from "./Envelope.js"
|
|
43
43
|
import * as EntityManager from "./internal/entityManager.js"
|
|
44
44
|
import { EntityReaper } from "./internal/entityReaper.js"
|
|
45
|
+
import { joinAllDiscard } from "./internal/fiber.js"
|
|
45
46
|
import { hashString } from "./internal/hash.js"
|
|
46
47
|
import { internalInterruptors } from "./internal/interruptors.js"
|
|
47
48
|
import { ResourceMap } from "./internal/resourceMap.js"
|
|
@@ -263,45 +264,37 @@ const make = Effect.gen(function*() {
|
|
|
263
264
|
const releaseShardsMap = yield* FiberMap.make<ShardId>()
|
|
264
265
|
const releaseShard = Effect.fnUntraced(
|
|
265
266
|
function*(shardId: ShardId) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
(state)
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
attributes: { entityType: state.entity.type }
|
|
273
|
-
})
|
|
274
|
-
),
|
|
275
|
-
{ concurrency: "unbounded", discard: true }
|
|
276
|
-
).pipe(
|
|
277
|
-
Effect.timeout(config.entityTerminationTimeout)
|
|
278
|
-
)
|
|
267
|
+
const fibers = Arr.empty<Fiber.RuntimeFiber<void>>()
|
|
268
|
+
for (const state of entityManagers.values()) {
|
|
269
|
+
if (state.status === "closed") continue
|
|
270
|
+
fibers.push(yield* Effect.fork(state.manager.interruptShard(shardId)))
|
|
271
|
+
}
|
|
272
|
+
yield* joinAllDiscard(fibers)
|
|
279
273
|
yield* runnerStorage.release(selfAddress, shardId)
|
|
280
274
|
MutableHashSet.remove(releasingShards, shardId)
|
|
281
275
|
yield* storage.unregisterShardReplyHandlers(shardId)
|
|
282
276
|
},
|
|
283
277
|
Effect.sandbox,
|
|
284
|
-
Effect.tapError((cause) => Effect.logDebug(`Could not release shard, retrying`, cause)),
|
|
285
|
-
Effect.eventually,
|
|
286
278
|
(effect, shardId) =>
|
|
287
279
|
effect.pipe(
|
|
288
|
-
Effect.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
280
|
+
Effect.tapError((cause) =>
|
|
281
|
+
Effect.logDebug(`Could not release shard, retrying`, cause).pipe(
|
|
282
|
+
Effect.annotateLogs({
|
|
283
|
+
package: "@effect/cluster",
|
|
284
|
+
module: "Sharding",
|
|
285
|
+
fiber: "releaseShard",
|
|
286
|
+
runner: selfAddress,
|
|
287
|
+
shardId
|
|
288
|
+
})
|
|
289
|
+
)
|
|
290
|
+
),
|
|
291
|
+
Effect.eventually,
|
|
300
292
|
FiberMap.run(releaseShardsMap, shardId, { onlyIfMissing: true })
|
|
301
293
|
)
|
|
302
294
|
)
|
|
303
295
|
const releaseShards = Effect.gen(function*() {
|
|
304
296
|
for (const shardId of releasingShards) {
|
|
297
|
+
if (FiberMap.unsafeHas(releaseShardsMap, shardId)) continue
|
|
305
298
|
yield* releaseShard(shardId)
|
|
306
299
|
}
|
|
307
300
|
})
|
|
@@ -1115,8 +1108,8 @@ const make = Effect.gen(function*() {
|
|
|
1115
1108
|
|
|
1116
1109
|
yield* Scope.addFinalizer(
|
|
1117
1110
|
yield* Effect.scope,
|
|
1118
|
-
Effect.
|
|
1119
|
-
internalInterruptors.add(
|
|
1111
|
+
Effect.fiberIdWith((fiberId) => {
|
|
1112
|
+
internalInterruptors.add(fiberId)
|
|
1120
1113
|
return Effect.void
|
|
1121
1114
|
})
|
|
1122
1115
|
)
|
|
@@ -1384,8 +1377,7 @@ const make = Effect.gen(function*() {
|
|
|
1384
1377
|
)
|
|
1385
1378
|
}
|
|
1386
1379
|
|
|
1387
|
-
|
|
1388
|
-
internalInterruptors.add(fiberId)
|
|
1380
|
+
internalInterruptors.add(yield* Effect.fiberId)
|
|
1389
1381
|
if (isShutdown.current) return
|
|
1390
1382
|
|
|
1391
1383
|
MutableRef.set(isShutdown, true)
|
|
@@ -9,12 +9,13 @@ import type { DurationInput } from "effect/Duration"
|
|
|
9
9
|
import * as Effect from "effect/Effect"
|
|
10
10
|
import * as Equal from "effect/Equal"
|
|
11
11
|
import * as Exit from "effect/Exit"
|
|
12
|
-
import * as
|
|
12
|
+
import type * as Fiber from "effect/Fiber"
|
|
13
13
|
import * as FiberRef from "effect/FiberRef"
|
|
14
14
|
import { identity } from "effect/Function"
|
|
15
15
|
import * as HashMap from "effect/HashMap"
|
|
16
16
|
import * as Metric from "effect/Metric"
|
|
17
17
|
import * as Option from "effect/Option"
|
|
18
|
+
import * as Runtime from "effect/Runtime"
|
|
18
19
|
import * as Schedule from "effect/Schedule"
|
|
19
20
|
import * as Schema from "effect/Schema"
|
|
20
21
|
import * as Scope from "effect/Scope"
|
|
@@ -35,6 +36,7 @@ import type { Sharding } from "../Sharding.js"
|
|
|
35
36
|
import { ShardingConfig } from "../ShardingConfig.js"
|
|
36
37
|
import * as Snowflake from "../Snowflake.js"
|
|
37
38
|
import { EntityReaper } from "./entityReaper.js"
|
|
39
|
+
import { joinAllDiscard } from "./fiber.js"
|
|
38
40
|
import { internalInterruptors } from "./interruptors.js"
|
|
39
41
|
import { ResourceMap } from "./resourceMap.js"
|
|
40
42
|
import { ResourceRef } from "./resourceRef.js"
|
|
@@ -435,44 +437,31 @@ export const make = Effect.fnUntraced(function*<
|
|
|
435
437
|
)
|
|
436
438
|
}
|
|
437
439
|
|
|
438
|
-
const entityRemovalMap = yield* FiberMap.make<EntityAddress>()
|
|
439
|
-
|
|
440
|
-
const interruptShard = (shardId: ShardId) =>
|
|
441
|
-
Effect.suspend(function loop(): Effect.Effect<void> {
|
|
442
|
-
const toAwait = Arr.empty<Effect.Effect<void>>()
|
|
443
|
-
activeServers.forEach((state) => {
|
|
444
|
-
if (shardId[Equal.symbol](state.address.shardId)) {
|
|
445
|
-
toAwait.push(
|
|
446
|
-
FiberMap.run(
|
|
447
|
-
entityRemovalMap,
|
|
448
|
-
state.address,
|
|
449
|
-
entities.removeIgnore(state.address),
|
|
450
|
-
{ onlyIfMissing: true }
|
|
451
|
-
)
|
|
452
|
-
)
|
|
453
|
-
}
|
|
454
|
-
})
|
|
455
|
-
serverCloseLatches.forEach((latch, address) => {
|
|
456
|
-
if (shardId[Equal.symbol](address.shardId)) {
|
|
457
|
-
toAwait.push(latch.await)
|
|
458
|
-
}
|
|
459
|
-
})
|
|
460
|
-
if (toAwait.length === 0) {
|
|
461
|
-
return Effect.void
|
|
462
|
-
}
|
|
463
|
-
return Effect.flatMap(
|
|
464
|
-
Effect.all(toAwait, {
|
|
465
|
-
concurrency: "unbounded",
|
|
466
|
-
discard: true
|
|
467
|
-
}),
|
|
468
|
-
loop
|
|
469
|
-
)
|
|
470
|
-
})
|
|
471
|
-
|
|
472
440
|
const decodeMessage = Schema.decode(makeMessageSchema(entity))
|
|
473
441
|
|
|
442
|
+
const runFork = Runtime.runFork(
|
|
443
|
+
yield* Effect.runtime<never>().pipe(
|
|
444
|
+
Effect.interruptible
|
|
445
|
+
)
|
|
446
|
+
)
|
|
447
|
+
|
|
474
448
|
return identity<EntityManager>({
|
|
475
|
-
interruptShard
|
|
449
|
+
interruptShard: (shardId: ShardId) =>
|
|
450
|
+
Effect.suspend(function loop(): Effect.Effect<void> {
|
|
451
|
+
const fibers = Arr.empty<Fiber.RuntimeFiber<void>>()
|
|
452
|
+
activeServers.forEach((state) => {
|
|
453
|
+
if (shardId[Equal.symbol](state.address.shardId)) {
|
|
454
|
+
fibers.push(runFork(entities.removeIgnore(state.address)))
|
|
455
|
+
}
|
|
456
|
+
})
|
|
457
|
+
serverCloseLatches.forEach((latch, address) => {
|
|
458
|
+
if (shardId[Equal.symbol](address.shardId)) {
|
|
459
|
+
fibers.push(runFork(latch.await))
|
|
460
|
+
}
|
|
461
|
+
})
|
|
462
|
+
if (fibers.length === 0) return Effect.void
|
|
463
|
+
return Effect.flatMap(joinAllDiscard(fibers), loop)
|
|
464
|
+
}),
|
|
476
465
|
isProcessingFor(message, options) {
|
|
477
466
|
if (options?.excludeReplies !== true && processedRequestIds.has(message.envelope.requestId)) {
|
|
478
467
|
return true
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import type * as Exit from "effect/Exit"
|
|
4
|
+
import type * as Fiber from "effect/Fiber"
|
|
5
|
+
|
|
6
|
+
/** @internal */
|
|
7
|
+
export const joinAllDiscard = <A, E>(fibers: ReadonlyArray<Fiber.RuntimeFiber<A, E>>) =>
|
|
8
|
+
Effect.async<void, E>((resume) => {
|
|
9
|
+
let cause: Cause.Cause<E> | undefined = undefined
|
|
10
|
+
let i = 0
|
|
11
|
+
function loop() {
|
|
12
|
+
while (i < fibers.length) {
|
|
13
|
+
const fiber = fibers[i]
|
|
14
|
+
const exit = fiber.unsafePoll()
|
|
15
|
+
if (exit) {
|
|
16
|
+
i++
|
|
17
|
+
if (exit._tag === "Success") continue
|
|
18
|
+
cause = cause ? Cause.parallel(cause, exit.cause) : exit.cause
|
|
19
|
+
continue
|
|
20
|
+
}
|
|
21
|
+
fiber.addObserver(onExit)
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
resume(cause ? Effect.failCause(cause) : Effect.void)
|
|
25
|
+
}
|
|
26
|
+
function onExit(exit: Exit.Exit<A, E>) {
|
|
27
|
+
i++
|
|
28
|
+
if (exit._tag === "Failure") {
|
|
29
|
+
cause = cause ? Cause.parallel(cause, exit.cause) : exit.cause
|
|
30
|
+
}
|
|
31
|
+
loop()
|
|
32
|
+
}
|
|
33
|
+
loop()
|
|
34
|
+
return Effect.sync(() => fibers[i].removeObserver(onExit))
|
|
35
|
+
})
|