@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.
Files changed (232) hide show
  1. package/RunnerStorage/package.json +6 -0
  2. package/SqlRunnerStorage/package.json +6 -0
  3. package/dist/cjs/ClusterError.js +2 -24
  4. package/dist/cjs/ClusterError.js.map +1 -1
  5. package/dist/cjs/ClusterMetrics.js +13 -15
  6. package/dist/cjs/ClusterMetrics.js.map +1 -1
  7. package/dist/cjs/ClusterSchema.js +17 -2
  8. package/dist/cjs/ClusterSchema.js.map +1 -1
  9. package/dist/cjs/ClusterWorkflowEngine.js +50 -83
  10. package/dist/cjs/ClusterWorkflowEngine.js.map +1 -1
  11. package/dist/cjs/Entity.js +1 -13
  12. package/dist/cjs/Entity.js.map +1 -1
  13. package/dist/cjs/EntityAddress.js +9 -1
  14. package/dist/cjs/EntityAddress.js.map +1 -1
  15. package/dist/cjs/EntityId.js +7 -1
  16. package/dist/cjs/EntityId.js.map +1 -1
  17. package/dist/cjs/EntityProxy.js +1 -1
  18. package/dist/cjs/EntityProxy.js.map +1 -1
  19. package/dist/cjs/HttpRunner.js +69 -43
  20. package/dist/cjs/HttpRunner.js.map +1 -1
  21. package/dist/cjs/MessageStorage.js +64 -16
  22. package/dist/cjs/MessageStorage.js.map +1 -1
  23. package/dist/cjs/Runner.js +3 -3
  24. package/dist/cjs/Runner.js.map +1 -1
  25. package/dist/cjs/RunnerAddress.js +7 -0
  26. package/dist/cjs/RunnerAddress.js.map +1 -1
  27. package/dist/cjs/RunnerHealth.js +91 -32
  28. package/dist/cjs/RunnerHealth.js.map +1 -1
  29. package/dist/cjs/RunnerServer.js +38 -24
  30. package/dist/cjs/RunnerServer.js.map +1 -1
  31. package/dist/cjs/RunnerStorage.js +100 -0
  32. package/dist/cjs/RunnerStorage.js.map +1 -0
  33. package/dist/cjs/Runners.js +18 -22
  34. package/dist/cjs/Runners.js.map +1 -1
  35. package/dist/cjs/ShardId.js +17 -7
  36. package/dist/cjs/ShardId.js.map +1 -1
  37. package/dist/cjs/Sharding.js +444 -320
  38. package/dist/cjs/Sharding.js.map +1 -1
  39. package/dist/cjs/ShardingConfig.js +10 -14
  40. package/dist/cjs/ShardingConfig.js.map +1 -1
  41. package/dist/cjs/Snowflake.js +1 -1
  42. package/dist/cjs/SocketRunner.js +1 -1
  43. package/dist/cjs/SocketRunner.js.map +1 -1
  44. package/dist/cjs/SqlMessageStorage.js +22 -28
  45. package/dist/cjs/SqlMessageStorage.js.map +1 -1
  46. package/dist/cjs/SqlRunnerStorage.js +375 -0
  47. package/dist/cjs/SqlRunnerStorage.js.map +1 -0
  48. package/dist/cjs/index.js +5 -15
  49. package/dist/cjs/internal/entityManager.js +42 -23
  50. package/dist/cjs/internal/entityManager.js.map +1 -1
  51. package/dist/dts/ClusterError.d.ts +0 -22
  52. package/dist/dts/ClusterError.d.ts.map +1 -1
  53. package/dist/dts/ClusterMetrics.d.ts +4 -14
  54. package/dist/dts/ClusterMetrics.d.ts.map +1 -1
  55. package/dist/dts/ClusterSchema.d.ts +9 -1
  56. package/dist/dts/ClusterSchema.d.ts.map +1 -1
  57. package/dist/dts/ClusterWorkflowEngine.d.ts.map +1 -1
  58. package/dist/dts/Entity.d.ts +3 -14
  59. package/dist/dts/Entity.d.ts.map +1 -1
  60. package/dist/dts/EntityAddress.d.ts +11 -0
  61. package/dist/dts/EntityAddress.d.ts.map +1 -1
  62. package/dist/dts/EntityId.d.ts +5 -0
  63. package/dist/dts/EntityId.d.ts.map +1 -1
  64. package/dist/dts/EntityProxy.d.ts +5 -6
  65. package/dist/dts/EntityProxy.d.ts.map +1 -1
  66. package/dist/dts/HttpRunner.d.ts +48 -25
  67. package/dist/dts/HttpRunner.d.ts.map +1 -1
  68. package/dist/dts/MessageStorage.d.ts +13 -5
  69. package/dist/dts/MessageStorage.d.ts.map +1 -1
  70. package/dist/dts/Runner.d.ts +4 -4
  71. package/dist/dts/Runner.d.ts.map +1 -1
  72. package/dist/dts/RunnerAddress.d.ts +5 -0
  73. package/dist/dts/RunnerAddress.d.ts.map +1 -1
  74. package/dist/dts/RunnerHealth.d.ts +24 -16
  75. package/dist/dts/RunnerHealth.d.ts.map +1 -1
  76. package/dist/dts/RunnerServer.d.ts +5 -4
  77. package/dist/dts/RunnerServer.d.ts.map +1 -1
  78. package/dist/dts/{ShardStorage.d.ts → RunnerStorage.d.ts} +41 -54
  79. package/dist/dts/RunnerStorage.d.ts.map +1 -0
  80. package/dist/dts/Runners.d.ts +15 -11
  81. package/dist/dts/Runners.d.ts.map +1 -1
  82. package/dist/dts/ShardId.d.ts +1 -1
  83. package/dist/dts/ShardId.d.ts.map +1 -1
  84. package/dist/dts/Sharding.d.ts +20 -10
  85. package/dist/dts/Sharding.d.ts.map +1 -1
  86. package/dist/dts/ShardingConfig.d.ts +40 -14
  87. package/dist/dts/ShardingConfig.d.ts.map +1 -1
  88. package/dist/dts/SocketRunner.d.ts +4 -3
  89. package/dist/dts/SocketRunner.d.ts.map +1 -1
  90. package/dist/dts/SqlMessageStorage.d.ts +2 -3
  91. package/dist/dts/SqlMessageStorage.d.ts.map +1 -1
  92. package/dist/dts/SqlRunnerStorage.d.ts +40 -0
  93. package/dist/dts/SqlRunnerStorage.d.ts.map +1 -0
  94. package/dist/dts/index.d.ts +4 -24
  95. package/dist/dts/index.d.ts.map +1 -1
  96. package/dist/esm/ClusterError.js +0 -21
  97. package/dist/esm/ClusterError.js.map +1 -1
  98. package/dist/esm/ClusterMetrics.js +12 -14
  99. package/dist/esm/ClusterMetrics.js.map +1 -1
  100. package/dist/esm/ClusterSchema.js +17 -2
  101. package/dist/esm/ClusterSchema.js.map +1 -1
  102. package/dist/esm/ClusterWorkflowEngine.js +50 -83
  103. package/dist/esm/ClusterWorkflowEngine.js.map +1 -1
  104. package/dist/esm/Entity.js +0 -12
  105. package/dist/esm/Entity.js.map +1 -1
  106. package/dist/esm/EntityAddress.js +7 -0
  107. package/dist/esm/EntityAddress.js.map +1 -1
  108. package/dist/esm/EntityId.js +5 -0
  109. package/dist/esm/EntityId.js.map +1 -1
  110. package/dist/esm/EntityProxy.js +2 -2
  111. package/dist/esm/EntityProxy.js.map +1 -1
  112. package/dist/esm/HttpRunner.js +62 -39
  113. package/dist/esm/HttpRunner.js.map +1 -1
  114. package/dist/esm/MessageStorage.js +65 -17
  115. package/dist/esm/MessageStorage.js.map +1 -1
  116. package/dist/esm/Runner.js +3 -3
  117. package/dist/esm/Runner.js.map +1 -1
  118. package/dist/esm/RunnerAddress.js +7 -0
  119. package/dist/esm/RunnerAddress.js.map +1 -1
  120. package/dist/esm/RunnerHealth.js +88 -30
  121. package/dist/esm/RunnerHealth.js.map +1 -1
  122. package/dist/esm/RunnerServer.js +38 -24
  123. package/dist/esm/RunnerServer.js.map +1 -1
  124. package/dist/esm/RunnerStorage.js +90 -0
  125. package/dist/esm/RunnerStorage.js.map +1 -0
  126. package/dist/esm/Runners.js +19 -23
  127. package/dist/esm/Runners.js.map +1 -1
  128. package/dist/esm/ShardId.js +16 -6
  129. package/dist/esm/ShardId.js.map +1 -1
  130. package/dist/esm/Sharding.js +447 -323
  131. package/dist/esm/Sharding.js.map +1 -1
  132. package/dist/esm/ShardingConfig.js +10 -14
  133. package/dist/esm/ShardingConfig.js.map +1 -1
  134. package/dist/esm/Snowflake.js +1 -1
  135. package/dist/esm/SocketRunner.js +1 -1
  136. package/dist/esm/SocketRunner.js.map +1 -1
  137. package/dist/esm/SqlMessageStorage.js +22 -28
  138. package/dist/esm/SqlMessageStorage.js.map +1 -1
  139. package/dist/esm/SqlRunnerStorage.js +366 -0
  140. package/dist/esm/SqlRunnerStorage.js.map +1 -0
  141. package/dist/esm/index.js +4 -24
  142. package/dist/esm/index.js.map +1 -1
  143. package/dist/esm/internal/entityManager.js +41 -22
  144. package/dist/esm/internal/entityManager.js.map +1 -1
  145. package/package.json +20 -60
  146. package/src/ClusterError.ts +0 -24
  147. package/src/ClusterMetrics.ts +12 -16
  148. package/src/ClusterSchema.ts +17 -2
  149. package/src/ClusterWorkflowEngine.ts +48 -80
  150. package/src/Entity.ts +3 -21
  151. package/src/EntityAddress.ts +10 -0
  152. package/src/EntityId.ts +6 -0
  153. package/src/EntityProxy.ts +10 -10
  154. package/src/HttpRunner.ts +132 -67
  155. package/src/MessageStorage.ts +89 -24
  156. package/src/Runner.ts +4 -4
  157. package/src/RunnerAddress.ts +8 -0
  158. package/src/RunnerHealth.ts +119 -56
  159. package/src/RunnerServer.ts +64 -47
  160. package/src/RunnerStorage.ts +218 -0
  161. package/src/Runners.ts +32 -45
  162. package/src/ShardId.ts +14 -3
  163. package/src/Sharding.ts +561 -417
  164. package/src/ShardingConfig.ts +39 -31
  165. package/src/Snowflake.ts +1 -1
  166. package/src/SocketRunner.ts +6 -4
  167. package/src/SqlMessageStorage.ts +28 -30
  168. package/src/SqlRunnerStorage.ts +537 -0
  169. package/src/index.ts +4 -29
  170. package/src/internal/entityManager.ts +45 -29
  171. package/HttpCommon/package.json +0 -6
  172. package/HttpShardManager/package.json +0 -6
  173. package/ShardManager/package.json +0 -6
  174. package/ShardStorage/package.json +0 -6
  175. package/SocketShardManager/package.json +0 -6
  176. package/SqlShardStorage/package.json +0 -6
  177. package/SynchronizedClock/package.json +0 -6
  178. package/dist/cjs/HttpCommon.js +0 -48
  179. package/dist/cjs/HttpCommon.js.map +0 -1
  180. package/dist/cjs/HttpShardManager.js +0 -139
  181. package/dist/cjs/HttpShardManager.js.map +0 -1
  182. package/dist/cjs/ShardManager.js +0 -549
  183. package/dist/cjs/ShardManager.js.map +0 -1
  184. package/dist/cjs/ShardStorage.js +0 -151
  185. package/dist/cjs/ShardStorage.js.map +0 -1
  186. package/dist/cjs/SocketShardManager.js +0 -32
  187. package/dist/cjs/SocketShardManager.js.map +0 -1
  188. package/dist/cjs/SqlShardStorage.js +0 -253
  189. package/dist/cjs/SqlShardStorage.js.map +0 -1
  190. package/dist/cjs/SynchronizedClock.js +0 -65
  191. package/dist/cjs/SynchronizedClock.js.map +0 -1
  192. package/dist/cjs/internal/shardManager.js +0 -353
  193. package/dist/cjs/internal/shardManager.js.map +0 -1
  194. package/dist/dts/HttpCommon.d.ts +0 -25
  195. package/dist/dts/HttpCommon.d.ts.map +0 -1
  196. package/dist/dts/HttpShardManager.d.ts +0 -119
  197. package/dist/dts/HttpShardManager.d.ts.map +0 -1
  198. package/dist/dts/ShardManager.d.ts +0 -459
  199. package/dist/dts/ShardManager.d.ts.map +0 -1
  200. package/dist/dts/ShardStorage.d.ts.map +0 -1
  201. package/dist/dts/SocketShardManager.d.ts +0 -17
  202. package/dist/dts/SocketShardManager.d.ts.map +0 -1
  203. package/dist/dts/SqlShardStorage.d.ts +0 -38
  204. package/dist/dts/SqlShardStorage.d.ts.map +0 -1
  205. package/dist/dts/SynchronizedClock.d.ts +0 -19
  206. package/dist/dts/SynchronizedClock.d.ts.map +0 -1
  207. package/dist/dts/internal/shardManager.d.ts +0 -2
  208. package/dist/dts/internal/shardManager.d.ts.map +0 -1
  209. package/dist/esm/HttpCommon.js +0 -38
  210. package/dist/esm/HttpCommon.js.map +0 -1
  211. package/dist/esm/HttpShardManager.js +0 -128
  212. package/dist/esm/HttpShardManager.js.map +0 -1
  213. package/dist/esm/ShardManager.js +0 -535
  214. package/dist/esm/ShardManager.js.map +0 -1
  215. package/dist/esm/ShardStorage.js +0 -141
  216. package/dist/esm/ShardStorage.js.map +0 -1
  217. package/dist/esm/SocketShardManager.js +0 -24
  218. package/dist/esm/SocketShardManager.js.map +0 -1
  219. package/dist/esm/SqlShardStorage.js +0 -244
  220. package/dist/esm/SqlShardStorage.js.map +0 -1
  221. package/dist/esm/SynchronizedClock.js +0 -57
  222. package/dist/esm/SynchronizedClock.js.map +0 -1
  223. package/dist/esm/internal/shardManager.js +0 -342
  224. package/dist/esm/internal/shardManager.js.map +0 -1
  225. package/src/HttpCommon.ts +0 -73
  226. package/src/HttpShardManager.ts +0 -273
  227. package/src/ShardManager.ts +0 -823
  228. package/src/ShardStorage.ts +0 -297
  229. package/src/SocketShardManager.ts +0 -48
  230. package/src/SqlShardStorage.ts +0 -329
  231. package/src/SynchronizedClock.ts +0 -82
  232. 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 Runners from "./Runners.js";
92
+ export * as RunnerStorage from "./RunnerStorage.js";
101
93
  /**
102
94
  * @since 1.0.0
103
95
  */
104
- export * as ShardId from "./ShardId.js";
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 ShardStorage from "./ShardStorage.js";
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 SqlShardStorage from "./SqlShardStorage.js";
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ClusterCron","ClusterError","ClusterMetrics","ClusterSchema","ClusterWorkflowEngine","DeliverAt","Entity","EntityAddress","EntityId","EntityProxy","EntityProxyServer","EntityType","Envelope","HttpCommon","HttpRunner","HttpShardManager","MachineId","Message","MessageStorage","Reply","Runner","RunnerAddress","RunnerHealth","RunnerServer","Runners","ShardId","ShardManager","ShardStorage","Sharding","ShardingConfig","ShardingRegistrationEvent","Singleton","SingletonAddress","Snowflake","SocketRunner","SocketShardManager","SqlMessageStorage","SqlShardStorage","SynchronizedClock"],"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,UAAU,MAAM,iBAAiB;AAE7C;;;AAGA,OAAO,KAAKC,gBAAgB,MAAM,uBAAuB;AAEzD;;;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,OAAO,MAAM,cAAc;AAEvC;;;AAGA,OAAO,KAAKC,OAAO,MAAM,cAAc;AAEvC;;;AAGA,OAAO,KAAKC,YAAY,MAAM,mBAAmB;AAEjD;;;AAGA,OAAO,KAAKC,YAAY,MAAM,mBAAmB;AAEjD;;;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,kBAAkB,MAAM,yBAAyB;AAE7D;;;AAGA,OAAO,KAAKC,iBAAiB,MAAM,wBAAwB;AAE3D;;;AAGA,OAAO,KAAKC,eAAe,MAAM,sBAAsB;AAEvD;;;AAGA,OAAO,KAAKC,iBAAiB,MAAM,wBAAwB","ignoreList":[]}
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 (yield* options.sharding.isShutdown) {
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.addFinalizer(scope, Effect.ignore(options.storage.resetAddress(address)));
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 || Context.get(request.rpc.annotations, Uninterruptible) || isInterruptIgnore(response.exit.cause))) {
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 toInterrupt = new Set();
272
- for (const state of activeServers.values()) {
288
+ const toAwait = Arr.empty();
289
+ activeServers.forEach(state => {
273
290
  if (shardId[Equal.symbol](state.address.shardId)) {
274
- toInterrupt.add(state);
291
+ toAwait.push(entities.removeIgnore(state.address));
275
292
  }
276
- }
277
- if (toInterrupt.size === 0) {
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.forEach(toInterrupt, state => entities.removeIgnore(state.address), {
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