@effect/cluster 0.53.5 → 0.54.0
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/SingleRunner/package.json +6 -0
- package/TestRunner/package.json +6 -0
- package/dist/cjs/ShardingConfig.js +2 -0
- package/dist/cjs/ShardingConfig.js.map +1 -1
- package/dist/cjs/SingleRunner.js +25 -0
- package/dist/cjs/SingleRunner.js.map +1 -0
- package/dist/cjs/SqlRunnerStorage.js +149 -65
- package/dist/cjs/SqlRunnerStorage.js.map +1 -1
- package/dist/cjs/TestRunner.js +29 -0
- package/dist/cjs/TestRunner.js.map +1 -0
- package/dist/cjs/index.js +5 -1
- package/dist/dts/ShardingConfig.d.ts +8 -0
- package/dist/dts/ShardingConfig.d.ts.map +1 -1
- package/dist/dts/SingleRunner.d.ts +22 -0
- package/dist/dts/SingleRunner.d.ts.map +1 -0
- package/dist/dts/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/dts/TestRunner.d.ts +18 -0
- package/dist/dts/TestRunner.d.ts.map +1 -0
- package/dist/dts/index.d.ts +8 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/ShardingConfig.js +2 -0
- package/dist/esm/ShardingConfig.js.map +1 -1
- package/dist/esm/SingleRunner.js +17 -0
- package/dist/esm/SingleRunner.js.map +1 -0
- package/dist/esm/SqlRunnerStorage.js +149 -65
- package/dist/esm/SqlRunnerStorage.js.map +1 -1
- package/dist/esm/TestRunner.js +21 -0
- package/dist/esm/TestRunner.js.map +1 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/index.js.map +1 -1
- package/package.json +21 -5
- package/src/ShardingConfig.ts +9 -0
- package/src/SingleRunner.ts +41 -0
- package/src/SqlRunnerStorage.ts +134 -22
- package/src/TestRunner.ts +28 -0
- package/src/index.ts +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect/cluster",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.0",
|
|
4
4
|
"description": "Unified interfaces for common cluster-specific services",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
"kubernetes-types": "^1.30.0"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
|
-
"@effect/
|
|
17
|
+
"@effect/platform": "^0.93.5",
|
|
18
|
+
"@effect/sql": "^0.48.5",
|
|
18
19
|
"@effect/rpc": "^0.72.2",
|
|
19
|
-
"@effect/
|
|
20
|
-
"effect": "^3.19.
|
|
21
|
-
"@effect/platform": "^0.93.3"
|
|
20
|
+
"@effect/workflow": "^0.14.0",
|
|
21
|
+
"effect": "^3.19.8"
|
|
22
22
|
},
|
|
23
23
|
"publishConfig": {
|
|
24
24
|
"provenance": true
|
|
@@ -183,6 +183,11 @@
|
|
|
183
183
|
"import": "./dist/esm/ShardingRegistrationEvent.js",
|
|
184
184
|
"default": "./dist/cjs/ShardingRegistrationEvent.js"
|
|
185
185
|
},
|
|
186
|
+
"./SingleRunner": {
|
|
187
|
+
"types": "./dist/dts/SingleRunner.d.ts",
|
|
188
|
+
"import": "./dist/esm/SingleRunner.js",
|
|
189
|
+
"default": "./dist/cjs/SingleRunner.js"
|
|
190
|
+
},
|
|
186
191
|
"./Singleton": {
|
|
187
192
|
"types": "./dist/dts/Singleton.d.ts",
|
|
188
193
|
"import": "./dist/esm/Singleton.js",
|
|
@@ -213,6 +218,11 @@
|
|
|
213
218
|
"import": "./dist/esm/SqlRunnerStorage.js",
|
|
214
219
|
"default": "./dist/cjs/SqlRunnerStorage.js"
|
|
215
220
|
},
|
|
221
|
+
"./TestRunner": {
|
|
222
|
+
"types": "./dist/dts/TestRunner.d.ts",
|
|
223
|
+
"import": "./dist/esm/TestRunner.js",
|
|
224
|
+
"default": "./dist/cjs/TestRunner.js"
|
|
225
|
+
},
|
|
216
226
|
"./index": {
|
|
217
227
|
"types": "./dist/dts/index.d.ts",
|
|
218
228
|
"import": "./dist/esm/index.js",
|
|
@@ -311,6 +321,9 @@
|
|
|
311
321
|
"ShardingRegistrationEvent": [
|
|
312
322
|
"./dist/dts/ShardingRegistrationEvent.d.ts"
|
|
313
323
|
],
|
|
324
|
+
"SingleRunner": [
|
|
325
|
+
"./dist/dts/SingleRunner.d.ts"
|
|
326
|
+
],
|
|
314
327
|
"Singleton": [
|
|
315
328
|
"./dist/dts/Singleton.d.ts"
|
|
316
329
|
],
|
|
@@ -329,6 +342,9 @@
|
|
|
329
342
|
"SqlRunnerStorage": [
|
|
330
343
|
"./dist/dts/SqlRunnerStorage.d.ts"
|
|
331
344
|
],
|
|
345
|
+
"TestRunner": [
|
|
346
|
+
"./dist/dts/TestRunner.d.ts"
|
|
347
|
+
],
|
|
332
348
|
"index": [
|
|
333
349
|
"./dist/dts/index.d.ts"
|
|
334
350
|
]
|
package/src/ShardingConfig.ts
CHANGED
|
@@ -63,6 +63,10 @@ export class ShardingConfig extends Context.Tag("@effect/cluster/ShardingConfig"
|
|
|
63
63
|
* Shard lock expiration duration.
|
|
64
64
|
*/
|
|
65
65
|
readonly shardLockExpiration: DurationInput
|
|
66
|
+
/**
|
|
67
|
+
* Disable the use of advisory locks for shard locking.
|
|
68
|
+
*/
|
|
69
|
+
readonly shardLockDisableAdvisory: boolean
|
|
66
70
|
/**
|
|
67
71
|
* Start shutting down as soon as an Entity has started shutting down.
|
|
68
72
|
*
|
|
@@ -134,6 +138,7 @@ export const defaults: ShardingConfig["Type"] = {
|
|
|
134
138
|
preemptiveShutdown: true,
|
|
135
139
|
shardLockRefreshInterval: Duration.seconds(10),
|
|
136
140
|
shardLockExpiration: Duration.seconds(35),
|
|
141
|
+
shardLockDisableAdvisory: false,
|
|
137
142
|
entityMailboxCapacity: 4096,
|
|
138
143
|
entityMaxIdleTime: Duration.minutes(1),
|
|
139
144
|
entityRegistrationTimeout: Duration.minutes(1),
|
|
@@ -206,6 +211,10 @@ export const config: Config.Config<ShardingConfig["Type"]> = Config.all({
|
|
|
206
211
|
Config.withDefault(defaults.shardLockExpiration),
|
|
207
212
|
Config.withDescription("Shard lock expiration duration.")
|
|
208
213
|
),
|
|
214
|
+
shardLockDisableAdvisory: Config.boolean("shardLockDisableAdvisory").pipe(
|
|
215
|
+
Config.withDefault(defaults.shardLockDisableAdvisory),
|
|
216
|
+
Config.withDescription("Disable the use of advisory locks for shard locking.")
|
|
217
|
+
),
|
|
209
218
|
entityMailboxCapacity: Config.integer("entityMailboxCapacity").pipe(
|
|
210
219
|
Config.withDefault(defaults.entityMailboxCapacity),
|
|
211
220
|
Config.withDescription("The default capacity of the mailbox for entities.")
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import type * as SqlClient from "@effect/sql/SqlClient"
|
|
5
|
+
import type * as ConfigError from "effect/ConfigError"
|
|
6
|
+
import * as Layer from "effect/Layer"
|
|
7
|
+
import type * as MessageStorage from "./MessageStorage.js"
|
|
8
|
+
import * as RunnerHealth from "./RunnerHealth.js"
|
|
9
|
+
import * as Runners from "./Runners.js"
|
|
10
|
+
import * as RunnerStorage from "./RunnerStorage.js"
|
|
11
|
+
import * as Sharding from "./Sharding.js"
|
|
12
|
+
import * as ShardingConfig from "./ShardingConfig.js"
|
|
13
|
+
import * as SqlMessageStorage from "./SqlMessageStorage.js"
|
|
14
|
+
import * as SqlRunnerStorage from "./SqlRunnerStorage.js"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A sql backed single-node cluster, that can be used for running durable
|
|
18
|
+
* entities and workflows.
|
|
19
|
+
*
|
|
20
|
+
* @since 1.0.0
|
|
21
|
+
* @category Layers
|
|
22
|
+
*/
|
|
23
|
+
export const layer = (options?: {
|
|
24
|
+
readonly shardingConfig?: Partial<ShardingConfig.ShardingConfig["Type"]> | undefined
|
|
25
|
+
readonly runnerStorage?: "memory" | "sql" | undefined
|
|
26
|
+
}): Layer.Layer<
|
|
27
|
+
| Sharding.Sharding
|
|
28
|
+
| Runners.Runners
|
|
29
|
+
| MessageStorage.MessageStorage,
|
|
30
|
+
ConfigError.ConfigError,
|
|
31
|
+
SqlClient.SqlClient
|
|
32
|
+
> =>
|
|
33
|
+
Sharding.layer.pipe(
|
|
34
|
+
Layer.provideMerge(Runners.layerNoop),
|
|
35
|
+
Layer.provideMerge(SqlMessageStorage.layer),
|
|
36
|
+
Layer.provide([
|
|
37
|
+
options?.runnerStorage === "memory" ? RunnerStorage.layerMemory : Layer.orDie(SqlRunnerStorage.layer),
|
|
38
|
+
RunnerHealth.layerNoop
|
|
39
|
+
]),
|
|
40
|
+
Layer.provide(ShardingConfig.layerFromEnv(options?.shardingConfig))
|
|
41
|
+
)
|
package/src/SqlRunnerStorage.ts
CHANGED
|
@@ -25,6 +25,7 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
25
25
|
readonly prefix?: string | undefined
|
|
26
26
|
}) {
|
|
27
27
|
const config = yield* ShardingConfig.ShardingConfig
|
|
28
|
+
const disableAdvisoryLocks = config.shardLockDisableAdvisory
|
|
28
29
|
const sql = (yield* SqlClient.SqlClient).withoutTransforms()
|
|
29
30
|
const prefix = options?.prefix ?? "cluster"
|
|
30
31
|
const table = (name: string) => `${prefix}_${name}`
|
|
@@ -138,8 +139,22 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
138
139
|
acquired_at DATETIME NOT NULL
|
|
139
140
|
)
|
|
140
141
|
`,
|
|
141
|
-
mysql: () =>
|
|
142
|
-
|
|
142
|
+
mysql: () =>
|
|
143
|
+
sql`
|
|
144
|
+
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
145
|
+
shard_id VARCHAR(50) PRIMARY KEY,
|
|
146
|
+
address VARCHAR(255) NOT NULL,
|
|
147
|
+
acquired_at DATETIME NOT NULL
|
|
148
|
+
)
|
|
149
|
+
`,
|
|
150
|
+
pg: () =>
|
|
151
|
+
sql`
|
|
152
|
+
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
153
|
+
shard_id VARCHAR(50) PRIMARY KEY,
|
|
154
|
+
address VARCHAR(255) NOT NULL,
|
|
155
|
+
acquired_at TIMESTAMP NOT NULL
|
|
156
|
+
)
|
|
157
|
+
`,
|
|
143
158
|
orElse: () =>
|
|
144
159
|
// sqlite
|
|
145
160
|
sql`
|
|
@@ -232,6 +247,16 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
232
247
|
Effect.onError(() => lockConn.unsafeRebuild())
|
|
233
248
|
)
|
|
234
249
|
}
|
|
250
|
+
const execWithLockConnUnprepared = <A>(
|
|
251
|
+
effect: Statement.Statement<A>
|
|
252
|
+
): Effect.Effect<ReadonlyArray<ReadonlyArray<any>>, SqlError> => {
|
|
253
|
+
if (!lockConn) return effect.values
|
|
254
|
+
const [query, params] = effect.compile()
|
|
255
|
+
return lockConn.await.pipe(
|
|
256
|
+
Effect.flatMap(([conn]) => conn.executeUnprepared(query, params, undefined)),
|
|
257
|
+
Effect.onError(() => lockConn.unsafeRebuild())
|
|
258
|
+
)
|
|
259
|
+
}
|
|
235
260
|
const execWithLockConnValues = <A>(
|
|
236
261
|
effect: Statement.Statement<A>
|
|
237
262
|
): Effect.Effect<ReadonlyArray<ReadonlyArray<any>>, SqlError> => {
|
|
@@ -244,8 +269,24 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
244
269
|
}
|
|
245
270
|
|
|
246
271
|
const acquireLock = sql.onDialectOrElse({
|
|
247
|
-
pg: () =>
|
|
248
|
-
|
|
272
|
+
pg: () => {
|
|
273
|
+
if (disableAdvisoryLocks) {
|
|
274
|
+
return (address: string, shardIds: ReadonlyArray<string>) => {
|
|
275
|
+
const values = shardIds.map((shardId) =>
|
|
276
|
+
sql`(${stringLiteral(shardId)}, ${stringLiteral(address)}, ${sqlNow})`
|
|
277
|
+
)
|
|
278
|
+
return sql`
|
|
279
|
+
INSERT INTO ${locksTableSql} (shard_id, address, acquired_at) VALUES ${sql.csv(values)}
|
|
280
|
+
ON CONFLICT (shard_id) DO UPDATE
|
|
281
|
+
SET address = ${address}, acquired_at = ${sqlNow}
|
|
282
|
+
WHERE ${locksTableSql}.address = ${address}
|
|
283
|
+
OR ${locksTableSql}.acquired_at < ${lockExpiresAt}
|
|
284
|
+
`.pipe(
|
|
285
|
+
Effect.andThen(acquiredLocks(address, shardIds))
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return Effect.fnUntraced(function*(_address: string, shardIds: ReadonlyArray<string>) {
|
|
249
290
|
const [conn, pid] = yield* lockConn!.await
|
|
250
291
|
const acquiredShardIds: Array<string> = []
|
|
251
292
|
const toAcquire = new Map(shardIds.map((shardId) => [lockNumbers.get(shardId)!, shardId]))
|
|
@@ -269,10 +310,26 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
269
310
|
}
|
|
270
311
|
}
|
|
271
312
|
return acquiredShardIds
|
|
272
|
-
}, Effect.onError(() => lockConn!.unsafeRebuild()))
|
|
313
|
+
}, Effect.onError(() => lockConn!.unsafeRebuild()))
|
|
314
|
+
},
|
|
273
315
|
|
|
274
|
-
mysql: () =>
|
|
275
|
-
|
|
316
|
+
mysql: () => {
|
|
317
|
+
if (disableAdvisoryLocks) {
|
|
318
|
+
return (address: string, shardIds: ReadonlyArray<string>) => {
|
|
319
|
+
const values = shardIds.map((shardId) =>
|
|
320
|
+
sql`(${stringLiteral(shardId)}, ${stringLiteral(address)}, ${sqlNow})`
|
|
321
|
+
)
|
|
322
|
+
return sql`
|
|
323
|
+
INSERT INTO ${locksTableSql} (shard_id, address, acquired_at) VALUES ${sql.csv(values)}
|
|
324
|
+
ON DUPLICATE KEY UPDATE
|
|
325
|
+
address = IF(address = VALUES(address) OR acquired_at < ${lockExpiresAt}, VALUES(address), address),
|
|
326
|
+
acquired_at = IF(address = VALUES(address) OR acquired_at < ${lockExpiresAt}, VALUES(acquired_at), acquired_at)
|
|
327
|
+
`.unprepared.pipe(
|
|
328
|
+
Effect.andThen(acquiredLocks(address, shardIds))
|
|
329
|
+
)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return Effect.fnUntraced(function*(_address: string, shardIds: ReadonlyArray<string>) {
|
|
276
333
|
const [conn, pid] = yield* lockConn!.await
|
|
277
334
|
const takenLocks = (yield* conn.executeValues(`SELECT ${allMySqlTakenLocks}`, []))[0] as Array<number | null>
|
|
278
335
|
const acquiredShardIds: Array<string> = []
|
|
@@ -296,7 +353,8 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
296
353
|
}
|
|
297
354
|
}
|
|
298
355
|
return acquiredShardIds
|
|
299
|
-
}, Effect.onError(() => lockConn!.unsafeRebuild()))
|
|
356
|
+
}, Effect.onError(() => lockConn!.unsafeRebuild()))
|
|
357
|
+
},
|
|
300
358
|
|
|
301
359
|
mssql: () => (address: string, shardIds: ReadonlyArray<string>) => {
|
|
302
360
|
const values = shardIds.map((shardId) => sql`(${stringLiteral(shardId)}, ${stringLiteral(address)}, ${sqlNow})`)
|
|
@@ -399,8 +457,34 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
399
457
|
const stringLiteralArr = (arr: ReadonlyArray<string>) => sql.literal(`(${arr.map(wrapString).join(",")})`)
|
|
400
458
|
|
|
401
459
|
const refreshShards = sql.onDialectOrElse({
|
|
402
|
-
pg: () =>
|
|
403
|
-
|
|
460
|
+
pg: () => {
|
|
461
|
+
if (!disableAdvisoryLocks) return acquireLock
|
|
462
|
+
return (address: string, shardIds: ReadonlyArray<string>) =>
|
|
463
|
+
sql`
|
|
464
|
+
UPDATE ${locksTableSql}
|
|
465
|
+
SET acquired_at = ${sqlNow}
|
|
466
|
+
WHERE address = ${address} AND shard_id IN ${stringLiteralArr(shardIds)}
|
|
467
|
+
RETURNING shard_id
|
|
468
|
+
`.pipe(
|
|
469
|
+
execWithLockConnValues,
|
|
470
|
+
Effect.map((rows) => rows.map((row) => row[0] as string))
|
|
471
|
+
)
|
|
472
|
+
},
|
|
473
|
+
mysql: () => {
|
|
474
|
+
if (!disableAdvisoryLocks) return acquireLock
|
|
475
|
+
return (address: string, shardIds: ReadonlyArray<string>) => {
|
|
476
|
+
const shardIdsStr = stringLiteralArr(shardIds)
|
|
477
|
+
return sql<Array<{ shard_id: string }>>`
|
|
478
|
+
UPDATE ${locksTableSql}
|
|
479
|
+
SET acquired_at = ${sqlNow}
|
|
480
|
+
WHERE address = ${address} AND shard_id IN ${shardIdsStr};
|
|
481
|
+
SELECT shard_id FROM ${locksTableSql} WHERE address = ${address} AND shard_id IN ${shardIdsStr}
|
|
482
|
+
`.pipe(
|
|
483
|
+
execWithLockConnUnprepared,
|
|
484
|
+
Effect.map((rows) => rows[1].map((row) => row.shard_id))
|
|
485
|
+
)
|
|
486
|
+
}
|
|
487
|
+
},
|
|
404
488
|
mssql: () => (address: string, shardIds: ReadonlyArray<string>) =>
|
|
405
489
|
sql`
|
|
406
490
|
UPDATE ${locksTableSql}
|
|
@@ -462,8 +546,14 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
462
546
|
),
|
|
463
547
|
|
|
464
548
|
release: sql.onDialectOrElse({
|
|
465
|
-
pg: () =>
|
|
466
|
-
|
|
549
|
+
pg: () => {
|
|
550
|
+
if (disableAdvisoryLocks) {
|
|
551
|
+
return (address: string, shardId: string) =>
|
|
552
|
+
sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(
|
|
553
|
+
PersistenceError.refail
|
|
554
|
+
)
|
|
555
|
+
}
|
|
556
|
+
return Effect.fnUntraced(
|
|
467
557
|
function*(_address, shardId) {
|
|
468
558
|
const lockNum = lockNumbers.get(shardId)!
|
|
469
559
|
for (let i = 0; i < 5; i++) {
|
|
@@ -481,9 +571,16 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
481
571
|
Effect.onError(() => lockConn!.unsafeRebuild()),
|
|
482
572
|
Effect.asVoid,
|
|
483
573
|
PersistenceError.refail
|
|
484
|
-
)
|
|
485
|
-
|
|
486
|
-
|
|
574
|
+
)
|
|
575
|
+
},
|
|
576
|
+
mysql: () => {
|
|
577
|
+
if (disableAdvisoryLocks) {
|
|
578
|
+
return (address: string, shardId: string) =>
|
|
579
|
+
sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(
|
|
580
|
+
PersistenceError.refail
|
|
581
|
+
)
|
|
582
|
+
}
|
|
583
|
+
return Effect.fnUntraced(
|
|
487
584
|
function*(_address, shardId) {
|
|
488
585
|
const lockName = lockNames.get(shardId)!
|
|
489
586
|
while (true) {
|
|
@@ -499,7 +596,8 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
499
596
|
Effect.onError(() => lockConn!.unsafeRebuild()),
|
|
500
597
|
Effect.asVoid,
|
|
501
598
|
PersistenceError.refail
|
|
502
|
-
)
|
|
599
|
+
)
|
|
600
|
+
},
|
|
503
601
|
orElse: () => (address, shardId) =>
|
|
504
602
|
sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(
|
|
505
603
|
PersistenceError.refail
|
|
@@ -507,20 +605,34 @@ export const make = Effect.fnUntraced(function*(options: {
|
|
|
507
605
|
}),
|
|
508
606
|
|
|
509
607
|
releaseAll: sql.onDialectOrElse({
|
|
510
|
-
pg: () => (
|
|
511
|
-
|
|
608
|
+
pg: () => (address) => {
|
|
609
|
+
if (disableAdvisoryLocks) {
|
|
610
|
+
return sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(
|
|
611
|
+
PersistenceError.refail,
|
|
612
|
+
withTracerDisabled
|
|
613
|
+
)
|
|
614
|
+
}
|
|
615
|
+
return sql`SELECT pg_advisory_unlock_all()`.pipe(
|
|
512
616
|
execWithLockConn,
|
|
513
617
|
Effect.asVoid,
|
|
514
618
|
PersistenceError.refail,
|
|
515
619
|
withTracerDisabled
|
|
516
|
-
)
|
|
517
|
-
|
|
518
|
-
|
|
620
|
+
)
|
|
621
|
+
},
|
|
622
|
+
mysql: () => (address) => {
|
|
623
|
+
if (disableAdvisoryLocks) {
|
|
624
|
+
return sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(
|
|
625
|
+
PersistenceError.refail,
|
|
626
|
+
withTracerDisabled
|
|
627
|
+
)
|
|
628
|
+
}
|
|
629
|
+
return sql`SELECT RELEASE_ALL_LOCKS()`.pipe(
|
|
519
630
|
execWithLockConn,
|
|
520
631
|
Effect.asVoid,
|
|
521
632
|
PersistenceError.refail,
|
|
522
633
|
withTracerDisabled
|
|
523
|
-
)
|
|
634
|
+
)
|
|
635
|
+
},
|
|
524
636
|
orElse: () => (address) =>
|
|
525
637
|
sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(
|
|
526
638
|
PersistenceError.refail,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Layer from "effect/Layer"
|
|
5
|
+
import * as MessageStorage from "./MessageStorage.js"
|
|
6
|
+
import * as RunnerHealth from "./RunnerHealth.js"
|
|
7
|
+
import * as Runners from "./Runners.js"
|
|
8
|
+
import * as RunnerStorage from "./RunnerStorage.js"
|
|
9
|
+
import * as Sharding from "./Sharding.js"
|
|
10
|
+
import * as ShardingConfig from "./ShardingConfig.js"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* An in-memory cluster that can be used for testing purposes.
|
|
14
|
+
*
|
|
15
|
+
* MessageStorage is backed by an in-memory driver, and RunnerStorage is backed
|
|
16
|
+
* by an in-memory driver.
|
|
17
|
+
*
|
|
18
|
+
* @since 1.0.0
|
|
19
|
+
* @category Layers
|
|
20
|
+
*/
|
|
21
|
+
export const layer: Layer.Layer<
|
|
22
|
+
Sharding.Sharding | Runners.Runners | MessageStorage.MessageStorage | MessageStorage.MemoryDriver
|
|
23
|
+
> = Sharding.layer.pipe(
|
|
24
|
+
Layer.provideMerge(Runners.layerNoop),
|
|
25
|
+
Layer.provideMerge(MessageStorage.layerMemory),
|
|
26
|
+
Layer.provide([RunnerStorage.layerMemory, RunnerHealth.layerNoop]),
|
|
27
|
+
Layer.provide(ShardingConfig.layer())
|
|
28
|
+
)
|
package/src/index.ts
CHANGED
|
@@ -148,6 +148,11 @@ export * as ShardingConfig from "./ShardingConfig.js"
|
|
|
148
148
|
*/
|
|
149
149
|
export * as ShardingRegistrationEvent from "./ShardingRegistrationEvent.js"
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* @since 1.0.0
|
|
153
|
+
*/
|
|
154
|
+
export * as SingleRunner from "./SingleRunner.js"
|
|
155
|
+
|
|
151
156
|
/**
|
|
152
157
|
* @since 1.0.0
|
|
153
158
|
*/
|
|
@@ -177,3 +182,8 @@ export * as SqlMessageStorage from "./SqlMessageStorage.js"
|
|
|
177
182
|
* @since 1.0.0
|
|
178
183
|
*/
|
|
179
184
|
export * as SqlRunnerStorage from "./SqlRunnerStorage.js"
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @since 1.0.0
|
|
188
|
+
*/
|
|
189
|
+
export * as TestRunner from "./TestRunner.js"
|