@effect/cluster 0.52.3 → 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 +41 -22
- package/dist/cjs/Sharding.js.map +1 -1
- package/dist/cjs/SqlRunnerStorage.js +2 -1
- 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 +41 -22
- package/dist/esm/Sharding.js.map +1 -1
- package/dist/esm/SqlRunnerStorage.js +2 -1
- 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 +2 -2
- package/src/Sharding.ts +67 -32
- package/src/SqlRunnerStorage.ts +2 -4
- 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": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"@effect/sql": "^0.48.0",
|
|
16
16
|
"@effect/workflow": "^0.12.2",
|
|
17
17
|
"@effect/rpc": "^0.72.1",
|
|
18
|
-
"effect": "^3.19.
|
|
18
|
+
"effect": "^3.19.2"
|
|
19
19
|
},
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"provenance": true
|
package/src/Sharding.ts
CHANGED
|
@@ -13,6 +13,7 @@ import * as Either from "effect/Either"
|
|
|
13
13
|
import * as Equal from "effect/Equal"
|
|
14
14
|
import type * as Exit from "effect/Exit"
|
|
15
15
|
import * as Fiber from "effect/Fiber"
|
|
16
|
+
import * as FiberHandle from "effect/FiberHandle"
|
|
16
17
|
import * as FiberMap from "effect/FiberMap"
|
|
17
18
|
import * as FiberRef from "effect/FiberRef"
|
|
18
19
|
import * as FiberSet from "effect/FiberSet"
|
|
@@ -236,6 +237,14 @@ const make = Effect.gen(function*() {
|
|
|
236
237
|
return MutableHashSet.has(acquiredShards, address.shardId)
|
|
237
238
|
}
|
|
238
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
|
+
|
|
239
248
|
// --- Shard acquisition ---
|
|
240
249
|
//
|
|
241
250
|
// Responsible for acquiring and releasing shards from RunnerStorage.
|
|
@@ -251,6 +260,37 @@ const make = Effect.gen(function*() {
|
|
|
251
260
|
return Effect.ignore(runnerStorage.releaseAll(selfAddress))
|
|
252
261
|
})
|
|
253
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
|
+
|
|
254
294
|
yield* Effect.gen(function*() {
|
|
255
295
|
activeShardsLatch.unsafeOpen()
|
|
256
296
|
|
|
@@ -281,8 +321,19 @@ const make = Effect.gen(function*() {
|
|
|
281
321
|
continue
|
|
282
322
|
}
|
|
283
323
|
|
|
284
|
-
const
|
|
285
|
-
|
|
324
|
+
const oacquired = yield* runnerStorage.acquire(selfAddress, unacquiredShards).pipe(
|
|
325
|
+
Effect.timeoutOption(config.shardLockRefreshInterval)
|
|
326
|
+
)
|
|
327
|
+
if (Option.isNone(oacquired)) {
|
|
328
|
+
activeShardsLatch.unsafeOpen()
|
|
329
|
+
continue
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const acquired = oacquired.value
|
|
333
|
+
yield* storage.resetShards(acquired).pipe(
|
|
334
|
+
Effect.ignore,
|
|
335
|
+
Effect.timeoutOption(config.shardLockRefreshInterval)
|
|
336
|
+
)
|
|
286
337
|
for (const shardId of acquired) {
|
|
287
338
|
if (MutableHashSet.has(releasingShards, shardId) || !MutableHashSet.has(selfShards, shardId)) {
|
|
288
339
|
continue
|
|
@@ -308,7 +359,8 @@ const make = Effect.gen(function*() {
|
|
|
308
359
|
fiber: "Shard acquisition loop",
|
|
309
360
|
runner: selfAddress
|
|
310
361
|
}),
|
|
311
|
-
Effect.forkIn(shardingScope)
|
|
362
|
+
Effect.forkIn(shardingScope),
|
|
363
|
+
Effect.interruptible
|
|
312
364
|
)
|
|
313
365
|
|
|
314
366
|
// refresh the shard locks every `shardLockRefreshInterval`
|
|
@@ -347,37 +399,16 @@ const make = Effect.gen(function*() {
|
|
|
347
399
|
),
|
|
348
400
|
Effect.repeat(Schedule.fixed(config.shardLockRefreshInterval)),
|
|
349
401
|
Effect.forever,
|
|
350
|
-
Effect.forkIn(shardingScope)
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const releaseShardsLock = Effect.unsafeMakeSemaphore(1).withPermits(1)
|
|
354
|
-
const releaseShards = releaseShardsLock(
|
|
355
|
-
Effect.suspend(() =>
|
|
356
|
-
Effect.forEach(
|
|
357
|
-
releasingShards,
|
|
358
|
-
(shardId) =>
|
|
359
|
-
Effect.forEach(
|
|
360
|
-
entityManagers.values(),
|
|
361
|
-
(state) => state.manager.interruptShard(shardId),
|
|
362
|
-
{ concurrency: "unbounded", discard: true }
|
|
363
|
-
).pipe(
|
|
364
|
-
Effect.andThen(runnerStorage.release(selfAddress, shardId)),
|
|
365
|
-
Effect.annotateLogs({ runner: selfAddress }),
|
|
366
|
-
Effect.flatMap(() => {
|
|
367
|
-
MutableHashSet.remove(releasingShards, shardId)
|
|
368
|
-
return storage.unregisterShardReplyHandlers(shardId)
|
|
369
|
-
})
|
|
370
|
-
),
|
|
371
|
-
{ concurrency: "unbounded", discard: true }
|
|
372
|
-
)
|
|
373
|
-
)
|
|
402
|
+
Effect.forkIn(shardingScope),
|
|
403
|
+
Effect.interruptible
|
|
374
404
|
)
|
|
375
405
|
|
|
376
406
|
// open the shard latch every poll interval
|
|
377
407
|
yield* activeShardsLatch.open.pipe(
|
|
378
408
|
Effect.delay(config.entityMessagePollInterval),
|
|
379
409
|
Effect.forever,
|
|
380
|
-
Effect.forkIn(shardingScope)
|
|
410
|
+
Effect.forkIn(shardingScope),
|
|
411
|
+
Effect.interruptible
|
|
381
412
|
)
|
|
382
413
|
}
|
|
383
414
|
|
|
@@ -542,14 +573,16 @@ const make = Effect.gen(function*() {
|
|
|
542
573
|
runner: selfAddress
|
|
543
574
|
}),
|
|
544
575
|
Effect.withUnhandledErrorLogLevel(Option.none()),
|
|
545
|
-
Effect.forkIn(shardingScope)
|
|
576
|
+
Effect.forkIn(shardingScope),
|
|
577
|
+
Effect.interruptible
|
|
546
578
|
)
|
|
547
579
|
|
|
548
580
|
// open the storage latch every poll interval
|
|
549
581
|
yield* storageReadLatch.open.pipe(
|
|
550
582
|
Effect.delay(config.entityMessagePollInterval),
|
|
551
583
|
Effect.forever,
|
|
552
|
-
Effect.forkIn(shardingScope)
|
|
584
|
+
Effect.forkIn(shardingScope),
|
|
585
|
+
Effect.interruptible
|
|
553
586
|
)
|
|
554
587
|
|
|
555
588
|
// Resume unprocessed messages for entities that reached a full mailbox.
|
|
@@ -669,7 +702,8 @@ const make = Effect.gen(function*() {
|
|
|
669
702
|
Effect.sync(() => MutableHashMap.remove(entityResumptionState, address))
|
|
670
703
|
),
|
|
671
704
|
Effect.withUnhandledErrorLogLevel(Option.none()),
|
|
672
|
-
Effect.forkIn(shardingScope)
|
|
705
|
+
Effect.forkIn(shardingScope),
|
|
706
|
+
Effect.interruptible
|
|
673
707
|
)
|
|
674
708
|
}
|
|
675
709
|
|
|
@@ -945,7 +979,8 @@ const make = Effect.gen(function*() {
|
|
|
945
979
|
fiber: "RunnerStorage sync",
|
|
946
980
|
runner: config.runnerAddress
|
|
947
981
|
}),
|
|
948
|
-
Effect.forkIn(shardingScope)
|
|
982
|
+
Effect.forkIn(shardingScope),
|
|
983
|
+
Effect.interruptible
|
|
949
984
|
)
|
|
950
985
|
|
|
951
986
|
// --- Clients ---
|
package/src/SqlRunnerStorage.ts
CHANGED
|
@@ -242,10 +242,8 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
242
242
|
if (toAcquire.size === 0) {
|
|
243
243
|
return acquiredShardIds
|
|
244
244
|
}
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
boolean
|
|
248
|
-
>
|
|
245
|
+
const rows = yield* conn.executeUnprepared(`SELECT ${pgLocks(toAcquire)}`, [], undefined)
|
|
246
|
+
const results = rows[0] as Record<string, boolean>
|
|
249
247
|
for (const shardId in results) {
|
|
250
248
|
if (results[shardId]) {
|
|
251
249
|
acquiredShardIds.push(shardId)
|
|
@@ -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
|
|