@effect/cluster 0.52.4 → 0.52.5
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 +33 -24
- package/dist/cjs/Sharding.js.map +1 -1
- package/dist/cjs/SqlRunnerStorage.js +3 -3
- package/dist/cjs/SqlRunnerStorage.js.map +1 -1
- package/dist/cjs/internal/entityManager.js +1 -1
- package/dist/cjs/internal/entityManager.js.map +1 -1
- package/dist/dts/Sharding.d.ts.map +1 -1
- package/dist/dts/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/esm/Sharding.js +33 -24
- package/dist/esm/Sharding.js.map +1 -1
- package/dist/esm/SqlRunnerStorage.js +3 -3
- package/dist/esm/SqlRunnerStorage.js.map +1 -1
- package/dist/esm/internal/entityManager.js +1 -1
- package/dist/esm/internal/entityManager.js.map +1 -1
- package/package.json +4 -4
- package/src/Sharding.ts +53 -31
- package/src/SqlRunnerStorage.ts +1 -5
- package/src/internal/entityManager.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect/cluster",
|
|
3
|
-
"version": "0.52.
|
|
3
|
+
"version": "0.52.5",
|
|
4
4
|
"description": "Unified interfaces for common cluster-specific services",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"homepage": "https://effect.website",
|
|
13
13
|
"peerDependencies": {
|
|
14
14
|
"@effect/platform": "^0.93.0",
|
|
15
|
-
"@effect/rpc": "^0.72.1",
|
|
16
15
|
"@effect/sql": "^0.48.0",
|
|
17
|
-
"effect": "^
|
|
18
|
-
"@effect/
|
|
16
|
+
"@effect/workflow": "^0.12.2",
|
|
17
|
+
"@effect/rpc": "^0.72.1",
|
|
18
|
+
"effect": "^3.19.2"
|
|
19
19
|
},
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"provenance": true
|
package/src/Sharding.ts
CHANGED
|
@@ -237,6 +237,14 @@ const make = Effect.gen(function*() {
|
|
|
237
237
|
return MutableHashSet.has(acquiredShards, address.shardId)
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
yield* Scope.addFinalizer(
|
|
241
|
+
shardingScope,
|
|
242
|
+
Effect.logDebug("Shutdown complete").pipe(Effect.annotateLogs({
|
|
243
|
+
package: "@effect/cluster",
|
|
244
|
+
module: "Sharding"
|
|
245
|
+
}))
|
|
246
|
+
)
|
|
247
|
+
|
|
240
248
|
// --- Shard acquisition ---
|
|
241
249
|
//
|
|
242
250
|
// Responsible for acquiring and releasing shards from RunnerStorage.
|
|
@@ -252,6 +260,37 @@ const make = Effect.gen(function*() {
|
|
|
252
260
|
return Effect.ignore(runnerStorage.releaseAll(selfAddress))
|
|
253
261
|
})
|
|
254
262
|
|
|
263
|
+
const releaseShardsHandle = yield* FiberHandle.make()
|
|
264
|
+
const releaseShards = Effect.suspend(function loop(): Effect.Effect<void, PersistenceError> {
|
|
265
|
+
return Effect.flatMap(
|
|
266
|
+
Effect.forEach(
|
|
267
|
+
releasingShards,
|
|
268
|
+
(shardId) =>
|
|
269
|
+
Effect.forEach(
|
|
270
|
+
entityManagers.values(),
|
|
271
|
+
(state) => state.status === "closed" ? Effect.void : state.manager.interruptShard(shardId),
|
|
272
|
+
{ concurrency: "unbounded", discard: true }
|
|
273
|
+
).pipe(
|
|
274
|
+
Effect.andThen(runnerStorage.release(selfAddress, shardId)),
|
|
275
|
+
Effect.annotateLogs({ runner: selfAddress }),
|
|
276
|
+
Effect.flatMap(() => {
|
|
277
|
+
MutableHashSet.remove(releasingShards, shardId)
|
|
278
|
+
return storage.unregisterShardReplyHandlers(shardId)
|
|
279
|
+
})
|
|
280
|
+
),
|
|
281
|
+
{ concurrency: "unbounded", discard: true }
|
|
282
|
+
),
|
|
283
|
+
() => {
|
|
284
|
+
if (MutableHashSet.size(releasingShards) === 0) {
|
|
285
|
+
return Effect.void
|
|
286
|
+
}
|
|
287
|
+
return loop()
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
}).pipe(
|
|
291
|
+
FiberHandle.run(releaseShardsHandle, { onlyIfMissing: true })
|
|
292
|
+
)
|
|
293
|
+
|
|
255
294
|
yield* Effect.gen(function*() {
|
|
256
295
|
activeShardsLatch.unsafeOpen()
|
|
257
296
|
|
|
@@ -320,7 +359,8 @@ const make = Effect.gen(function*() {
|
|
|
320
359
|
fiber: "Shard acquisition loop",
|
|
321
360
|
runner: selfAddress
|
|
322
361
|
}),
|
|
323
|
-
Effect.forkIn(shardingScope)
|
|
362
|
+
Effect.forkIn(shardingScope),
|
|
363
|
+
Effect.interruptible
|
|
324
364
|
)
|
|
325
365
|
|
|
326
366
|
// refresh the shard locks every `shardLockRefreshInterval`
|
|
@@ -359,38 +399,16 @@ const make = Effect.gen(function*() {
|
|
|
359
399
|
),
|
|
360
400
|
Effect.repeat(Schedule.fixed(config.shardLockRefreshInterval)),
|
|
361
401
|
Effect.forever,
|
|
362
|
-
Effect.forkIn(shardingScope)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
const releaseShardsHandle = yield* FiberHandle.make()
|
|
366
|
-
const releaseShards = Effect.suspend(() =>
|
|
367
|
-
Effect.forEach(
|
|
368
|
-
releasingShards,
|
|
369
|
-
(shardId) =>
|
|
370
|
-
Effect.forEach(
|
|
371
|
-
entityManagers.values(),
|
|
372
|
-
(state) => state.manager.interruptShard(shardId),
|
|
373
|
-
{ concurrency: "unbounded", discard: true }
|
|
374
|
-
).pipe(
|
|
375
|
-
Effect.andThen(runnerStorage.release(selfAddress, shardId)),
|
|
376
|
-
Effect.annotateLogs({ runner: selfAddress }),
|
|
377
|
-
Effect.flatMap(() => {
|
|
378
|
-
MutableHashSet.remove(releasingShards, shardId)
|
|
379
|
-
return storage.unregisterShardReplyHandlers(shardId)
|
|
380
|
-
})
|
|
381
|
-
),
|
|
382
|
-
{ concurrency: "unbounded", discard: true }
|
|
383
|
-
)
|
|
384
|
-
).pipe(
|
|
385
|
-
Effect.repeat({ until: () => MutableHashSet.size(releasingShards) === 0 }),
|
|
386
|
-
FiberHandle.run(releaseShardsHandle, { onlyIfMissing: true })
|
|
402
|
+
Effect.forkIn(shardingScope),
|
|
403
|
+
Effect.interruptible
|
|
387
404
|
)
|
|
388
405
|
|
|
389
406
|
// open the shard latch every poll interval
|
|
390
407
|
yield* activeShardsLatch.open.pipe(
|
|
391
408
|
Effect.delay(config.entityMessagePollInterval),
|
|
392
409
|
Effect.forever,
|
|
393
|
-
Effect.forkIn(shardingScope)
|
|
410
|
+
Effect.forkIn(shardingScope),
|
|
411
|
+
Effect.interruptible
|
|
394
412
|
)
|
|
395
413
|
}
|
|
396
414
|
|
|
@@ -555,14 +573,16 @@ const make = Effect.gen(function*() {
|
|
|
555
573
|
runner: selfAddress
|
|
556
574
|
}),
|
|
557
575
|
Effect.withUnhandledErrorLogLevel(Option.none()),
|
|
558
|
-
Effect.forkIn(shardingScope)
|
|
576
|
+
Effect.forkIn(shardingScope),
|
|
577
|
+
Effect.interruptible
|
|
559
578
|
)
|
|
560
579
|
|
|
561
580
|
// open the storage latch every poll interval
|
|
562
581
|
yield* storageReadLatch.open.pipe(
|
|
563
582
|
Effect.delay(config.entityMessagePollInterval),
|
|
564
583
|
Effect.forever,
|
|
565
|
-
Effect.forkIn(shardingScope)
|
|
584
|
+
Effect.forkIn(shardingScope),
|
|
585
|
+
Effect.interruptible
|
|
566
586
|
)
|
|
567
587
|
|
|
568
588
|
// Resume unprocessed messages for entities that reached a full mailbox.
|
|
@@ -682,7 +702,8 @@ const make = Effect.gen(function*() {
|
|
|
682
702
|
Effect.sync(() => MutableHashMap.remove(entityResumptionState, address))
|
|
683
703
|
),
|
|
684
704
|
Effect.withUnhandledErrorLogLevel(Option.none()),
|
|
685
|
-
Effect.forkIn(shardingScope)
|
|
705
|
+
Effect.forkIn(shardingScope),
|
|
706
|
+
Effect.interruptible
|
|
686
707
|
)
|
|
687
708
|
}
|
|
688
709
|
|
|
@@ -958,7 +979,8 @@ const make = Effect.gen(function*() {
|
|
|
958
979
|
fiber: "RunnerStorage sync",
|
|
959
980
|
runner: config.runnerAddress
|
|
960
981
|
}),
|
|
961
|
-
Effect.forkIn(shardingScope)
|
|
982
|
+
Effect.forkIn(shardingScope),
|
|
983
|
+
Effect.interruptible
|
|
962
984
|
)
|
|
963
985
|
|
|
964
986
|
// --- Clients ---
|
package/src/SqlRunnerStorage.ts
CHANGED
|
@@ -447,9 +447,7 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
447
447
|
function*(_address, shardId) {
|
|
448
448
|
const lockNum = lockNumbers.get(shardId)!
|
|
449
449
|
const conn = yield* Resource.get(lockConnRef!)
|
|
450
|
-
const release = conn.executeRaw(`SELECT pg_advisory_unlock(${lockNum})`, [])
|
|
451
|
-
Effect.timeoutOption(Duration.seconds(5))
|
|
452
|
-
)
|
|
450
|
+
const release = conn.executeRaw(`SELECT pg_advisory_unlock(${lockNum})`, [])
|
|
453
451
|
const check = conn.executeValues(
|
|
454
452
|
`SELECT 1 FROM pg_locks WHERE locktype = 'advisory' AND granted = true AND pid = pg_backend_pid() AND objid = ${lockNum}`,
|
|
455
453
|
[]
|
|
@@ -460,7 +458,6 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
460
458
|
if (takenLocks.length === 0) return
|
|
461
459
|
}
|
|
462
460
|
},
|
|
463
|
-
Effect.timeout(config.shardLockExpiration),
|
|
464
461
|
Effect.onError(() => Resource.refresh(lockConnRef!)),
|
|
465
462
|
Effect.asVoid,
|
|
466
463
|
PersistenceError.refail,
|
|
@@ -482,7 +479,6 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
482
479
|
if (takenLocks.length === 0 || takenLocks[0][0] !== 1) return
|
|
483
480
|
}
|
|
484
481
|
},
|
|
485
|
-
Effect.timeout(config.shardLockExpiration),
|
|
486
482
|
Effect.onError(() => Resource.refresh(lockConnRef!)),
|
|
487
483
|
Effect.asVoid,
|
|
488
484
|
PersistenceError.refail,
|
|
@@ -127,7 +127,7 @@ export const make = Effect.fnUntraced(function*<
|
|
|
127
127
|
() => {
|
|
128
128
|
serverCloseLatches.get(address)?.unsafeOpen()
|
|
129
129
|
serverCloseLatches.delete(address)
|
|
130
|
-
return Effect.
|
|
130
|
+
return Effect.void
|
|
131
131
|
}
|
|
132
132
|
)
|
|
133
133
|
|