@effect/cluster 0.50.6 → 0.52.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/RunnerStorage/package.json +6 -0
- package/SqlRunnerStorage/package.json +6 -0
- package/dist/cjs/ClusterError.js +2 -24
- package/dist/cjs/ClusterError.js.map +1 -1
- package/dist/cjs/ClusterMetrics.js +13 -15
- package/dist/cjs/ClusterMetrics.js.map +1 -1
- package/dist/cjs/ClusterSchema.js +17 -2
- package/dist/cjs/ClusterSchema.js.map +1 -1
- package/dist/cjs/ClusterWorkflowEngine.js +50 -83
- package/dist/cjs/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cjs/Entity.js +1 -13
- package/dist/cjs/Entity.js.map +1 -1
- package/dist/cjs/EntityAddress.js +9 -1
- package/dist/cjs/EntityAddress.js.map +1 -1
- package/dist/cjs/EntityId.js +7 -1
- package/dist/cjs/EntityId.js.map +1 -1
- package/dist/cjs/EntityProxy.js +1 -1
- package/dist/cjs/EntityProxy.js.map +1 -1
- package/dist/cjs/HttpRunner.js +69 -43
- package/dist/cjs/HttpRunner.js.map +1 -1
- package/dist/cjs/MessageStorage.js +64 -16
- package/dist/cjs/MessageStorage.js.map +1 -1
- package/dist/cjs/Runner.js +3 -3
- package/dist/cjs/Runner.js.map +1 -1
- package/dist/cjs/RunnerAddress.js +7 -0
- package/dist/cjs/RunnerAddress.js.map +1 -1
- package/dist/cjs/RunnerHealth.js +91 -32
- package/dist/cjs/RunnerHealth.js.map +1 -1
- package/dist/cjs/RunnerServer.js +38 -24
- package/dist/cjs/RunnerServer.js.map +1 -1
- package/dist/cjs/RunnerStorage.js +100 -0
- package/dist/cjs/RunnerStorage.js.map +1 -0
- package/dist/cjs/Runners.js +18 -22
- package/dist/cjs/Runners.js.map +1 -1
- package/dist/cjs/ShardId.js +17 -7
- package/dist/cjs/ShardId.js.map +1 -1
- package/dist/cjs/Sharding.js +444 -320
- package/dist/cjs/Sharding.js.map +1 -1
- package/dist/cjs/ShardingConfig.js +10 -14
- package/dist/cjs/ShardingConfig.js.map +1 -1
- package/dist/cjs/Snowflake.js +1 -1
- package/dist/cjs/SocketRunner.js +1 -1
- package/dist/cjs/SocketRunner.js.map +1 -1
- package/dist/cjs/SqlMessageStorage.js +22 -28
- package/dist/cjs/SqlMessageStorage.js.map +1 -1
- package/dist/cjs/SqlRunnerStorage.js +375 -0
- package/dist/cjs/SqlRunnerStorage.js.map +1 -0
- package/dist/cjs/index.js +5 -15
- package/dist/cjs/internal/entityManager.js +42 -23
- package/dist/cjs/internal/entityManager.js.map +1 -1
- package/dist/dts/ClusterError.d.ts +0 -22
- package/dist/dts/ClusterError.d.ts.map +1 -1
- package/dist/dts/ClusterMetrics.d.ts +4 -14
- package/dist/dts/ClusterMetrics.d.ts.map +1 -1
- package/dist/dts/ClusterSchema.d.ts +9 -1
- package/dist/dts/ClusterSchema.d.ts.map +1 -1
- package/dist/dts/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/dts/Entity.d.ts +3 -14
- package/dist/dts/Entity.d.ts.map +1 -1
- package/dist/dts/EntityAddress.d.ts +11 -0
- package/dist/dts/EntityAddress.d.ts.map +1 -1
- package/dist/dts/EntityId.d.ts +5 -0
- package/dist/dts/EntityId.d.ts.map +1 -1
- package/dist/dts/EntityProxy.d.ts +5 -6
- package/dist/dts/EntityProxy.d.ts.map +1 -1
- package/dist/dts/HttpRunner.d.ts +48 -25
- package/dist/dts/HttpRunner.d.ts.map +1 -1
- package/dist/dts/MessageStorage.d.ts +13 -5
- package/dist/dts/MessageStorage.d.ts.map +1 -1
- package/dist/dts/Runner.d.ts +4 -4
- package/dist/dts/Runner.d.ts.map +1 -1
- package/dist/dts/RunnerAddress.d.ts +5 -0
- package/dist/dts/RunnerAddress.d.ts.map +1 -1
- package/dist/dts/RunnerHealth.d.ts +24 -16
- package/dist/dts/RunnerHealth.d.ts.map +1 -1
- package/dist/dts/RunnerServer.d.ts +5 -4
- package/dist/dts/RunnerServer.d.ts.map +1 -1
- package/dist/dts/{ShardStorage.d.ts → RunnerStorage.d.ts} +41 -54
- package/dist/dts/RunnerStorage.d.ts.map +1 -0
- package/dist/dts/Runners.d.ts +15 -11
- package/dist/dts/Runners.d.ts.map +1 -1
- package/dist/dts/ShardId.d.ts +1 -1
- package/dist/dts/ShardId.d.ts.map +1 -1
- package/dist/dts/Sharding.d.ts +20 -10
- package/dist/dts/Sharding.d.ts.map +1 -1
- package/dist/dts/ShardingConfig.d.ts +40 -14
- package/dist/dts/ShardingConfig.d.ts.map +1 -1
- package/dist/dts/SocketRunner.d.ts +4 -3
- package/dist/dts/SocketRunner.d.ts.map +1 -1
- package/dist/dts/SqlMessageStorage.d.ts +2 -3
- package/dist/dts/SqlMessageStorage.d.ts.map +1 -1
- package/dist/dts/SqlRunnerStorage.d.ts +40 -0
- package/dist/dts/SqlRunnerStorage.d.ts.map +1 -0
- package/dist/dts/index.d.ts +4 -24
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/ClusterError.js +0 -21
- package/dist/esm/ClusterError.js.map +1 -1
- package/dist/esm/ClusterMetrics.js +12 -14
- package/dist/esm/ClusterMetrics.js.map +1 -1
- package/dist/esm/ClusterSchema.js +17 -2
- package/dist/esm/ClusterSchema.js.map +1 -1
- package/dist/esm/ClusterWorkflowEngine.js +50 -83
- package/dist/esm/ClusterWorkflowEngine.js.map +1 -1
- package/dist/esm/Entity.js +0 -12
- package/dist/esm/Entity.js.map +1 -1
- package/dist/esm/EntityAddress.js +7 -0
- package/dist/esm/EntityAddress.js.map +1 -1
- package/dist/esm/EntityId.js +5 -0
- package/dist/esm/EntityId.js.map +1 -1
- package/dist/esm/EntityProxy.js +2 -2
- package/dist/esm/EntityProxy.js.map +1 -1
- package/dist/esm/HttpRunner.js +62 -39
- package/dist/esm/HttpRunner.js.map +1 -1
- package/dist/esm/MessageStorage.js +65 -17
- package/dist/esm/MessageStorage.js.map +1 -1
- package/dist/esm/Runner.js +3 -3
- package/dist/esm/Runner.js.map +1 -1
- package/dist/esm/RunnerAddress.js +7 -0
- package/dist/esm/RunnerAddress.js.map +1 -1
- package/dist/esm/RunnerHealth.js +88 -30
- package/dist/esm/RunnerHealth.js.map +1 -1
- package/dist/esm/RunnerServer.js +38 -24
- package/dist/esm/RunnerServer.js.map +1 -1
- package/dist/esm/RunnerStorage.js +90 -0
- package/dist/esm/RunnerStorage.js.map +1 -0
- package/dist/esm/Runners.js +19 -23
- package/dist/esm/Runners.js.map +1 -1
- package/dist/esm/ShardId.js +16 -6
- package/dist/esm/ShardId.js.map +1 -1
- package/dist/esm/Sharding.js +447 -323
- package/dist/esm/Sharding.js.map +1 -1
- package/dist/esm/ShardingConfig.js +10 -14
- package/dist/esm/ShardingConfig.js.map +1 -1
- package/dist/esm/Snowflake.js +1 -1
- package/dist/esm/SocketRunner.js +1 -1
- package/dist/esm/SocketRunner.js.map +1 -1
- package/dist/esm/SqlMessageStorage.js +22 -28
- package/dist/esm/SqlMessageStorage.js.map +1 -1
- package/dist/esm/SqlRunnerStorage.js +366 -0
- package/dist/esm/SqlRunnerStorage.js.map +1 -0
- package/dist/esm/index.js +4 -24
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/entityManager.js +41 -22
- package/dist/esm/internal/entityManager.js.map +1 -1
- package/package.json +20 -60
- package/src/ClusterError.ts +0 -24
- package/src/ClusterMetrics.ts +12 -16
- package/src/ClusterSchema.ts +17 -2
- package/src/ClusterWorkflowEngine.ts +48 -80
- package/src/Entity.ts +3 -21
- package/src/EntityAddress.ts +10 -0
- package/src/EntityId.ts +6 -0
- package/src/EntityProxy.ts +10 -10
- package/src/HttpRunner.ts +132 -67
- package/src/MessageStorage.ts +89 -24
- package/src/Runner.ts +4 -4
- package/src/RunnerAddress.ts +8 -0
- package/src/RunnerHealth.ts +119 -56
- package/src/RunnerServer.ts +64 -47
- package/src/RunnerStorage.ts +218 -0
- package/src/Runners.ts +32 -45
- package/src/ShardId.ts +14 -3
- package/src/Sharding.ts +561 -417
- package/src/ShardingConfig.ts +39 -31
- package/src/Snowflake.ts +1 -1
- package/src/SocketRunner.ts +6 -4
- package/src/SqlMessageStorage.ts +28 -30
- package/src/SqlRunnerStorage.ts +537 -0
- package/src/index.ts +4 -29
- package/src/internal/entityManager.ts +45 -29
- package/HttpCommon/package.json +0 -6
- package/HttpShardManager/package.json +0 -6
- package/ShardManager/package.json +0 -6
- package/ShardStorage/package.json +0 -6
- package/SocketShardManager/package.json +0 -6
- package/SqlShardStorage/package.json +0 -6
- package/SynchronizedClock/package.json +0 -6
- package/dist/cjs/HttpCommon.js +0 -48
- package/dist/cjs/HttpCommon.js.map +0 -1
- package/dist/cjs/HttpShardManager.js +0 -139
- package/dist/cjs/HttpShardManager.js.map +0 -1
- package/dist/cjs/ShardManager.js +0 -549
- package/dist/cjs/ShardManager.js.map +0 -1
- package/dist/cjs/ShardStorage.js +0 -151
- package/dist/cjs/ShardStorage.js.map +0 -1
- package/dist/cjs/SocketShardManager.js +0 -32
- package/dist/cjs/SocketShardManager.js.map +0 -1
- package/dist/cjs/SqlShardStorage.js +0 -253
- package/dist/cjs/SqlShardStorage.js.map +0 -1
- package/dist/cjs/SynchronizedClock.js +0 -65
- package/dist/cjs/SynchronizedClock.js.map +0 -1
- package/dist/cjs/internal/shardManager.js +0 -353
- package/dist/cjs/internal/shardManager.js.map +0 -1
- package/dist/dts/HttpCommon.d.ts +0 -25
- package/dist/dts/HttpCommon.d.ts.map +0 -1
- package/dist/dts/HttpShardManager.d.ts +0 -119
- package/dist/dts/HttpShardManager.d.ts.map +0 -1
- package/dist/dts/ShardManager.d.ts +0 -459
- package/dist/dts/ShardManager.d.ts.map +0 -1
- package/dist/dts/ShardStorage.d.ts.map +0 -1
- package/dist/dts/SocketShardManager.d.ts +0 -17
- package/dist/dts/SocketShardManager.d.ts.map +0 -1
- package/dist/dts/SqlShardStorage.d.ts +0 -38
- package/dist/dts/SqlShardStorage.d.ts.map +0 -1
- package/dist/dts/SynchronizedClock.d.ts +0 -19
- package/dist/dts/SynchronizedClock.d.ts.map +0 -1
- package/dist/dts/internal/shardManager.d.ts +0 -2
- package/dist/dts/internal/shardManager.d.ts.map +0 -1
- package/dist/esm/HttpCommon.js +0 -38
- package/dist/esm/HttpCommon.js.map +0 -1
- package/dist/esm/HttpShardManager.js +0 -128
- package/dist/esm/HttpShardManager.js.map +0 -1
- package/dist/esm/ShardManager.js +0 -535
- package/dist/esm/ShardManager.js.map +0 -1
- package/dist/esm/ShardStorage.js +0 -141
- package/dist/esm/ShardStorage.js.map +0 -1
- package/dist/esm/SocketShardManager.js +0 -24
- package/dist/esm/SocketShardManager.js.map +0 -1
- package/dist/esm/SqlShardStorage.js +0 -244
- package/dist/esm/SqlShardStorage.js.map +0 -1
- package/dist/esm/SynchronizedClock.js +0 -57
- package/dist/esm/SynchronizedClock.js.map +0 -1
- package/dist/esm/internal/shardManager.js +0 -342
- package/dist/esm/internal/shardManager.js.map +0 -1
- package/src/HttpCommon.ts +0 -73
- package/src/HttpShardManager.ts +0 -273
- package/src/ShardManager.ts +0 -823
- package/src/ShardStorage.ts +0 -297
- package/src/SocketShardManager.ts +0 -48
- package/src/SqlShardStorage.ts +0 -329
- package/src/SynchronizedClock.ts +0 -82
- package/src/internal/shardManager.ts +0 -412
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as SqlClient from "@effect/sql/SqlClient";
|
|
5
|
+
import * as Arr from "effect/Array";
|
|
6
|
+
import * as Duration from "effect/Duration";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import * as Layer from "effect/Layer";
|
|
9
|
+
import * as Resource from "effect/Resource";
|
|
10
|
+
import { PersistenceError } from "./ClusterError.js";
|
|
11
|
+
import * as RunnerStorage from "./RunnerStorage.js";
|
|
12
|
+
import * as ShardId from "./ShardId.js";
|
|
13
|
+
import * as ShardingConfig from "./ShardingConfig.js";
|
|
14
|
+
const withTracerDisabled = /*#__PURE__*/Effect.withTracerEnabled(false);
|
|
15
|
+
/**
|
|
16
|
+
* @since 1.0.0
|
|
17
|
+
* @category Constructors
|
|
18
|
+
*/
|
|
19
|
+
export const make = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
20
|
+
const config = yield* ShardingConfig.ShardingConfig;
|
|
21
|
+
const sql = (yield* SqlClient.SqlClient).withoutTransforms();
|
|
22
|
+
const prefix = options?.prefix ?? "cluster";
|
|
23
|
+
const table = name => `${prefix}_${name}`;
|
|
24
|
+
const acquireLockConn = sql.onDialectOrElse({
|
|
25
|
+
pg: () => Effect.gen(function* () {
|
|
26
|
+
const conn = yield* Effect.orDie(sql.reserve);
|
|
27
|
+
yield* Effect.addFinalizer(() => Effect.orDie(conn.executeRaw("SELECT pg_advisory_unlock_all()", [])));
|
|
28
|
+
return conn;
|
|
29
|
+
}),
|
|
30
|
+
mysql: () => Effect.gen(function* () {
|
|
31
|
+
const conn = yield* Effect.orDie(sql.reserve);
|
|
32
|
+
yield* Effect.addFinalizer(() => Effect.orDie(conn.executeRaw("SELECT RELEASE_ALL_LOCKS()", [])));
|
|
33
|
+
return conn;
|
|
34
|
+
}),
|
|
35
|
+
orElse: () => undefined
|
|
36
|
+
});
|
|
37
|
+
const lockConnRef = acquireLockConn && (yield* Resource.manual(acquireLockConn));
|
|
38
|
+
const runnersTable = table("runners");
|
|
39
|
+
const runnersTableSql = sql(runnersTable);
|
|
40
|
+
// Migrate old tables if they exist
|
|
41
|
+
// TODO: Remove in next major version
|
|
42
|
+
const hasOldTables = yield* sql`SELECT shard_id FROM ${sql(table("shards"))} LIMIT 1`.pipe(Effect.isSuccess);
|
|
43
|
+
if (hasOldTables) {
|
|
44
|
+
yield* sql`DROP TABLE ${sql(table("shards"))}`.pipe(Effect.ignore);
|
|
45
|
+
yield* sql`DROP TABLE ${runnersTableSql}`.pipe(Effect.ignore);
|
|
46
|
+
}
|
|
47
|
+
yield* sql.onDialectOrElse({
|
|
48
|
+
mssql: () => sql`
|
|
49
|
+
IF OBJECT_ID(N'${runnersTableSql}', N'U') IS NULL
|
|
50
|
+
CREATE TABLE ${runnersTableSql} (
|
|
51
|
+
machine_id INT IDENTITY PRIMARY KEY,
|
|
52
|
+
address VARCHAR(255) NOT NULL,
|
|
53
|
+
runner TEXT NOT NULL,
|
|
54
|
+
healthy BIT NOT NULL DEFAULT 1,
|
|
55
|
+
last_heartbeat DATETIME NOT NULL DEFAULT GETDATE(),
|
|
56
|
+
UNIQUE(address)
|
|
57
|
+
)
|
|
58
|
+
`,
|
|
59
|
+
mysql: () => sql`
|
|
60
|
+
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
61
|
+
machine_id INT AUTO_INCREMENT PRIMARY KEY,
|
|
62
|
+
address VARCHAR(255) NOT NULL,
|
|
63
|
+
runner TEXT NOT NULL,
|
|
64
|
+
healthy BOOLEAN NOT NULL DEFAULT TRUE,
|
|
65
|
+
last_heartbeat DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
66
|
+
UNIQUE(address)
|
|
67
|
+
)
|
|
68
|
+
`,
|
|
69
|
+
pg: () => sql`
|
|
70
|
+
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
71
|
+
machine_id SERIAL PRIMARY KEY,
|
|
72
|
+
address VARCHAR(255) NOT NULL,
|
|
73
|
+
runner TEXT NOT NULL,
|
|
74
|
+
healthy BOOLEAN NOT NULL DEFAULT TRUE,
|
|
75
|
+
last_heartbeat TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
76
|
+
UNIQUE(address)
|
|
77
|
+
)
|
|
78
|
+
`,
|
|
79
|
+
orElse: () =>
|
|
80
|
+
// sqlite
|
|
81
|
+
sql`
|
|
82
|
+
CREATE TABLE IF NOT EXISTS ${runnersTableSql} (
|
|
83
|
+
machine_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
84
|
+
address TEXT NOT NULL,
|
|
85
|
+
runner TEXT NOT NULL,
|
|
86
|
+
healthy INTEGER NOT NULL DEFAULT 1,
|
|
87
|
+
last_heartbeat DATETIME NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
|
88
|
+
UNIQUE(address)
|
|
89
|
+
)
|
|
90
|
+
`
|
|
91
|
+
});
|
|
92
|
+
const locksTable = table("locks");
|
|
93
|
+
const locksTableSql = sql(locksTable);
|
|
94
|
+
yield* sql.onDialectOrElse({
|
|
95
|
+
mssql: () => sql`
|
|
96
|
+
IF OBJECT_ID(N'${locksTableSql}', N'U') IS NULL
|
|
97
|
+
CREATE TABLE ${locksTableSql} (
|
|
98
|
+
shard_id VARCHAR(50) PRIMARY KEY,
|
|
99
|
+
address VARCHAR(255) NOT NULL,
|
|
100
|
+
acquired_at DATETIME NOT NULL
|
|
101
|
+
)
|
|
102
|
+
`,
|
|
103
|
+
mysql: () => Effect.void,
|
|
104
|
+
pg: () => Effect.void,
|
|
105
|
+
orElse: () =>
|
|
106
|
+
// sqlite
|
|
107
|
+
sql`
|
|
108
|
+
CREATE TABLE IF NOT EXISTS ${locksTableSql} (
|
|
109
|
+
shard_id TEXT PRIMARY KEY,
|
|
110
|
+
address TEXT NOT NULL,
|
|
111
|
+
acquired_at DATETIME NOT NULL
|
|
112
|
+
)
|
|
113
|
+
`
|
|
114
|
+
});
|
|
115
|
+
const sqlNowString = sql.onDialectOrElse({
|
|
116
|
+
pg: () => "NOW()",
|
|
117
|
+
mysql: () => "NOW()",
|
|
118
|
+
mssql: () => "GETDATE()",
|
|
119
|
+
orElse: () => "CURRENT_TIMESTAMP"
|
|
120
|
+
});
|
|
121
|
+
const sqlNow = sql.literal(sqlNowString);
|
|
122
|
+
const expiresSeconds = sql.literal(Math.ceil(Duration.toSeconds(config.shardLockExpiration)).toString());
|
|
123
|
+
const lockExpiresAt = sql.onDialectOrElse({
|
|
124
|
+
pg: () => sql`${sqlNow} - INTERVAL '${expiresSeconds} seconds'`,
|
|
125
|
+
mysql: () => sql`DATE_SUB(${sqlNow}, INTERVAL ${expiresSeconds} SECOND)`,
|
|
126
|
+
mssql: () => sql`DATEADD(SECOND, -${expiresSeconds}, ${sqlNow})`,
|
|
127
|
+
orElse: () => sql`datetime(${sqlNow}, '-${expiresSeconds} seconds')`
|
|
128
|
+
});
|
|
129
|
+
const encodeBoolean = sql.onDialectOrElse({
|
|
130
|
+
mssql: () => b => b ? 1 : 0,
|
|
131
|
+
sqlite: () => b => b ? 1 : 0,
|
|
132
|
+
orElse: () => b => b
|
|
133
|
+
});
|
|
134
|
+
// Upsert runner and return machine_id
|
|
135
|
+
const insertRunner = sql.onDialectOrElse({
|
|
136
|
+
mssql: () => (address, runner, healthy) => sql`
|
|
137
|
+
MERGE ${runnersTableSql} AS target
|
|
138
|
+
USING (SELECT ${address} AS address, ${runner} AS runner, ${sqlNow} AS last_heartbeat, ${encodeBoolean(healthy)} AS healthy) AS source
|
|
139
|
+
ON target.address = source.address
|
|
140
|
+
WHEN MATCHED THEN
|
|
141
|
+
UPDATE SET runner = source.runner, last_heartbeat = source.last_heartbeat, healthy = source.healthy
|
|
142
|
+
WHEN NOT MATCHED THEN
|
|
143
|
+
INSERT (address, runner, last_heartbeat, healthy)
|
|
144
|
+
VALUES (source.address, source.runner, source.last_heartbeat, source.healthy)
|
|
145
|
+
OUTPUT INSERTED.machine_id;
|
|
146
|
+
`.values,
|
|
147
|
+
mysql: () => (address, runner, healthy) => sql`
|
|
148
|
+
INSERT INTO ${runnersTableSql} (address, runner, last_heartbeat, healthy)
|
|
149
|
+
VALUES (${address}, ${runner}, ${sqlNow}, ${healthy})
|
|
150
|
+
ON DUPLICATE KEY UPDATE
|
|
151
|
+
runner = VALUES(runner),
|
|
152
|
+
last_heartbeat = VALUES(last_heartbeat),
|
|
153
|
+
healthy = VALUES(healthy);
|
|
154
|
+
SELECT machine_id FROM ${runnersTableSql} WHERE address = ${address};
|
|
155
|
+
`.unprepared.pipe(Effect.map(results => [[results[1][0].machine_id]])),
|
|
156
|
+
pg: () => (address, runner, healthy) => sql`
|
|
157
|
+
INSERT INTO ${runnersTableSql} (address, runner, last_heartbeat, healthy)
|
|
158
|
+
VALUES (${address}, ${runner}, ${sqlNow}, ${healthy})
|
|
159
|
+
ON CONFLICT (address) DO UPDATE
|
|
160
|
+
SET runner = EXCLUDED.runner,
|
|
161
|
+
last_heartbeat = EXCLUDED.last_heartbeat,
|
|
162
|
+
healthy = EXCLUDED.healthy
|
|
163
|
+
RETURNING machine_id
|
|
164
|
+
`.values,
|
|
165
|
+
orElse: () => (address, runner, healthy) =>
|
|
166
|
+
// sqlite
|
|
167
|
+
sql`
|
|
168
|
+
INSERT INTO ${runnersTableSql} (address, runner, last_heartbeat, healthy)
|
|
169
|
+
VALUES (${address}, ${runner}, ${sqlNow}, ${encodeBoolean(healthy)})
|
|
170
|
+
ON CONFLICT(address) DO UPDATE SET
|
|
171
|
+
runner = excluded.runner,
|
|
172
|
+
last_heartbeat = excluded.last_heartbeat,
|
|
173
|
+
healthy = excluded.healthy
|
|
174
|
+
RETURNING machine_id;
|
|
175
|
+
`.values
|
|
176
|
+
});
|
|
177
|
+
const execWithLockConn = effect => {
|
|
178
|
+
if (!lockConnRef) return effect;
|
|
179
|
+
const [query, params] = effect.compile();
|
|
180
|
+
return Resource.get(lockConnRef).pipe(Effect.flatMap(conn => conn.executeRaw(query, params)), Effect.onError(() => Resource.refresh(lockConnRef)));
|
|
181
|
+
};
|
|
182
|
+
const execWithLockConnValues = effect => {
|
|
183
|
+
if (!lockConnRef) return effect.values;
|
|
184
|
+
const [query, params] = effect.compile();
|
|
185
|
+
return Resource.get(lockConnRef).pipe(Effect.flatMap(conn => conn.executeValues(query, params)), Effect.onError(() => Resource.refresh(lockConnRef)));
|
|
186
|
+
};
|
|
187
|
+
const acquireLock = sql.onDialectOrElse({
|
|
188
|
+
pg: () => Effect.fnUntraced(function* (_address, shardIds) {
|
|
189
|
+
const conn = yield* Resource.get(lockConnRef);
|
|
190
|
+
const acquiredShardIds = [];
|
|
191
|
+
const toAcquire = new Map(shardIds.map(shardId => [lockNumbers.get(shardId), shardId]));
|
|
192
|
+
const takenLocks = yield* conn.executeValues(`SELECT objid FROM pg_locks WHERE locktype = 'advisory' AND granted = true AND pid = pg_backend_pid() ORDER BY objid`, []);
|
|
193
|
+
for (let i = 0; i < takenLocks.length; i++) {
|
|
194
|
+
const lockNum = takenLocks[i][0];
|
|
195
|
+
acquiredShardIds.push(lockNumbersReverse.get(lockNum));
|
|
196
|
+
toAcquire.delete(lockNum);
|
|
197
|
+
}
|
|
198
|
+
if (toAcquire.size === 0) {
|
|
199
|
+
return acquiredShardIds;
|
|
200
|
+
}
|
|
201
|
+
const results = (yield* conn.executeUnprepared(`SELECT ${pgLocks(toAcquire)}`, [], undefined))[0];
|
|
202
|
+
for (const shardId in results) {
|
|
203
|
+
if (results[shardId]) {
|
|
204
|
+
acquiredShardIds.push(shardId);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return acquiredShardIds;
|
|
208
|
+
}, Effect.onError(() => Resource.refresh(lockConnRef))),
|
|
209
|
+
mysql: () => Effect.fnUntraced(function* (_address, shardIds) {
|
|
210
|
+
const conn = yield* Resource.get(lockConnRef);
|
|
211
|
+
const takenLocks = (yield* conn.executeUnprepared(`SELECT ${allMySqlTakenLocks}`, [], undefined))[0];
|
|
212
|
+
const acquiredShardIds = [];
|
|
213
|
+
const toAcquire = [];
|
|
214
|
+
for (const shardId in takenLocks) {
|
|
215
|
+
if (takenLocks[shardId] === 1) {
|
|
216
|
+
acquiredShardIds.push(shardId);
|
|
217
|
+
} else if (shardIds.includes(shardId)) {
|
|
218
|
+
toAcquire.push(shardId);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (toAcquire.length === 0) {
|
|
222
|
+
return acquiredShardIds;
|
|
223
|
+
}
|
|
224
|
+
const results = (yield* conn.executeUnprepared(`SELECT ${mysqlLocks(toAcquire)}`, [], undefined))[0];
|
|
225
|
+
for (const shardId in results) {
|
|
226
|
+
if (results[shardId] === 1) {
|
|
227
|
+
acquiredShardIds.push(shardId);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return acquiredShardIds;
|
|
231
|
+
}, Effect.onError(() => Resource.refresh(lockConnRef))),
|
|
232
|
+
mssql: () => (address, shardIds) => {
|
|
233
|
+
const values = shardIds.map(shardId => sql`(${stringLiteral(shardId)}, ${stringLiteral(address)}, ${sqlNow})`);
|
|
234
|
+
return sql`
|
|
235
|
+
MERGE ${locksTableSql} WITH (HOLDLOCK) AS target
|
|
236
|
+
USING (SELECT * FROM (VALUES ${sql.csv(values)})) AS source (shard_id, address, acquired_at)
|
|
237
|
+
ON target.shard_id = source.shard_id
|
|
238
|
+
WHEN MATCHED AND (target.address = source.address OR DATEDIFF(SECOND, target.acquired_at, ${sqlNow}) > ${expiresSeconds}) THEN
|
|
239
|
+
UPDATE SET address = source.address, acquired_at = source.acquired_at
|
|
240
|
+
WHEN NOT MATCHED THEN
|
|
241
|
+
INSERT (shard_id, address, acquired_at)
|
|
242
|
+
VALUES (source.shard_id, source.address, source.acquired_at);
|
|
243
|
+
`.pipe(Effect.andThen(acquiredLocks(address, shardIds)), sql.withTransaction);
|
|
244
|
+
},
|
|
245
|
+
orElse: () => (address, shardIds) => {
|
|
246
|
+
const values = shardIds.map(shardId => sql`(${stringLiteral(shardId)}, ${stringLiteral(address)}, ${sqlNow})`);
|
|
247
|
+
return sql`
|
|
248
|
+
WITH source(shard_id, address, acquired_at) AS (VALUES ${sql.csv(values)})
|
|
249
|
+
INSERT INTO ${locksTableSql} (shard_id, address, acquired_at)
|
|
250
|
+
SELECT source.shard_id, source.address, source.acquired_at
|
|
251
|
+
FROM source
|
|
252
|
+
WHERE NOT EXISTS (
|
|
253
|
+
SELECT 1 FROM ${locksTableSql}
|
|
254
|
+
WHERE shard_id = source.shard_id
|
|
255
|
+
AND address != ${address}
|
|
256
|
+
AND (strftime('%s', ${sqlNow}) - strftime('%s', acquired_at)) <= ${expiresSeconds}
|
|
257
|
+
)
|
|
258
|
+
ON CONFLICT(shard_id) DO UPDATE
|
|
259
|
+
SET address = ${address}, acquired_at = ${sqlNow}
|
|
260
|
+
`.pipe(Effect.andThen(acquiredLocks(address, shardIds)), sql.withTransaction);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
const lockNumbers = new Map();
|
|
264
|
+
const lockNumbersReverse = new Map();
|
|
265
|
+
for (let i = 0; i < config.shardGroups.length; i++) {
|
|
266
|
+
const group = config.shardGroups[i];
|
|
267
|
+
const base = (i + 1) * 1000000;
|
|
268
|
+
for (let shard = 1; shard <= config.shardsPerGroup; shard++) {
|
|
269
|
+
const shardId = ShardId.make(group, shard).toString();
|
|
270
|
+
const lockNum = base + shard;
|
|
271
|
+
lockNumbers.set(shardId, lockNum);
|
|
272
|
+
lockNumbersReverse.set(lockNum, shardId);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const lockNames = new Map();
|
|
276
|
+
const lockNamesReverse = new Map();
|
|
277
|
+
for (let i = 0; i < config.shardGroups.length; i++) {
|
|
278
|
+
const group = config.shardGroups[i];
|
|
279
|
+
for (let shard = 1; shard <= config.shardsPerGroup; shard++) {
|
|
280
|
+
const shardId = ShardId.make(group, shard).toString();
|
|
281
|
+
const lockName = `${prefix}.${shardId}`;
|
|
282
|
+
lockNames.set(shardId, lockName);
|
|
283
|
+
lockNamesReverse.set(lockName, shardId);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const pgLocks = shardIdsMap => Array.from(shardIdsMap.entries(), ([lockNum, shardId]) => `pg_try_advisory_lock(${lockNum}) AS "${shardId}"`).join(", ");
|
|
287
|
+
const mysqlLocks = shardIds => shardIds.map(shardId => `GET_LOCK('${lockNames.get(shardId)}', 0) AS "${shardId}"`).join(", ");
|
|
288
|
+
const allMySqlTakenLocks = Array.from(lockNames.entries(), ([shardId, lockName]) => `IS_USED_LOCK('${lockName}') = CONNECTION_ID() AS "${shardId}"`).join(", ");
|
|
289
|
+
const acquiredLocks = (address, shardIds) => sql`
|
|
290
|
+
SELECT shard_id FROM ${sql(locksTable)}
|
|
291
|
+
WHERE address = ${address}
|
|
292
|
+
AND acquired_at >= ${lockExpiresAt}
|
|
293
|
+
AND shard_id IN ${stringLiteralArr(shardIds)}
|
|
294
|
+
`.values.pipe(Effect.map(rows => rows.map(row => row[0])));
|
|
295
|
+
const wrapString = sql.onDialectOrElse({
|
|
296
|
+
mssql: () => s => `N'${s}'`,
|
|
297
|
+
orElse: () => s => `'${s}'`
|
|
298
|
+
});
|
|
299
|
+
const stringLiteral = s => sql.literal(wrapString(s));
|
|
300
|
+
const stringLiteralArr = arr => sql.literal(`(${arr.map(wrapString).join(",")})`);
|
|
301
|
+
const refreshShards = sql.onDialectOrElse({
|
|
302
|
+
pg: () => acquireLock,
|
|
303
|
+
mysql: () => acquireLock,
|
|
304
|
+
mssql: () => (address, shardIds) => sql`
|
|
305
|
+
UPDATE ${locksTableSql}
|
|
306
|
+
SET acquired_at = ${sqlNow}
|
|
307
|
+
OUTPUT inserted.shard_id
|
|
308
|
+
WHERE address = ${address} AND shard_id IN ${stringLiteralArr(shardIds)}
|
|
309
|
+
`.pipe(execWithLockConnValues, Effect.map(rows => rows.map(row => row[0]))),
|
|
310
|
+
orElse: () => (address, shardIds) => sql`
|
|
311
|
+
UPDATE ${locksTableSql}
|
|
312
|
+
SET acquired_at = ${sqlNow}
|
|
313
|
+
WHERE address = ${address} AND shard_id IN ${stringLiteralArr(shardIds)}
|
|
314
|
+
RETURNING shard_id
|
|
315
|
+
`.pipe(execWithLockConnValues, Effect.map(rows => rows.map(row => row[0])))
|
|
316
|
+
});
|
|
317
|
+
return RunnerStorage.makeEncoded({
|
|
318
|
+
getRunners: sql`SELECT runner, healthy FROM ${runnersTableSql} WHERE last_heartbeat > ${lockExpiresAt}`.values.pipe(PersistenceError.refail, Effect.map(Arr.map(([runner, healthy]) => [String(runner), Boolean(healthy)])), withTracerDisabled),
|
|
319
|
+
register: (address, runner, healthy) => insertRunner(address, runner, healthy).pipe(Effect.map(rows => Number(rows[0][0])), PersistenceError.refail, withTracerDisabled),
|
|
320
|
+
unregister: address => sql`DELETE FROM ${runnersTableSql} WHERE address = ${address} OR last_heartbeat < ${lockExpiresAt}`.pipe(Effect.asVoid, PersistenceError.refail, withTracerDisabled),
|
|
321
|
+
setRunnerHealth: (address, healthy) => sql`UPDATE ${runnersTableSql} SET healthy = ${encodeBoolean(healthy)} WHERE address = ${address}`.pipe(Effect.asVoid, PersistenceError.refail, withTracerDisabled),
|
|
322
|
+
acquire: (address, shardIds) => acquireLock(address, shardIds).pipe(PersistenceError.refail, withTracerDisabled),
|
|
323
|
+
refresh: (address, shardIds) => sql`UPDATE ${runnersTableSql} SET last_heartbeat = ${sqlNow} WHERE address = ${address}`.pipe(execWithLockConn, shardIds.length > 0 ? Effect.andThen(refreshShards(address, shardIds)) : Effect.as([]), PersistenceError.refail),
|
|
324
|
+
release: sql.onDialectOrElse({
|
|
325
|
+
pg: () => Effect.fnUntraced(function* (_address, shardId) {
|
|
326
|
+
const lockNum = lockNumbers.get(shardId);
|
|
327
|
+
const conn = yield* Resource.get(lockConnRef);
|
|
328
|
+
const release = conn.executeRaw(`SELECT pg_advisory_unlock(${lockNum})`, []);
|
|
329
|
+
const check = conn.executeValues(`SELECT 1 FROM pg_locks WHERE locktype = 'advisory' AND granted = true AND pid = pg_backend_pid() AND objid = ${lockNum}`, []);
|
|
330
|
+
while (true) {
|
|
331
|
+
yield* release;
|
|
332
|
+
const takenLocks = yield* check;
|
|
333
|
+
if (takenLocks.length === 0) return;
|
|
334
|
+
}
|
|
335
|
+
}, Effect.onError(() => Resource.refresh(lockConnRef)), Effect.asVoid, PersistenceError.refail, withTracerDisabled),
|
|
336
|
+
mysql: () => Effect.fnUntraced(function* (_address, shardId) {
|
|
337
|
+
const conn = yield* Resource.get(lockConnRef);
|
|
338
|
+
const lockName = lockNames.get(shardId);
|
|
339
|
+
const release = conn.executeRaw(`SELECT RELEASE_LOCK('${lockName}')`, []);
|
|
340
|
+
const check = conn.executeValues(`SELECT IS_USED_LOCK('${lockName}') = CONNECTION_ID() AS is_taken`, []);
|
|
341
|
+
while (true) {
|
|
342
|
+
yield* release;
|
|
343
|
+
const takenLocks = yield* check;
|
|
344
|
+
if (takenLocks.length === 0 || takenLocks[0][0] !== 1) return;
|
|
345
|
+
}
|
|
346
|
+
}, Effect.onError(() => Resource.refresh(lockConnRef)), Effect.asVoid, PersistenceError.refail, withTracerDisabled),
|
|
347
|
+
orElse: () => (address, shardId) => sql`DELETE FROM ${locksTableSql} WHERE address = ${address} AND shard_id = ${shardId}`.pipe(PersistenceError.refail, withTracerDisabled)
|
|
348
|
+
}),
|
|
349
|
+
releaseAll: sql.onDialectOrElse({
|
|
350
|
+
pg: () => _address => sql`SELECT pg_advisory_unlock_all()`.pipe(execWithLockConn, Effect.asVoid, PersistenceError.refail, withTracerDisabled),
|
|
351
|
+
mysql: () => _address => sql`SELECT RELEASE_ALL_LOCKS()`.pipe(execWithLockConn, Effect.asVoid, PersistenceError.refail, withTracerDisabled),
|
|
352
|
+
orElse: () => address => sql`DELETE FROM ${locksTableSql} WHERE address = ${address}`.pipe(PersistenceError.refail, withTracerDisabled)
|
|
353
|
+
})
|
|
354
|
+
});
|
|
355
|
+
}, withTracerDisabled);
|
|
356
|
+
/**
|
|
357
|
+
* @since 1.0.0
|
|
358
|
+
* @category Layers
|
|
359
|
+
*/
|
|
360
|
+
export const layer = /*#__PURE__*/Layer.scoped(RunnerStorage.RunnerStorage)(/*#__PURE__*/make({}));
|
|
361
|
+
/**
|
|
362
|
+
* @since 1.0.0
|
|
363
|
+
* @category Layers
|
|
364
|
+
*/
|
|
365
|
+
export const layerWith = options => Layer.scoped(RunnerStorage.RunnerStorage)(make(options));
|
|
366
|
+
//# sourceMappingURL=SqlRunnerStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqlRunnerStorage.js","names":["SqlClient","Arr","Duration","Effect","Layer","Resource","PersistenceError","RunnerStorage","ShardId","ShardingConfig","withTracerDisabled","withTracerEnabled","make","fnUntraced","options","config","sql","withoutTransforms","prefix","table","name","acquireLockConn","onDialectOrElse","pg","gen","conn","orDie","reserve","addFinalizer","executeRaw","mysql","orElse","undefined","lockConnRef","manual","runnersTable","runnersTableSql","hasOldTables","pipe","isSuccess","ignore","mssql","locksTable","locksTableSql","void","sqlNowString","sqlNow","literal","expiresSeconds","Math","ceil","toSeconds","shardLockExpiration","toString","lockExpiresAt","encodeBoolean","b","sqlite","insertRunner","address","runner","healthy","values","unprepared","map","results","machine_id","execWithLockConn","effect","query","params","compile","get","flatMap","onError","refresh","execWithLockConnValues","executeValues","acquireLock","_address","shardIds","acquiredShardIds","toAcquire","Map","shardId","lockNumbers","takenLocks","i","length","lockNum","push","lockNumbersReverse","delete","size","executeUnprepared","pgLocks","allMySqlTakenLocks","includes","mysqlLocks","stringLiteral","csv","andThen","acquiredLocks","withTransaction","shardGroups","group","base","shard","shardsPerGroup","set","lockNames","lockNamesReverse","lockName","shardIdsMap","Array","from","entries","join","stringLiteralArr","rows","row","wrapString","s","arr","refreshShards","makeEncoded","getRunners","refail","String","Boolean","register","Number","unregister","asVoid","setRunnerHealth","acquire","as","release","check","releaseAll","layer","scoped","layerWith"],"sources":["../../src/SqlRunnerStorage.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/dist/esm/index.js
CHANGED
|
@@ -50,18 +50,10 @@ export * as EntityType from "./EntityType.js";
|
|
|
50
50
|
* @since 1.0.0
|
|
51
51
|
*/
|
|
52
52
|
export * as Envelope from "./Envelope.js";
|
|
53
|
-
/**
|
|
54
|
-
* @since 1.0.0
|
|
55
|
-
*/
|
|
56
|
-
export * as HttpCommon from "./HttpCommon.js";
|
|
57
53
|
/**
|
|
58
54
|
* @since 1.0.0
|
|
59
55
|
*/
|
|
60
56
|
export * as HttpRunner from "./HttpRunner.js";
|
|
61
|
-
/**
|
|
62
|
-
* @since 1.0.0
|
|
63
|
-
*/
|
|
64
|
-
export * as HttpShardManager from "./HttpShardManager.js";
|
|
65
57
|
/**
|
|
66
58
|
* @since 1.0.0
|
|
67
59
|
*/
|
|
@@ -97,19 +89,15 @@ export * as RunnerServer from "./RunnerServer.js";
|
|
|
97
89
|
/**
|
|
98
90
|
* @since 1.0.0
|
|
99
91
|
*/
|
|
100
|
-
export * as
|
|
92
|
+
export * as RunnerStorage from "./RunnerStorage.js";
|
|
101
93
|
/**
|
|
102
94
|
* @since 1.0.0
|
|
103
95
|
*/
|
|
104
|
-
export * as
|
|
105
|
-
/**
|
|
106
|
-
* @since 1.0.0
|
|
107
|
-
*/
|
|
108
|
-
export * as ShardManager from "./ShardManager.js";
|
|
96
|
+
export * as Runners from "./Runners.js";
|
|
109
97
|
/**
|
|
110
98
|
* @since 1.0.0
|
|
111
99
|
*/
|
|
112
|
-
export * as
|
|
100
|
+
export * as ShardId from "./ShardId.js";
|
|
113
101
|
/**
|
|
114
102
|
* @since 1.0.0
|
|
115
103
|
*/
|
|
@@ -138,10 +126,6 @@ export * as Snowflake from "./Snowflake.js";
|
|
|
138
126
|
* @since 1.0.0
|
|
139
127
|
*/
|
|
140
128
|
export * as SocketRunner from "./SocketRunner.js";
|
|
141
|
-
/**
|
|
142
|
-
* @since 1.0.0
|
|
143
|
-
*/
|
|
144
|
-
export * as SocketShardManager from "./SocketShardManager.js";
|
|
145
129
|
/**
|
|
146
130
|
* @since 1.0.0
|
|
147
131
|
*/
|
|
@@ -149,9 +133,5 @@ export * as SqlMessageStorage from "./SqlMessageStorage.js";
|
|
|
149
133
|
/**
|
|
150
134
|
* @since 1.0.0
|
|
151
135
|
*/
|
|
152
|
-
export * as
|
|
153
|
-
/**
|
|
154
|
-
* @since 1.0.0
|
|
155
|
-
*/
|
|
156
|
-
export * as SynchronizedClock from "./SynchronizedClock.js";
|
|
136
|
+
export * as SqlRunnerStorage from "./SqlRunnerStorage.js";
|
|
157
137
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["ClusterCron","ClusterError","ClusterMetrics","ClusterSchema","ClusterWorkflowEngine","DeliverAt","Entity","EntityAddress","EntityId","EntityProxy","EntityProxyServer","EntityType","Envelope","
|
|
1
|
+
{"version":3,"file":"index.js","names":["ClusterCron","ClusterError","ClusterMetrics","ClusterSchema","ClusterWorkflowEngine","DeliverAt","Entity","EntityAddress","EntityId","EntityProxy","EntityProxyServer","EntityType","Envelope","HttpRunner","MachineId","Message","MessageStorage","Reply","Runner","RunnerAddress","RunnerHealth","RunnerServer","RunnerStorage","Runners","ShardId","Sharding","ShardingConfig","ShardingRegistrationEvent","Singleton","SingletonAddress","Snowflake","SocketRunner","SqlMessageStorage","SqlRunnerStorage"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAGA,OAAO,KAAKA,WAAW,MAAM,kBAAkB;AAE/C;;;AAGA,OAAO,KAAKC,YAAY,MAAM,mBAAmB;AAEjD;;;AAGA,OAAO,KAAKC,cAAc,MAAM,qBAAqB;AAErD;;;AAGA,OAAO,KAAKC,aAAa,MAAM,oBAAoB;AAEnD;;;AAGA,OAAO,KAAKC,qBAAqB,MAAM,4BAA4B;AAEnE;;;AAGA,OAAO,KAAKC,SAAS,MAAM,gBAAgB;AAE3C;;;AAGA,OAAO,KAAKC,MAAM,MAAM,aAAa;AAErC;;;AAGA,OAAO,KAAKC,aAAa,MAAM,oBAAoB;AAEnD;;;AAGA,OAAO,KAAKC,QAAQ,MAAM,eAAe;AAEzC;;;AAGA,OAAO,KAAKC,WAAW,MAAM,kBAAkB;AAE/C;;;AAGA,OAAO,KAAKC,iBAAiB,MAAM,wBAAwB;AAE3D;;;AAGA,OAAO,KAAKC,UAAU,MAAM,iBAAiB;AAE7C;;;AAGA,OAAO,KAAKC,QAAQ,MAAM,eAAe;AAEzC;;;AAGA,OAAO,KAAKC,UAAU,MAAM,iBAAiB;AAE7C;;;AAGA,OAAO,KAAKC,SAAS,MAAM,gBAAgB;AAE3C;;;AAGA,OAAO,KAAKC,OAAO,MAAM,cAAc;AAEvC;;;AAGA,OAAO,KAAKC,cAAc,MAAM,qBAAqB;AAErD;;;AAGA,OAAO,KAAKC,KAAK,MAAM,YAAY;AAEnC;;;AAGA,OAAO,KAAKC,MAAM,MAAM,aAAa;AAErC;;;AAGA,OAAO,KAAKC,aAAa,MAAM,oBAAoB;AAEnD;;;AAGA,OAAO,KAAKC,YAAY,MAAM,mBAAmB;AAEjD;;;AAGA,OAAO,KAAKC,YAAY,MAAM,mBAAmB;AAEjD;;;AAGA,OAAO,KAAKC,aAAa,MAAM,oBAAoB;AAEnD;;;AAGA,OAAO,KAAKC,OAAO,MAAM,cAAc;AAEvC;;;AAGA,OAAO,KAAKC,OAAO,MAAM,cAAc;AAEvC;;;AAGA,OAAO,KAAKC,QAAQ,MAAM,eAAe;AAEzC;;;AAGA,OAAO,KAAKC,cAAc,MAAM,qBAAqB;AAErD;;;AAGA,OAAO,KAAKC,yBAAyB,MAAM,gCAAgC;AAE3E;;;AAGA,OAAO,KAAKC,SAAS,MAAM,gBAAgB;AAE3C;;;AAGA,OAAO,KAAKC,gBAAgB,MAAM,uBAAuB;AAEzD;;;AAGA,OAAO,KAAKC,SAAS,MAAM,gBAAgB;AAE3C;;;AAGA,OAAO,KAAKC,YAAY,MAAM,mBAAmB;AAEjD;;;AAGA,OAAO,KAAKC,iBAAiB,MAAM,wBAAwB;AAE3D;;;AAGA,OAAO,KAAKC,gBAAgB,MAAM,uBAAuB","ignoreList":[]}
|
|
@@ -7,12 +7,9 @@ import * as Duration from "effect/Duration";
|
|
|
7
7
|
import * as Effect from "effect/Effect";
|
|
8
8
|
import * as Equal from "effect/Equal";
|
|
9
9
|
import * as Exit from "effect/Exit";
|
|
10
|
-
import * as FiberId from "effect/FiberId";
|
|
11
10
|
import * as FiberRef from "effect/FiberRef";
|
|
12
11
|
import { identity } from "effect/Function";
|
|
13
|
-
import * as Function from "effect/Function";
|
|
14
12
|
import * as HashMap from "effect/HashMap";
|
|
15
|
-
import * as HashSet from "effect/HashSet";
|
|
16
13
|
import * as Metric from "effect/Metric";
|
|
17
14
|
import * as Option from "effect/Option";
|
|
18
15
|
import * as Schedule from "effect/Schedule";
|
|
@@ -43,8 +40,10 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
43
40
|
const context = yield* Effect.context();
|
|
44
41
|
const retryDriver = yield* Schedule.driver(options.defectRetryPolicy ? Schedule.andThen(options.defectRetryPolicy, defaultRetryPolicy) : defaultRetryPolicy);
|
|
45
42
|
const activeServers = new Map();
|
|
43
|
+
const serverCloseLatches = new Map();
|
|
44
|
+
const processedRequestIds = new Set();
|
|
46
45
|
const entities = yield* ResourceMap.make(Effect.fnUntraced(function* (address) {
|
|
47
|
-
if (
|
|
46
|
+
if (!options.sharding.hasShardId(address.shardId)) {
|
|
48
47
|
return yield* new EntityNotAssignedToRunner({
|
|
49
48
|
address
|
|
50
49
|
});
|
|
@@ -52,7 +51,11 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
52
51
|
const scope = yield* Effect.scope;
|
|
53
52
|
const endLatch = yield* Effect.makeLatch();
|
|
54
53
|
// on shutdown, reset the storage for the entity
|
|
55
|
-
yield* Scope.
|
|
54
|
+
yield* Scope.addFinalizerExit(scope, () => {
|
|
55
|
+
serverCloseLatches.get(address)?.unsafeOpen();
|
|
56
|
+
serverCloseLatches.delete(address);
|
|
57
|
+
return Effect.ignore(options.storage.resetAddress(address));
|
|
58
|
+
});
|
|
56
59
|
const activeRequests = new Map();
|
|
57
60
|
let defectRequestIds = [];
|
|
58
61
|
// the server is stored in a ref, so if there is a defect, we can
|
|
@@ -81,7 +84,19 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
81
84
|
// They will be retried when the entity is restarted.
|
|
82
85
|
// Also, if the request is uninterruptible, we ignore the
|
|
83
86
|
// interrupt.
|
|
84
|
-
if (storageEnabled && Context.get(request.rpc.annotations, Persisted) && Exit.isFailure(response.exit) && Exit.isInterrupted(response.exit) && (isShuttingDown ||
|
|
87
|
+
if (storageEnabled && Context.get(request.rpc.annotations, Persisted) && Exit.isFailure(response.exit) && Exit.isInterrupted(response.exit) && (isShuttingDown || Uninterruptible.forServer(request.rpc.annotations))) {
|
|
88
|
+
if (!isShuttingDown) {
|
|
89
|
+
return server.write(0, {
|
|
90
|
+
...request.message.envelope,
|
|
91
|
+
id: RequestId(request.message.envelope.requestId),
|
|
92
|
+
tag: request.message.envelope.tag,
|
|
93
|
+
payload: new Request({
|
|
94
|
+
...request.message.envelope,
|
|
95
|
+
lastSentChunk: request.lastSentChunk
|
|
96
|
+
})
|
|
97
|
+
}).pipe(Effect.forkIn(scope));
|
|
98
|
+
}
|
|
99
|
+
activeRequests.delete(response.requestId);
|
|
85
100
|
return options.storage.unregisterReplyHandler(request.message.envelope.requestId);
|
|
86
101
|
}
|
|
87
102
|
return retryRespond(4, Effect.suspend(() => request.message.respond(new Reply.WithExit({
|
|
@@ -89,6 +104,7 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
89
104
|
id: snowflakeGen.unsafeNext(),
|
|
90
105
|
exit: response.exit
|
|
91
106
|
})))).pipe(Effect.flatMap(() => {
|
|
107
|
+
processedRequestIds.add(request.message.envelope.requestId);
|
|
92
108
|
activeRequests.delete(response.requestId);
|
|
93
109
|
// ensure that the reaper does not remove the entity as we haven't
|
|
94
110
|
// been "idle" yet
|
|
@@ -181,6 +197,7 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
181
197
|
// If the termination timeout is reached, let the server clean itself up
|
|
182
198
|
yield* Scope.addFinalizer(scope, Effect.withFiberRuntime(fiber => {
|
|
183
199
|
activeServers.delete(address.entityId);
|
|
200
|
+
serverCloseLatches.set(address, Effect.unsafeMakeLatch(false));
|
|
184
201
|
internalInterruptors.add(fiber.id());
|
|
185
202
|
return state.write(0, {
|
|
186
203
|
_tag: "Eof"
|
|
@@ -212,7 +229,7 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
212
229
|
// one sender for the same request. In this case, the other senders
|
|
213
230
|
// should resume from storage only.
|
|
214
231
|
let entry = server.activeRequests.get(message.envelope.requestId);
|
|
215
|
-
if (entry) {
|
|
232
|
+
if (entry || processedRequestIds.has(message.envelope.requestId)) {
|
|
216
233
|
return Effect.fail(new AlreadyProcessingMessage({
|
|
217
234
|
envelopeId: message.envelope.requestId,
|
|
218
235
|
address: message.envelope.address
|
|
@@ -268,16 +285,21 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
268
285
|
}), FiberRef.currentLogAnnotations, HashMap.empty());
|
|
269
286
|
}
|
|
270
287
|
const interruptShard = shardId => Effect.suspend(function loop() {
|
|
271
|
-
const
|
|
272
|
-
|
|
288
|
+
const toAwait = Arr.empty();
|
|
289
|
+
activeServers.forEach(state => {
|
|
273
290
|
if (shardId[Equal.symbol](state.address.shardId)) {
|
|
274
|
-
|
|
291
|
+
toAwait.push(entities.removeIgnore(state.address));
|
|
275
292
|
}
|
|
276
|
-
}
|
|
277
|
-
|
|
293
|
+
});
|
|
294
|
+
serverCloseLatches.forEach((latch, address) => {
|
|
295
|
+
if (shardId[Equal.symbol](address.shardId)) {
|
|
296
|
+
toAwait.push(latch.await);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
if (toAwait.length === 0) {
|
|
278
300
|
return Effect.void;
|
|
279
301
|
}
|
|
280
|
-
return Effect.flatMap(Effect.
|
|
302
|
+
return Effect.flatMap(Effect.all(toAwait, {
|
|
281
303
|
concurrency: "unbounded",
|
|
282
304
|
discard: true
|
|
283
305
|
}), loop);
|
|
@@ -286,6 +308,9 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
286
308
|
return identity({
|
|
287
309
|
interruptShard,
|
|
288
310
|
isProcessingFor(message, options) {
|
|
311
|
+
if (options?.excludeReplies !== true && processedRequestIds.has(message.envelope.requestId)) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
289
314
|
const state = activeServers.get(message.envelope.address.entityId);
|
|
290
315
|
if (!state) return false;
|
|
291
316
|
const request = state.activeRequests.get(message.envelope.requestId);
|
|
@@ -296,6 +321,9 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (entity, buildHandl
|
|
|
296
321
|
}
|
|
297
322
|
return true;
|
|
298
323
|
},
|
|
324
|
+
clearProcessed() {
|
|
325
|
+
processedRequestIds.clear();
|
|
326
|
+
},
|
|
299
327
|
sendLocal,
|
|
300
328
|
send: message => decodeMessage(message).pipe(Effect.matchEffect({
|
|
301
329
|
onFailure: cause => {
|
|
@@ -357,13 +385,4 @@ const makeMessageSchema = entity => {
|
|
|
357
385
|
}));
|
|
358
386
|
};
|
|
359
387
|
const retryRespond = (times, effect) => times === 0 ? effect : Effect.catchAll(effect, () => Effect.delay(retryRespond(times - 1, effect), 200));
|
|
360
|
-
const IsInterruptedIgnoreReducer = {
|
|
361
|
-
emptyCase: Function.constFalse,
|
|
362
|
-
failCase: Function.constFalse,
|
|
363
|
-
dieCase: Function.constFalse,
|
|
364
|
-
interruptCase: (_, fiberId) => HashSet.has(FiberId.ids(fiberId), -1),
|
|
365
|
-
sequentialCase: (_, left, right) => left || right,
|
|
366
|
-
parallelCase: (_, left, right) => left || right
|
|
367
|
-
};
|
|
368
|
-
const isInterruptIgnore = /*#__PURE__*/Cause.reduceWithContext(undefined, IsInterruptedIgnoreReducer);
|
|
369
388
|
//# sourceMappingURL=entityManager.js.map
|