@delali/sirannon-db 0.1.7 → 0.2.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/README.md +117 -969
- package/dist/backup-scheduler/index.d.ts +1 -1
- package/dist/backup-scheduler/index.mjs +2 -2
- package/dist/baseline-Br77Fnhb.d.ts +6 -0
- package/dist/{change-tracker-CbmaMO-N.d.ts → change-tracker-DKRVUC3l.d.ts} +5 -8
- package/dist/{chunk-DJLX6CAE.mjs → chunk-4ISB7XMA.mjs} +2 -1
- package/dist/chunk-5NOIGN5Y.mjs +18 -0
- package/dist/chunk-67M7KAH6.mjs +90 -0
- package/dist/{chunk-GEZUUIKV.mjs → chunk-D7LAYTKN.mjs} +5 -2
- package/dist/{chunk-4IGMIJQK.mjs → chunk-EBJXPQQO.mjs} +59 -20
- package/dist/{chunk-BNUTBHHH.mjs → chunk-FHWTZFI4.mjs} +1 -1
- package/dist/chunk-GVCNMPOS.mjs +130 -0
- package/dist/chunk-H237TXZW.mjs +1407 -0
- package/dist/{chunk-HHRMRFFR.mjs → chunk-H6PIVVDN.mjs} +353 -142
- package/dist/chunk-HR5CWTLC.mjs +661 -0
- package/dist/chunk-JU64Y7HM.mjs +299 -0
- package/dist/{chunk-CW6S3WL5.mjs → chunk-JZGINXTN.mjs} +7 -5
- package/dist/{chunk-CJLYFDP5.mjs → chunk-LFZ37BSX.mjs} +1 -1
- package/dist/chunk-LNY2VVHE.mjs +18 -0
- package/dist/chunk-NVQS53NT.mjs +665 -0
- package/dist/{chunk-H5AB6NIR.mjs → chunk-O7SLN3GI.mjs} +2 -15
- package/dist/chunk-OQVZBEBY.mjs +283 -0
- package/dist/{chunk-VLTICJOD.mjs → chunk-PIKHN33N.mjs} +1 -1
- package/dist/chunk-TJF5GZSV.mjs +187 -0
- package/dist/chunk-TUD5CJ76.mjs +126 -0
- package/dist/{chunk-YPYVQJ4C.mjs → chunk-UC3SCMIN.mjs} +9 -1
- package/dist/client/index.d.ts +216 -321
- package/dist/client/index.mjs +1192 -1342
- package/dist/client/topology.d.ts +61 -0
- package/dist/client/topology.mjs +682 -0
- package/dist/client-base-CLWmH5Ln.d.ts +234 -0
- package/dist/codegen/cli.d.ts +2 -0
- package/dist/codegen/cli.mjs +11 -0
- package/dist/codegen/index.d.ts +30 -0
- package/dist/codegen/index.mjs +5 -0
- package/dist/core/index.d.ts +37 -16
- package/dist/core/index.mjs +2322 -298
- package/dist/core/writer-worker.mjs +28 -6
- package/dist/{database-DuGp0Rtr.d.ts → database-BY0L5Q2n.d.ts} +59 -14
- package/dist/driver/better-sqlite3.d.ts +1 -1
- package/dist/driver/better-sqlite3.mjs +6 -6
- package/dist/driver/node.d.ts +1 -1
- package/dist/driver/node.mjs +6 -6
- package/dist/driver/wa-sqlite.d.ts +1 -136
- package/dist/{errors-5Nf5ZAEC.d.ts → errors-Bw5MdNCu.d.ts} +5 -1
- package/dist/file-migrations/index.d.ts +7 -5
- package/dist/file-migrations/index.mjs +42 -37
- package/dist/operation-registry-9DcvxcE5.d.ts +45 -0
- package/dist/primary-wins-DPAm2AKG.d.ts +61 -0
- package/dist/protocol-6KrSq2Hy.d.ts +66 -0
- package/dist/react/index.d.ts +20 -0
- package/dist/react/index.mjs +137 -0
- package/dist/replication/coordinator/etcd.d.ts +5 -3
- package/dist/replication/coordinator/etcd.mjs +554 -462
- package/dist/replication/index.d.ts +51 -105
- package/dist/replication/index.mjs +1415 -2061
- package/dist/server/index.d.ts +111 -87
- package/dist/server/index.mjs +1917 -489
- package/dist/server-options-1JHu8pid.d.ts +191 -0
- package/dist/{sirannon-4SspRvP5.d.ts → sirannon-DaQSyhbJ.d.ts} +7 -2
- package/dist/transport/grpc.d.ts +7 -4
- package/dist/transport/grpc.mjs +191 -97
- package/dist/transport/memory.d.ts +5 -134
- package/dist/transport/memory.mjs +3 -1
- package/dist/{types-BsjobKbl.d.ts → types-B7gmEsZW.d.ts} +8 -61
- package/dist/{types-BEu1I_9_.d.ts → types-BsVabqSI.d.ts} +1 -1
- package/dist/types-CL6piSnD.d.ts +43 -0
- package/dist/types-C_D8IhpO.d.ts +60 -0
- package/dist/{types-D_hQW1hr.d.ts → types-zhnRXrsb.d.ts} +55 -165
- package/package.json +44 -6
- package/dist/chunk-TKGHYWQ6.mjs +0 -35
- package/dist/types-D4p4UyDK.d.ts +0 -26
package/dist/transport/grpc.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { TransportError } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import
|
|
1
|
+
import { TransportError } from '../chunk-O7SLN3GI.mjs';
|
|
2
|
+
import '../chunk-5NOIGN5Y.mjs';
|
|
3
|
+
import '../chunk-UC3SCMIN.mjs';
|
|
4
4
|
import { BinaryWriter, BinaryReader } from '@bufbuild/protobuf/wire';
|
|
5
|
+
import { makeGenericClientConstructor, Server, Metadata, status, ServerCredentials, credentials } from '@grpc/grpc-js';
|
|
5
6
|
import { readFileSync } from 'fs';
|
|
6
7
|
import { HealthImplementation } from 'grpc-health-check';
|
|
7
8
|
|
|
@@ -138,7 +139,8 @@ function toSyncRequestPayload(req) {
|
|
|
138
139
|
joinerNodeId: req.joinerNodeId,
|
|
139
140
|
completedTables: req.completedTables,
|
|
140
141
|
groupId: req.groupId ?? "",
|
|
141
|
-
primaryTerm: req.primaryTerm ?? 0n
|
|
142
|
+
primaryTerm: req.primaryTerm ?? 0n,
|
|
143
|
+
supportsStreamVerification: req.supportsStreamVerification === true
|
|
142
144
|
};
|
|
143
145
|
}
|
|
144
146
|
function fromSyncRequestPayload(p) {
|
|
@@ -146,6 +148,7 @@ function fromSyncRequestPayload(p) {
|
|
|
146
148
|
requestId: p.requestId,
|
|
147
149
|
joinerNodeId: p.joinerNodeId,
|
|
148
150
|
completedTables: p.completedTables,
|
|
151
|
+
supportsStreamVerification: p.supportsStreamVerification === true ? true : void 0,
|
|
149
152
|
groupId: p.groupId || void 0,
|
|
150
153
|
primaryTerm: p.primaryTerm === 0n ? void 0 : p.primaryTerm
|
|
151
154
|
};
|
|
@@ -185,7 +188,8 @@ function toSyncCompletePayload(complete) {
|
|
|
185
188
|
manifests: complete.manifests.map((m) => ({
|
|
186
189
|
table: m.table,
|
|
187
190
|
rowCount: m.rowCount,
|
|
188
|
-
pkHash: m.pkHash
|
|
191
|
+
pkHash: m.pkHash ?? "",
|
|
192
|
+
batchDigest: m.batchDigest ?? ""
|
|
189
193
|
})),
|
|
190
194
|
groupId: complete.groupId ?? "",
|
|
191
195
|
primaryTerm: complete.primaryTerm ?? 0n
|
|
@@ -199,7 +203,8 @@ function fromSyncCompletePayload(p) {
|
|
|
199
203
|
(m) => ({
|
|
200
204
|
table: m.table,
|
|
201
205
|
rowCount: m.rowCount,
|
|
202
|
-
pkHash: m.pkHash
|
|
206
|
+
pkHash: m.pkHash || void 0,
|
|
207
|
+
batchDigest: m.batchDigest || void 0
|
|
203
208
|
})
|
|
204
209
|
),
|
|
205
210
|
groupId: p.groupId || void 0,
|
|
@@ -272,6 +277,63 @@ function fromForwardRequest(proto) {
|
|
|
272
277
|
primaryTerm: proto.primaryTerm === 0n ? void 0 : proto.primaryTerm
|
|
273
278
|
};
|
|
274
279
|
}
|
|
280
|
+
|
|
281
|
+
// src/transport/grpc/client-reconnect.ts
|
|
282
|
+
var RECONNECT_MIN_DELAY_MS = 250;
|
|
283
|
+
var RECONNECT_MAX_DELAY_MS = 5e3;
|
|
284
|
+
var stateByTransport = /* @__PURE__ */ new WeakMap();
|
|
285
|
+
function stateFor(transport) {
|
|
286
|
+
const existing = stateByTransport.get(transport);
|
|
287
|
+
if (existing) return existing;
|
|
288
|
+
const created = { timers: /* @__PURE__ */ new Map(), delays: /* @__PURE__ */ new Map(), dialled: /* @__PURE__ */ new Map() };
|
|
289
|
+
stateByTransport.set(transport, created);
|
|
290
|
+
return created;
|
|
291
|
+
}
|
|
292
|
+
function claimEndpoint(transport, endpoint) {
|
|
293
|
+
const state = stateFor(transport);
|
|
294
|
+
if (state.dialled.has(endpoint)) return false;
|
|
295
|
+
state.dialled.set(endpoint, () => void 0);
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
function registerEndpointAbort(transport, endpoint, abort) {
|
|
299
|
+
const state = stateFor(transport);
|
|
300
|
+
if (!state.dialled.has(endpoint)) return;
|
|
301
|
+
state.dialled.set(endpoint, abort);
|
|
302
|
+
}
|
|
303
|
+
function releaseEndpoint(transport, endpoint) {
|
|
304
|
+
stateFor(transport).dialled.delete(endpoint);
|
|
305
|
+
}
|
|
306
|
+
function noteEndpointReachable(transport, endpoint) {
|
|
307
|
+
stateFor(transport).delays.delete(endpoint);
|
|
308
|
+
}
|
|
309
|
+
function scheduleEndpointRedial(transport, endpoint, redial) {
|
|
310
|
+
if (!transport.connected) return;
|
|
311
|
+
const state = stateFor(transport);
|
|
312
|
+
if (state.timers.has(endpoint)) return;
|
|
313
|
+
const delayMs = state.delays.get(endpoint) ?? RECONNECT_MIN_DELAY_MS;
|
|
314
|
+
state.delays.set(endpoint, Math.min(delayMs * 2, RECONNECT_MAX_DELAY_MS));
|
|
315
|
+
const timer = setTimeout(() => {
|
|
316
|
+
state.timers.delete(endpoint);
|
|
317
|
+
if (!transport.connected) return;
|
|
318
|
+
redial();
|
|
319
|
+
}, delayMs);
|
|
320
|
+
timer.unref?.();
|
|
321
|
+
state.timers.set(endpoint, timer);
|
|
322
|
+
}
|
|
323
|
+
function stopEndpointDialling(transport) {
|
|
324
|
+
const state = stateByTransport.get(transport);
|
|
325
|
+
if (!state) return;
|
|
326
|
+
for (const timer of state.timers.values()) {
|
|
327
|
+
clearTimeout(timer);
|
|
328
|
+
}
|
|
329
|
+
state.timers.clear();
|
|
330
|
+
state.delays.clear();
|
|
331
|
+
const aborts = [...state.dialled.values()];
|
|
332
|
+
state.dialled.clear();
|
|
333
|
+
for (const abort of aborts) {
|
|
334
|
+
abort();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
275
337
|
function createBaseColumnValue() {
|
|
276
338
|
return {
|
|
277
339
|
nullValue: void 0,
|
|
@@ -1332,7 +1394,14 @@ var ReplicationMessage = {
|
|
|
1332
1394
|
}
|
|
1333
1395
|
};
|
|
1334
1396
|
function createBaseSyncRequestPayload() {
|
|
1335
|
-
return {
|
|
1397
|
+
return {
|
|
1398
|
+
requestId: "",
|
|
1399
|
+
joinerNodeId: "",
|
|
1400
|
+
completedTables: [],
|
|
1401
|
+
groupId: "",
|
|
1402
|
+
primaryTerm: 0n,
|
|
1403
|
+
supportsStreamVerification: false
|
|
1404
|
+
};
|
|
1336
1405
|
}
|
|
1337
1406
|
var SyncRequestPayload = {
|
|
1338
1407
|
encode(message, writer = new BinaryWriter()) {
|
|
@@ -1354,6 +1423,9 @@ var SyncRequestPayload = {
|
|
|
1354
1423
|
}
|
|
1355
1424
|
writer.uint32(40).int64(message.primaryTerm);
|
|
1356
1425
|
}
|
|
1426
|
+
if (message.supportsStreamVerification !== false) {
|
|
1427
|
+
writer.uint32(48).bool(message.supportsStreamVerification);
|
|
1428
|
+
}
|
|
1357
1429
|
return writer;
|
|
1358
1430
|
},
|
|
1359
1431
|
decode(input, length) {
|
|
@@ -1398,6 +1470,13 @@ var SyncRequestPayload = {
|
|
|
1398
1470
|
message.primaryTerm = reader.int64();
|
|
1399
1471
|
continue;
|
|
1400
1472
|
}
|
|
1473
|
+
case 6: {
|
|
1474
|
+
if (tag !== 48) {
|
|
1475
|
+
break;
|
|
1476
|
+
}
|
|
1477
|
+
message.supportsStreamVerification = reader.bool();
|
|
1478
|
+
continue;
|
|
1479
|
+
}
|
|
1401
1480
|
}
|
|
1402
1481
|
if ((tag & 7) === 4 || tag === 0) {
|
|
1403
1482
|
break;
|
|
@@ -1412,7 +1491,8 @@ var SyncRequestPayload = {
|
|
|
1412
1491
|
joinerNodeId: isSet(object.joinerNodeId) ? globalThis.String(object.joinerNodeId) : isSet(object.joiner_node_id) ? globalThis.String(object.joiner_node_id) : "",
|
|
1413
1492
|
completedTables: globalThis.Array.isArray(object?.completedTables) ? object.completedTables.map((e) => globalThis.String(e)) : globalThis.Array.isArray(object?.completed_tables) ? object.completed_tables.map((e) => globalThis.String(e)) : [],
|
|
1414
1493
|
groupId: isSet(object.groupId) ? globalThis.String(object.groupId) : isSet(object.group_id) ? globalThis.String(object.group_id) : "",
|
|
1415
|
-
primaryTerm: isSet(object.primaryTerm) ? BigInt(object.primaryTerm) : isSet(object.primary_term) ? BigInt(object.primary_term) : 0n
|
|
1494
|
+
primaryTerm: isSet(object.primaryTerm) ? BigInt(object.primaryTerm) : isSet(object.primary_term) ? BigInt(object.primary_term) : 0n,
|
|
1495
|
+
supportsStreamVerification: isSet(object.supportsStreamVerification) ? globalThis.Boolean(object.supportsStreamVerification) : isSet(object.supports_stream_verification) ? globalThis.Boolean(object.supports_stream_verification) : false
|
|
1416
1496
|
};
|
|
1417
1497
|
},
|
|
1418
1498
|
toJSON(message) {
|
|
@@ -1432,6 +1512,9 @@ var SyncRequestPayload = {
|
|
|
1432
1512
|
if (message.primaryTerm !== 0n) {
|
|
1433
1513
|
obj.primaryTerm = message.primaryTerm.toString();
|
|
1434
1514
|
}
|
|
1515
|
+
if (message.supportsStreamVerification !== false) {
|
|
1516
|
+
obj.supportsStreamVerification = message.supportsStreamVerification;
|
|
1517
|
+
}
|
|
1435
1518
|
return obj;
|
|
1436
1519
|
},
|
|
1437
1520
|
create(base) {
|
|
@@ -1444,6 +1527,7 @@ var SyncRequestPayload = {
|
|
|
1444
1527
|
message.completedTables = object.completedTables?.map((e) => e) || [];
|
|
1445
1528
|
message.groupId = object.groupId ?? "";
|
|
1446
1529
|
message.primaryTerm = object.primaryTerm ?? 0n;
|
|
1530
|
+
message.supportsStreamVerification = object.supportsStreamVerification ?? false;
|
|
1447
1531
|
return message;
|
|
1448
1532
|
}
|
|
1449
1533
|
};
|
|
@@ -1769,7 +1853,7 @@ var SyncCompletePayload = {
|
|
|
1769
1853
|
}
|
|
1770
1854
|
};
|
|
1771
1855
|
function createBaseSyncTableManifest() {
|
|
1772
|
-
return { table: "", rowCount: 0, pkHash: "" };
|
|
1856
|
+
return { table: "", rowCount: 0, pkHash: "", batchDigest: "" };
|
|
1773
1857
|
}
|
|
1774
1858
|
var SyncTableManifest = {
|
|
1775
1859
|
encode(message, writer = new BinaryWriter()) {
|
|
@@ -1782,6 +1866,9 @@ var SyncTableManifest = {
|
|
|
1782
1866
|
if (message.pkHash !== "") {
|
|
1783
1867
|
writer.uint32(26).string(message.pkHash);
|
|
1784
1868
|
}
|
|
1869
|
+
if (message.batchDigest !== "") {
|
|
1870
|
+
writer.uint32(34).string(message.batchDigest);
|
|
1871
|
+
}
|
|
1785
1872
|
return writer;
|
|
1786
1873
|
},
|
|
1787
1874
|
decode(input, length) {
|
|
@@ -1812,6 +1899,13 @@ var SyncTableManifest = {
|
|
|
1812
1899
|
message.pkHash = reader.string();
|
|
1813
1900
|
continue;
|
|
1814
1901
|
}
|
|
1902
|
+
case 4: {
|
|
1903
|
+
if (tag !== 34) {
|
|
1904
|
+
break;
|
|
1905
|
+
}
|
|
1906
|
+
message.batchDigest = reader.string();
|
|
1907
|
+
continue;
|
|
1908
|
+
}
|
|
1815
1909
|
}
|
|
1816
1910
|
if ((tag & 7) === 4 || tag === 0) {
|
|
1817
1911
|
break;
|
|
@@ -1824,7 +1918,8 @@ var SyncTableManifest = {
|
|
|
1824
1918
|
return {
|
|
1825
1919
|
table: isSet(object.table) ? globalThis.String(object.table) : "",
|
|
1826
1920
|
rowCount: isSet(object.rowCount) ? globalThis.Number(object.rowCount) : isSet(object.row_count) ? globalThis.Number(object.row_count) : 0,
|
|
1827
|
-
pkHash: isSet(object.pkHash) ? globalThis.String(object.pkHash) : isSet(object.pk_hash) ? globalThis.String(object.pk_hash) : ""
|
|
1921
|
+
pkHash: isSet(object.pkHash) ? globalThis.String(object.pkHash) : isSet(object.pk_hash) ? globalThis.String(object.pk_hash) : "",
|
|
1922
|
+
batchDigest: isSet(object.batchDigest) ? globalThis.String(object.batchDigest) : isSet(object.batch_digest) ? globalThis.String(object.batch_digest) : ""
|
|
1828
1923
|
};
|
|
1829
1924
|
},
|
|
1830
1925
|
toJSON(message) {
|
|
@@ -1838,6 +1933,9 @@ var SyncTableManifest = {
|
|
|
1838
1933
|
if (message.pkHash !== "") {
|
|
1839
1934
|
obj.pkHash = message.pkHash;
|
|
1840
1935
|
}
|
|
1936
|
+
if (message.batchDigest !== "") {
|
|
1937
|
+
obj.batchDigest = message.batchDigest;
|
|
1938
|
+
}
|
|
1841
1939
|
return obj;
|
|
1842
1940
|
},
|
|
1843
1941
|
create(base) {
|
|
@@ -1848,6 +1946,7 @@ var SyncTableManifest = {
|
|
|
1848
1946
|
message.table = object.table ?? "";
|
|
1849
1947
|
message.rowCount = object.rowCount ?? 0;
|
|
1850
1948
|
message.pkHash = object.pkHash ?? "";
|
|
1949
|
+
message.batchDigest = object.batchDigest ?? "";
|
|
1851
1950
|
return message;
|
|
1852
1951
|
}
|
|
1853
1952
|
};
|
|
@@ -2702,7 +2801,15 @@ function removePeer(connectedPeers, serverPeerStreams, peerDisconnectedHandler,
|
|
|
2702
2801
|
}
|
|
2703
2802
|
|
|
2704
2803
|
// src/transport/grpc/client-streams.ts
|
|
2705
|
-
|
|
2804
|
+
function cancelQuietly(stream) {
|
|
2805
|
+
try {
|
|
2806
|
+
stream.cancel();
|
|
2807
|
+
} catch {
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
function connectToEndpoint(t, endpoint) {
|
|
2811
|
+
if (!t.connected) return;
|
|
2812
|
+
if (!claimEndpoint(t, endpoint)) return;
|
|
2706
2813
|
const channelCreds = buildChannelCreds(t.options);
|
|
2707
2814
|
const clientOpts = {};
|
|
2708
2815
|
const client = new ReplicationClient(endpoint, channelCreds, clientOpts);
|
|
@@ -2713,34 +2820,47 @@ async function connectToEndpoint(t, endpoint) {
|
|
|
2713
2820
|
replicateStream,
|
|
2714
2821
|
syncStream
|
|
2715
2822
|
};
|
|
2716
|
-
replicateStream.write({
|
|
2717
|
-
hello: {
|
|
2718
|
-
nodeId: t.localNodeId,
|
|
2719
|
-
role: t.localRole,
|
|
2720
|
-
groupId: t.localGroupId ?? "",
|
|
2721
|
-
primaryTerm: t.localPrimaryTerm ?? 0n,
|
|
2722
|
-
protocolVersion: t.localProtocolVersion ?? ""
|
|
2723
|
-
}
|
|
2724
|
-
});
|
|
2725
|
-
syncStream.write({
|
|
2726
|
-
hello: {
|
|
2727
|
-
nodeId: t.localNodeId,
|
|
2728
|
-
role: t.localRole,
|
|
2729
|
-
groupId: t.localGroupId ?? "",
|
|
2730
|
-
primaryTerm: t.localPrimaryTerm ?? 0n,
|
|
2731
|
-
protocolVersion: t.localProtocolVersion ?? ""
|
|
2732
|
-
}
|
|
2733
|
-
});
|
|
2734
2823
|
let replicatePeerId = null;
|
|
2824
|
+
let syncPeerId = null;
|
|
2825
|
+
let closed = false;
|
|
2826
|
+
const teardown = () => {
|
|
2827
|
+
if (closed) return;
|
|
2828
|
+
closed = true;
|
|
2829
|
+
releaseEndpoint(t, endpoint);
|
|
2830
|
+
const peerId = replicatePeerId ?? syncPeerId;
|
|
2831
|
+
if (peerId !== null && t.clientPeerStreams.get(peerId) === entry) {
|
|
2832
|
+
t.clientPeerStreams.delete(peerId);
|
|
2833
|
+
removePeer(t.connectedPeers, t.serverPeerStreams, t.peerDisconnectedHandler, peerId);
|
|
2834
|
+
}
|
|
2835
|
+
entry.replicateStream = null;
|
|
2836
|
+
entry.syncStream = null;
|
|
2837
|
+
cancelQuietly(replicateStream);
|
|
2838
|
+
cancelQuietly(syncStream);
|
|
2839
|
+
client.close();
|
|
2840
|
+
scheduleEndpointRedial(t, endpoint, () => {
|
|
2841
|
+
connectToEndpoint(t, endpoint);
|
|
2842
|
+
});
|
|
2843
|
+
};
|
|
2844
|
+
registerEndpointAbort(t, endpoint, teardown);
|
|
2845
|
+
const hello = {
|
|
2846
|
+
nodeId: t.localNodeId,
|
|
2847
|
+
role: t.localRole,
|
|
2848
|
+
groupId: t.localGroupId ?? "",
|
|
2849
|
+
primaryTerm: t.localPrimaryTerm ?? 0n,
|
|
2850
|
+
protocolVersion: t.localProtocolVersion ?? ""
|
|
2851
|
+
};
|
|
2852
|
+
replicateStream.write({ hello });
|
|
2853
|
+
syncStream.write({ hello });
|
|
2735
2854
|
replicateStream.on("data", (msg) => {
|
|
2736
2855
|
if (replicatePeerId === null) {
|
|
2737
2856
|
if (!msg.hello) {
|
|
2738
|
-
|
|
2857
|
+
teardown();
|
|
2739
2858
|
return;
|
|
2740
2859
|
}
|
|
2741
2860
|
replicatePeerId = msg.hello.nodeId;
|
|
2742
2861
|
const peerRole = msg.hello.role;
|
|
2743
2862
|
t.clientPeerStreams.set(replicatePeerId, entry);
|
|
2863
|
+
noteEndpointReachable(t, endpoint);
|
|
2744
2864
|
registerPeer(t.connectedPeers, t.peerConnectedHandler, replicatePeerId, peerRole, {
|
|
2745
2865
|
groupId: msg.hello.groupId || void 0,
|
|
2746
2866
|
primaryTerm: msg.hello.primaryTerm === 0n ? void 0 : msg.hello.primaryTerm,
|
|
@@ -2755,17 +2875,12 @@ async function connectToEndpoint(t, endpoint) {
|
|
|
2755
2875
|
t.ackHandler?.(fromAckPayload(msg.ack), replicatePeerId);
|
|
2756
2876
|
}
|
|
2757
2877
|
});
|
|
2758
|
-
replicateStream.on("end",
|
|
2759
|
-
|
|
2760
|
-
});
|
|
2761
|
-
replicateStream.on("error", () => {
|
|
2762
|
-
detachReplicate(t, replicatePeerId);
|
|
2763
|
-
});
|
|
2764
|
-
let syncPeerId = null;
|
|
2878
|
+
replicateStream.on("end", teardown);
|
|
2879
|
+
replicateStream.on("error", teardown);
|
|
2765
2880
|
syncStream.on("data", (msg) => {
|
|
2766
2881
|
if (syncPeerId === null) {
|
|
2767
2882
|
if (!msg.hello) {
|
|
2768
|
-
|
|
2883
|
+
teardown();
|
|
2769
2884
|
return;
|
|
2770
2885
|
}
|
|
2771
2886
|
syncPeerId = msg.hello.nodeId;
|
|
@@ -2784,32 +2899,42 @@ async function connectToEndpoint(t, endpoint) {
|
|
|
2784
2899
|
t.syncAckHandler?.(fromSyncAckPayload(msg.syncAck), syncPeerId);
|
|
2785
2900
|
}
|
|
2786
2901
|
});
|
|
2787
|
-
syncStream.on("end",
|
|
2788
|
-
|
|
2789
|
-
});
|
|
2790
|
-
syncStream.on("error", () => {
|
|
2791
|
-
detachSync(t, syncPeerId);
|
|
2792
|
-
});
|
|
2902
|
+
syncStream.on("end", teardown);
|
|
2903
|
+
syncStream.on("error", teardown);
|
|
2793
2904
|
}
|
|
2794
|
-
function
|
|
2795
|
-
|
|
2796
|
-
const
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2905
|
+
function forwardOverRpc(entry, request, deadlineMs) {
|
|
2906
|
+
const protoRequest = toForwardRequest(request);
|
|
2907
|
+
const deadline = new Date(Date.now() + deadlineMs);
|
|
2908
|
+
return new Promise((resolve, reject) => {
|
|
2909
|
+
entry.client.forward(
|
|
2910
|
+
protoRequest,
|
|
2911
|
+
new Metadata(),
|
|
2912
|
+
{ deadline },
|
|
2913
|
+
(err, response) => {
|
|
2914
|
+
if (err) {
|
|
2915
|
+
reject(new TransportError(`Forward RPC failed: ${err.message}`));
|
|
2916
|
+
return;
|
|
2917
|
+
}
|
|
2918
|
+
if (!response) {
|
|
2919
|
+
reject(new TransportError("Forward RPC returned empty response"));
|
|
2920
|
+
return;
|
|
2921
|
+
}
|
|
2922
|
+
if (response.error) {
|
|
2923
|
+
reject(new TransportError(`Forward RPC error: ${response.error}`));
|
|
2924
|
+
return;
|
|
2925
|
+
}
|
|
2926
|
+
resolve({
|
|
2927
|
+
requestId: response.requestId,
|
|
2928
|
+
results: response.results.map((r) => ({
|
|
2929
|
+
changes: r.changes,
|
|
2930
|
+
lastInsertRowId: Number(r.lastInsertRowId)
|
|
2931
|
+
})),
|
|
2932
|
+
groupId: response.groupId || void 0,
|
|
2933
|
+
primaryTerm: response.primaryTerm === 0n ? void 0 : response.primaryTerm
|
|
2934
|
+
});
|
|
2935
|
+
}
|
|
2936
|
+
);
|
|
2937
|
+
});
|
|
2813
2938
|
}
|
|
2814
2939
|
|
|
2815
2940
|
// src/transport/grpc/options.ts
|
|
@@ -3117,13 +3242,14 @@ var GrpcReplicationTransport = class {
|
|
|
3117
3242
|
}
|
|
3118
3243
|
if (config.endpoints && config.endpoints.length > 0) {
|
|
3119
3244
|
for (const endpoint of config.endpoints) {
|
|
3120
|
-
|
|
3245
|
+
connectToEndpoint(this, endpoint);
|
|
3121
3246
|
}
|
|
3122
3247
|
}
|
|
3123
3248
|
}
|
|
3124
3249
|
async disconnect() {
|
|
3125
3250
|
if (!this.connected) return;
|
|
3126
3251
|
this.connected = false;
|
|
3252
|
+
stopEndpointDialling(this);
|
|
3127
3253
|
for (const [peerId, entry] of this.clientPeerStreams) {
|
|
3128
3254
|
entry.replicateStream?.cancel();
|
|
3129
3255
|
entry.syncStream?.cancel();
|
|
@@ -3196,39 +3322,7 @@ var GrpcReplicationTransport = class {
|
|
|
3196
3322
|
if (!clientEntry) {
|
|
3197
3323
|
throw new TransportError(`Peer '${peerId}' is not connected`);
|
|
3198
3324
|
}
|
|
3199
|
-
|
|
3200
|
-
const deadlineMs = this.options.forwardDeadlineMs ?? DEFAULT_FORWARD_DEADLINE_MS;
|
|
3201
|
-
const deadline = new Date(Date.now() + deadlineMs);
|
|
3202
|
-
return new Promise((resolve, reject) => {
|
|
3203
|
-
clientEntry.client.forward(
|
|
3204
|
-
protoReq,
|
|
3205
|
-
new Metadata(),
|
|
3206
|
-
{ deadline },
|
|
3207
|
-
(err, response) => {
|
|
3208
|
-
if (err) {
|
|
3209
|
-
reject(new TransportError(`Forward RPC failed: ${err.message}`));
|
|
3210
|
-
return;
|
|
3211
|
-
}
|
|
3212
|
-
if (!response) {
|
|
3213
|
-
reject(new TransportError("Forward RPC returned empty response"));
|
|
3214
|
-
return;
|
|
3215
|
-
}
|
|
3216
|
-
if (response.error) {
|
|
3217
|
-
reject(new TransportError(`Forward RPC error: ${response.error}`));
|
|
3218
|
-
return;
|
|
3219
|
-
}
|
|
3220
|
-
resolve({
|
|
3221
|
-
requestId: response.requestId,
|
|
3222
|
-
results: response.results.map((r) => ({
|
|
3223
|
-
changes: r.changes,
|
|
3224
|
-
lastInsertRowId: Number(r.lastInsertRowId)
|
|
3225
|
-
})),
|
|
3226
|
-
groupId: response.groupId || void 0,
|
|
3227
|
-
primaryTerm: response.primaryTerm === 0n ? void 0 : response.primaryTerm
|
|
3228
|
-
});
|
|
3229
|
-
}
|
|
3230
|
-
);
|
|
3231
|
-
});
|
|
3325
|
+
return forwardOverRpc(clientEntry, request, this.options.forwardDeadlineMs ?? DEFAULT_FORWARD_DEADLINE_MS);
|
|
3232
3326
|
}
|
|
3233
3327
|
async requestSync(peerId, request) {
|
|
3234
3328
|
this.ensureConnected();
|
|
@@ -1,137 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
protocolVersion?: string;
|
|
7
|
-
joinedAt: number;
|
|
8
|
-
lastSeenAt: number;
|
|
9
|
-
lastAckedSeq: bigint;
|
|
10
|
-
metadata?: Record<string, unknown>;
|
|
11
|
-
}
|
|
12
|
-
interface ReplicationChange {
|
|
13
|
-
table: string;
|
|
14
|
-
operation: 'insert' | 'update' | 'delete' | 'ddl';
|
|
15
|
-
rowId: string;
|
|
16
|
-
primaryKey: Record<string, unknown>;
|
|
17
|
-
hlc: string;
|
|
18
|
-
txId: string;
|
|
19
|
-
nodeId: string;
|
|
20
|
-
newData: Record<string, unknown> | null;
|
|
21
|
-
oldData: Record<string, unknown> | null;
|
|
22
|
-
ddlStatement?: string;
|
|
23
|
-
}
|
|
24
|
-
interface ReplicationBatch {
|
|
25
|
-
sourceNodeId: string;
|
|
26
|
-
batchId: string;
|
|
27
|
-
fromSeq: bigint;
|
|
28
|
-
toSeq: bigint;
|
|
29
|
-
hlcRange: {
|
|
30
|
-
min: string;
|
|
31
|
-
max: string;
|
|
32
|
-
};
|
|
33
|
-
changes: ReplicationChange[];
|
|
34
|
-
checksum: string;
|
|
35
|
-
groupId?: string;
|
|
36
|
-
primaryTerm?: bigint;
|
|
37
|
-
}
|
|
38
|
-
interface ReplicationAck {
|
|
39
|
-
batchId: string;
|
|
40
|
-
ackedSeq: bigint;
|
|
41
|
-
nodeId: string;
|
|
42
|
-
groupId?: string;
|
|
43
|
-
primaryTerm?: bigint;
|
|
44
|
-
}
|
|
45
|
-
interface ForwardedTransaction {
|
|
46
|
-
statements: Array<{
|
|
47
|
-
sql: string;
|
|
48
|
-
params?: Record<string, unknown> | unknown[];
|
|
49
|
-
}>;
|
|
50
|
-
requestId: string;
|
|
51
|
-
groupId?: string;
|
|
52
|
-
primaryTerm?: bigint;
|
|
53
|
-
}
|
|
54
|
-
interface ForwardedTransactionResult {
|
|
55
|
-
results: Array<{
|
|
56
|
-
changes: number;
|
|
57
|
-
lastInsertRowId: number | string;
|
|
58
|
-
}>;
|
|
59
|
-
requestId: string;
|
|
60
|
-
groupId?: string;
|
|
61
|
-
primaryTerm?: bigint;
|
|
62
|
-
}
|
|
63
|
-
type TopologyRole = 'primary' | 'replica';
|
|
64
|
-
interface TransportConfig {
|
|
65
|
-
endpoints?: string[];
|
|
66
|
-
localRole?: TopologyRole;
|
|
67
|
-
groupId?: string;
|
|
68
|
-
primaryTerm?: bigint;
|
|
69
|
-
protocolVersion?: string;
|
|
70
|
-
metadata?: Record<string, unknown>;
|
|
71
|
-
}
|
|
72
|
-
interface ReplicationTransport {
|
|
73
|
-
connect(localNodeId: string, config: TransportConfig): Promise<void>;
|
|
74
|
-
disconnect(): Promise<void>;
|
|
75
|
-
send(peerId: string, batch: ReplicationBatch): Promise<void>;
|
|
76
|
-
broadcast(batch: ReplicationBatch): Promise<void>;
|
|
77
|
-
sendAck(peerId: string, ack: ReplicationAck): Promise<void>;
|
|
78
|
-
forward(peerId: string, request: ForwardedTransaction): Promise<ForwardedTransactionResult>;
|
|
79
|
-
requestSync(peerId: string, request: SyncRequest): Promise<void>;
|
|
80
|
-
sendSyncBatch(peerId: string, batch: SyncBatch): Promise<void>;
|
|
81
|
-
sendSyncComplete(peerId: string, complete: SyncComplete): Promise<void>;
|
|
82
|
-
sendSyncAck(peerId: string, ack: SyncAck): Promise<void>;
|
|
83
|
-
onBatchReceived(handler: (batch: ReplicationBatch, fromPeerId: string) => Promise<void>): void;
|
|
84
|
-
onAckReceived(handler: (ack: ReplicationAck, fromPeerId: string) => void): void;
|
|
85
|
-
onForwardReceived(handler: (request: ForwardedTransaction, fromPeerId: string) => Promise<ForwardedTransactionResult>): void;
|
|
86
|
-
onSyncRequested(handler: (request: SyncRequest, fromPeerId: string) => Promise<void>): void;
|
|
87
|
-
onSyncBatchReceived(handler: (batch: SyncBatch, fromPeerId: string) => Promise<void>): void;
|
|
88
|
-
onSyncCompleteReceived(handler: (complete: SyncComplete, fromPeerId: string) => Promise<void>): void;
|
|
89
|
-
onSyncAckReceived(handler: (ack: SyncAck, fromPeerId: string) => void): void;
|
|
90
|
-
onPeerConnected(handler: (peer: NodeInfo) => void): void;
|
|
91
|
-
onPeerDisconnected(handler: (peerId: string) => void): void;
|
|
92
|
-
peers(): ReadonlyMap<string, NodeInfo>;
|
|
93
|
-
}
|
|
94
|
-
interface SyncRequest {
|
|
95
|
-
requestId: string;
|
|
96
|
-
joinerNodeId: string;
|
|
97
|
-
completedTables: string[];
|
|
98
|
-
groupId?: string;
|
|
99
|
-
primaryTerm?: bigint;
|
|
100
|
-
}
|
|
101
|
-
interface SyncBatch {
|
|
102
|
-
requestId: string;
|
|
103
|
-
table: string;
|
|
104
|
-
batchIndex: number;
|
|
105
|
-
rows: Record<string, unknown>[];
|
|
106
|
-
schema?: string[];
|
|
107
|
-
checksum: string;
|
|
108
|
-
isLastBatchForTable: boolean;
|
|
109
|
-
totalTables?: number;
|
|
110
|
-
groupId?: string;
|
|
111
|
-
primaryTerm?: bigint;
|
|
112
|
-
}
|
|
113
|
-
interface SyncTableManifest {
|
|
114
|
-
table: string;
|
|
115
|
-
rowCount: number;
|
|
116
|
-
pkHash: string;
|
|
117
|
-
}
|
|
118
|
-
interface SyncComplete {
|
|
119
|
-
requestId: string;
|
|
120
|
-
snapshotSeq: bigint;
|
|
121
|
-
manifests: SyncTableManifest[];
|
|
122
|
-
groupId?: string;
|
|
123
|
-
primaryTerm?: bigint;
|
|
124
|
-
}
|
|
125
|
-
interface SyncAck {
|
|
126
|
-
requestId: string;
|
|
127
|
-
joinerNodeId: string;
|
|
128
|
-
table: string;
|
|
129
|
-
batchIndex: number;
|
|
130
|
-
success: boolean;
|
|
131
|
-
error?: string;
|
|
132
|
-
groupId?: string;
|
|
133
|
-
primaryTerm?: bigint;
|
|
134
|
-
}
|
|
1
|
+
import { N as NodeInfo, R as ReplicationAck, F as ForwardedTransaction, a as ForwardedTransactionResult, S as SyncRequest, b as SyncBatch, c as SyncComplete, d as SyncAck, e as ReplicationTransport, T as TransportConfig } from '../types-B7gmEsZW.js';
|
|
2
|
+
import { R as ReplicationBatch } from '../types-C_D8IhpO.js';
|
|
3
|
+
import '../change-tracker-DKRVUC3l.js';
|
|
4
|
+
import '../types-zhnRXrsb.js';
|
|
5
|
+
import '../types-BsVabqSI.js';
|
|
135
6
|
|
|
136
7
|
type BatchHandler = (batch: ReplicationBatch, fromPeerId: string) => Promise<void>;
|
|
137
8
|
type AckHandler = (ack: ReplicationAck, fromPeerId: string) => void;
|
|
@@ -27,7 +27,7 @@ var SirannonError = class extends Error {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
// src/
|
|
30
|
+
// src/core/sync/errors.ts
|
|
31
31
|
var ReplicationError = class extends SirannonError {
|
|
32
32
|
constructor(message, code = "REPLICATION_ERROR", details) {
|
|
33
33
|
super(message, code);
|
|
@@ -35,6 +35,8 @@ var ReplicationError = class extends SirannonError {
|
|
|
35
35
|
this.name = "ReplicationError";
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
|
+
|
|
39
|
+
// src/replication/errors.ts
|
|
38
40
|
var TransportError = class extends ReplicationError {
|
|
39
41
|
constructor(message) {
|
|
40
42
|
super(message, "TRANSPORT_ERROR");
|