@delali/sirannon-db 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backup-scheduler/index.d.ts +15 -1
- package/dist/backup-scheduler/index.mjs +2 -2
- package/dist/baseline-D93hcIEE.d.ts +17 -0
- package/dist/{change-tracker-DKRVUC3l.d.ts → change-tracker-DDmXB754.d.ts} +56 -8
- package/dist/{chunk-5NOIGN5Y.mjs → chunk-2QLXDHAP.mjs} +1 -1
- package/dist/{chunk-LNY2VVHE.mjs → chunk-7C36BCSN.mjs} +1 -1
- package/dist/{chunk-NVQS53NT.mjs → chunk-7FQRQH5Z.mjs} +53 -64
- package/dist/{chunk-D7LAYTKN.mjs → chunk-7R4ER4FB.mjs} +1 -1
- package/dist/{chunk-FHWTZFI4.mjs → chunk-BQFQ65OL.mjs} +1 -1
- package/dist/{chunk-O7SLN3GI.mjs → chunk-BTTFW4Z4.mjs} +1 -1
- package/dist/{chunk-H6PIVVDN.mjs → chunk-CCZK6LCB.mjs} +38 -25
- package/dist/{chunk-JZGINXTN.mjs → chunk-HCCGEIZ2.mjs} +2 -2
- package/dist/{chunk-67M7KAH6.mjs → chunk-IWGIYDMZ.mjs} +1 -1
- package/dist/{chunk-LFZ37BSX.mjs → chunk-OUSWVNWT.mjs} +1 -1
- package/dist/{chunk-HR5CWTLC.mjs → chunk-P2VJYRVY.mjs} +60 -7
- package/dist/{chunk-UC3SCMIN.mjs → chunk-PBRXXISQ.mjs} +3 -0
- package/dist/{chunk-JU64Y7HM.mjs → chunk-SBL6GN43.mjs} +1 -1
- package/dist/{chunk-EBJXPQQO.mjs → chunk-UPKKSUPA.mjs} +2 -2
- package/dist/{chunk-TJF5GZSV.mjs → chunk-VOSJBZ6Q.mjs} +1 -1
- package/dist/{chunk-PIKHN33N.mjs → chunk-VOYGMAU7.mjs} +9 -1
- package/dist/{chunk-H237TXZW.mjs → chunk-WJ67DTD6.mjs} +48 -6
- package/dist/{chunk-OQVZBEBY.mjs → chunk-XF2HH5E6.mjs} +4 -61
- package/dist/client/index.d.ts +211 -12
- package/dist/client/index.mjs +155 -67
- package/dist/client/topology.d.ts +55 -7
- package/dist/client/topology.mjs +20 -1
- package/dist/{client-base-CLWmH5Ln.d.ts → client-base-CmZO0v3m.d.ts} +133 -24
- package/dist/codegen/cli.mjs +3 -3
- package/dist/codegen/index.d.ts +92 -2
- package/dist/codegen/index.mjs +3 -3
- package/dist/core/index.d.ts +177 -15
- package/dist/core/index.mjs +2481 -2226
- package/dist/core/writer-worker.mjs +3 -3
- package/dist/database-B5Qv1-cU.d.ts +380 -0
- package/dist/driver/better-sqlite3.d.ts +18 -1
- package/dist/driver/better-sqlite3.mjs +5 -5
- package/dist/driver/bun.d.ts +28 -0
- package/dist/driver/expo.d.ts +17 -0
- package/dist/driver/node.d.ts +18 -1
- package/dist/driver/node.mjs +5 -5
- package/dist/driver/wa-sqlite.d.ts +18 -1
- package/dist/{errors-Bw5MdNCu.d.ts → errors-Dei4GdBb.d.ts} +80 -7
- package/dist/file-migrations/index.d.ts +54 -2
- package/dist/file-migrations/index.mjs +3 -3
- package/dist/{operation-registry-9DcvxcE5.d.ts → operation-registry-hlbhqu7q.d.ts} +50 -1
- package/dist/{primary-wins-DPAm2AKG.d.ts → primary-wins-B0np8JS3.d.ts} +25 -1
- package/dist/protocol-rqANt-9Q.d.ts +152 -0
- package/dist/query-types-DL3LtPvY.d.ts +95 -0
- package/dist/react/index.d.ts +58 -3
- package/dist/replication/coordinator/etcd.d.ts +63 -3
- package/dist/replication/coordinator/etcd.mjs +82 -46
- package/dist/replication/index.d.ts +329 -95
- package/dist/replication/index.mjs +256 -141
- package/dist/server/index.d.ts +230 -12
- package/dist/server/index.mjs +63 -50
- package/dist/{server-options-1JHu8pid.d.ts → server-options-Dab_Jvd_.d.ts} +96 -12
- package/dist/sirannon-CMhiJa5Y.d.ts +111 -0
- package/dist/transport/grpc.d.ts +93 -9
- package/dist/transport/grpc.mjs +63 -20
- package/dist/transport/memory.d.ts +50 -20
- package/dist/transport/memory.mjs +25 -0
- package/dist/{types-CL6piSnD.d.ts → types-BCejqzNA.d.ts} +20 -0
- package/dist/types-CMBcFPhb.d.ts +336 -0
- package/dist/types-CjhxcjhA.d.ts +123 -0
- package/dist/types-DyrCiWuc.d.ts +499 -0
- package/dist/types-rVZKnKN-.d.ts +591 -0
- package/package.json +7 -1
- package/dist/baseline-Br77Fnhb.d.ts +0 -6
- package/dist/database-BY0L5Q2n.d.ts +0 -172
- package/dist/protocol-6KrSq2Hy.d.ts +0 -66
- package/dist/sirannon-DaQSyhbJ.d.ts +0 -36
- package/dist/types-B7gmEsZW.d.ts +0 -221
- package/dist/types-BsVabqSI.d.ts +0 -139
- package/dist/types-C_D8IhpO.d.ts +0 -60
- package/dist/types-zhnRXrsb.d.ts +0 -384
package/dist/client/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DatabaseClient, createEndpointTransport, toBaseUrl, DEFAULT_HTTP_REQUEST_TIMEOUT_MS, postJson, decodeTaggedValues, RemoteError, encodeTaggedValues,
|
|
2
|
-
export { HttpTransport, RemoteDatabase, RemoteError, RemoteLiveQuery, RemoteSubscriptionBuilderImpl, SQL_REFUSED_MESSAGE, ServerCapabilities, WebSocketTransport } from '../chunk-
|
|
1
|
+
import { DatabaseClient, createEndpointTransport, toBaseUrl, DEFAULT_HTTP_REQUEST_TIMEOUT_MS, postJson, decodeTaggedValues, RemoteError, encodeTaggedValues, STAGED_STREAM_CAPABILITY, verifyDeviceSyncCapabilities, unrefTimer, toWsUrl, WebSocketTransport } from '../chunk-WJ67DTD6.mjs';
|
|
2
|
+
export { HttpTransport, RemoteDatabase, RemoteError, RemoteLiveQuery, RemoteSubscriptionBuilderImpl, SQL_REFUSED_MESSAGE, ServerCapabilities, WebSocketTransport } from '../chunk-WJ67DTD6.mjs';
|
|
3
3
|
|
|
4
4
|
// src/core/sync/canonicalise.ts
|
|
5
5
|
function canonicaliseForChecksum(value) {
|
|
@@ -74,7 +74,11 @@ var HLC = class _HLC {
|
|
|
74
74
|
this.wallMs = 0;
|
|
75
75
|
this.logical = 0;
|
|
76
76
|
}
|
|
77
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Generate a new HLC timestamp, advancing the clock.
|
|
79
|
+
*
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
78
82
|
now() {
|
|
79
83
|
const physicalMs = Date.now();
|
|
80
84
|
if (physicalMs > this.wallMs) {
|
|
@@ -88,7 +92,11 @@ var HLC = class _HLC {
|
|
|
88
92
|
}
|
|
89
93
|
return _HLC.encode(this.wallMs, this.logical, this.nodeId);
|
|
90
94
|
}
|
|
91
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Merge a remote HLC timestamp into the local clock and return the updated value.
|
|
97
|
+
*
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
92
100
|
receive(remote) {
|
|
93
101
|
const r = _HLC.decode(remote);
|
|
94
102
|
const physicalMs = Date.now();
|
|
@@ -126,6 +134,14 @@ var HLC = class _HLC {
|
|
|
126
134
|
nodeId: parts.slice(2).join("-")
|
|
127
135
|
};
|
|
128
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Builds the string form of a clock reading, which sorts in the same order as the reading itself.
|
|
139
|
+
*
|
|
140
|
+
* @param wallMs - Wall-clock milliseconds since the Unix epoch.
|
|
141
|
+
* @param logical - Counter that orders events sharing one millisecond.
|
|
142
|
+
* @param nodeId - Identifier of the node taking the reading.
|
|
143
|
+
* @returns The encoded stamp.
|
|
144
|
+
*/
|
|
129
145
|
static encode(wallMs, logical, nodeId) {
|
|
130
146
|
const wallHex = wallMs.toString(16).padStart(12, "0");
|
|
131
147
|
const logicalHex = logical.toString(16).padStart(4, "0");
|
|
@@ -135,6 +151,12 @@ var HLC = class _HLC {
|
|
|
135
151
|
|
|
136
152
|
// src/core/sync/conflict/lww.ts
|
|
137
153
|
var LWWResolver = class {
|
|
154
|
+
/**
|
|
155
|
+
* Takes the incoming row when its stamp is higher, and keeps the local row otherwise.
|
|
156
|
+
*
|
|
157
|
+
* @param ctx - The local and incoming versions of one row.
|
|
158
|
+
* @returns Which version to write.
|
|
159
|
+
*/
|
|
138
160
|
resolve(ctx) {
|
|
139
161
|
if (ctx.remoteChange.operation === "delete") {
|
|
140
162
|
return { action: "accept_remote" };
|
|
@@ -163,6 +185,12 @@ var FieldMergeResolver = class {
|
|
|
163
185
|
constructor(getColumnVersions) {
|
|
164
186
|
this.getColumnVersions = getColumnVersions;
|
|
165
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Merges columns only one side changed, and settles overlapping columns by their per-column stamps.
|
|
190
|
+
*
|
|
191
|
+
* @param ctx - The local and incoming versions of one row.
|
|
192
|
+
* @returns Which version to write, or the merged row.
|
|
193
|
+
*/
|
|
166
194
|
async resolve(ctx) {
|
|
167
195
|
const columnVersions = await this.getColumnVersions(ctx.table, ctx.rowId);
|
|
168
196
|
if (columnVersions.size === 0) {
|
|
@@ -237,6 +265,12 @@ var PrimaryWinsResolver = class {
|
|
|
237
265
|
constructor(primaryNodeId) {
|
|
238
266
|
this.primaryNodeId = primaryNodeId;
|
|
239
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Takes the version authored by the configured primary node, and falls back to last-writer-wins otherwise.
|
|
270
|
+
*
|
|
271
|
+
* @param ctx - The local and incoming versions of one row.
|
|
272
|
+
* @returns Which version to write.
|
|
273
|
+
*/
|
|
240
274
|
resolve(ctx) {
|
|
241
275
|
if (ctx.remoteChange.nodeId === this.primaryNodeId) {
|
|
242
276
|
return { action: "accept_remote" };
|
|
@@ -266,9 +300,20 @@ var SirannonClient = class extends DatabaseClient {
|
|
|
266
300
|
super(options);
|
|
267
301
|
this.baseUrl = normaliseClientUrl(url);
|
|
268
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Builds the transport a database's requests travel over.
|
|
305
|
+
*
|
|
306
|
+
* @param databaseId - Identifier of the database.
|
|
307
|
+
* @returns A transport bound to that database.
|
|
308
|
+
*/
|
|
269
309
|
createTransport(databaseId) {
|
|
270
310
|
return createEndpointTransport(this.settings, this.baseUrl, databaseId);
|
|
271
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Returns the address requests are sent to.
|
|
314
|
+
*
|
|
315
|
+
* @returns The server's base address.
|
|
316
|
+
*/
|
|
272
317
|
resolveServerUrl() {
|
|
273
318
|
return this.baseUrl;
|
|
274
319
|
}
|
|
@@ -875,7 +920,7 @@ var PushLoop = class {
|
|
|
875
920
|
this.timer = null;
|
|
876
921
|
}
|
|
877
922
|
/**
|
|
878
|
-
* Empties the outbox before a snapshot replaces the database
|
|
923
|
+
* Empties the outbox before a snapshot replaces the database so that local work
|
|
879
924
|
* reaches the server before the copy overwrites it. A schema refusal is
|
|
880
925
|
* reconciled once; a device that still cannot push returns rather than
|
|
881
926
|
* looping, leaving the snapshot to bring it back into line.
|
|
@@ -1007,13 +1052,75 @@ var ResyncScheduler = class {
|
|
|
1007
1052
|
}
|
|
1008
1053
|
};
|
|
1009
1054
|
|
|
1010
|
-
// src/client/sync-controller.ts
|
|
1055
|
+
// src/client/sync-controller-wiring.ts
|
|
1011
1056
|
var DEFAULT_BATCH_SIZE = 100;
|
|
1012
1057
|
var DEFAULT_PUSH_INTERVAL_MS = 1e3;
|
|
1013
1058
|
var DEFAULT_ACK_INTERVAL_MS = 2e3;
|
|
1014
1059
|
var DEFAULT_MAX_PUSH_RETRY_DELAY_MS = 3e4;
|
|
1015
1060
|
var DEFAULT_SNAPSHOT_RETRY_DELAY_MS = 5e3;
|
|
1016
1061
|
var DEFAULT_MAX_SNAPSHOT_RETRY_DELAY_MS = 3e5;
|
|
1062
|
+
function createSyncCollaborators(baseUrl, options, host) {
|
|
1063
|
+
const isRunning = () => host.state() === "running";
|
|
1064
|
+
const push = new PushLoop(
|
|
1065
|
+
{
|
|
1066
|
+
baseUrl,
|
|
1067
|
+
databaseId: options.databaseId,
|
|
1068
|
+
headers: options.headers,
|
|
1069
|
+
requestTimeout: options.requestTimeout,
|
|
1070
|
+
batchSize: options.batchSize ?? DEFAULT_BATCH_SIZE,
|
|
1071
|
+
intervalMs: options.pushIntervalMs ?? DEFAULT_PUSH_INTERVAL_MS,
|
|
1072
|
+
maxRetryDelayMs: options.maxPushRetryDelayMs ?? DEFAULT_MAX_PUSH_RETRY_DELAY_MS
|
|
1073
|
+
},
|
|
1074
|
+
{
|
|
1075
|
+
isRunning,
|
|
1076
|
+
port: () => host.port(),
|
|
1077
|
+
schemaVersion: () => host.schemaVersion(),
|
|
1078
|
+
reconcileSchema: () => host.reconcileSchema(),
|
|
1079
|
+
recordError: (err) => host.recordError(err),
|
|
1080
|
+
onDrained: () => host.clearError()
|
|
1081
|
+
}
|
|
1082
|
+
);
|
|
1083
|
+
const pull = new PullStream(
|
|
1084
|
+
{
|
|
1085
|
+
wsBaseUrl: toWsUrl(baseUrl),
|
|
1086
|
+
databaseId: options.databaseId,
|
|
1087
|
+
tables: options.tables,
|
|
1088
|
+
headers: options.headers,
|
|
1089
|
+
ackIntervalMs: options.ackIntervalMs ?? DEFAULT_ACK_INTERVAL_MS,
|
|
1090
|
+
requestTimeout: options.requestTimeout,
|
|
1091
|
+
immediateAckAfterChanges: options.immediateAckAfterChanges,
|
|
1092
|
+
resolver: options.resolver
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
isRunning,
|
|
1096
|
+
port: () => host.port(),
|
|
1097
|
+
onChange: options.onChange,
|
|
1098
|
+
onResyncRequired: () => host.markResyncRequired(),
|
|
1099
|
+
onApplyFailure: (err) => host.onApplyFailure(err),
|
|
1100
|
+
onApplySuccess: () => host.onApplySuccess(),
|
|
1101
|
+
recordError: (err) => host.recordError(err)
|
|
1102
|
+
}
|
|
1103
|
+
);
|
|
1104
|
+
const resync = new ResyncScheduler(
|
|
1105
|
+
{
|
|
1106
|
+
autoResync: options.autoResync,
|
|
1107
|
+
retryDelayMs: options.snapshotRetryDelayMs ?? DEFAULT_SNAPSHOT_RETRY_DELAY_MS,
|
|
1108
|
+
maxRetryDelayMs: options.maxSnapshotRetryDelayMs ?? DEFAULT_MAX_SNAPSHOT_RETRY_DELAY_MS,
|
|
1109
|
+
onResyncRequired: options.onResyncRequired,
|
|
1110
|
+
onSnapshotComplete: options.onSnapshotComplete
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
isRunning,
|
|
1114
|
+
isSnapshotting: () => host.state() === "snapshotting",
|
|
1115
|
+
port: () => host.port(),
|
|
1116
|
+
recordError: (err) => host.recordError(err),
|
|
1117
|
+
download: () => host.download()
|
|
1118
|
+
}
|
|
1119
|
+
);
|
|
1120
|
+
return { push, pull, resync };
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// src/client/sync-controller.ts
|
|
1017
1124
|
var SyncController = class {
|
|
1018
1125
|
constructor(db, options) {
|
|
1019
1126
|
this.db = db;
|
|
@@ -1021,69 +1128,25 @@ var SyncController = class {
|
|
|
1021
1128
|
this.baseUrl = toBaseUrl(options.url);
|
|
1022
1129
|
this.pushIntervalMs = options.pushIntervalMs ?? DEFAULT_PUSH_INTERVAL_MS;
|
|
1023
1130
|
this.maxPushRetryDelayMs = options.maxPushRetryDelayMs ?? DEFAULT_MAX_PUSH_RETRY_DELAY_MS;
|
|
1024
|
-
this.
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
maxRetryDelayMs: this.maxPushRetryDelayMs
|
|
1033
|
-
},
|
|
1034
|
-
{
|
|
1035
|
-
isRunning: () => this.state === "running",
|
|
1036
|
-
port: () => this.port,
|
|
1037
|
-
schemaVersion: () => this.schemaVersion ?? 0,
|
|
1038
|
-
reconcileSchema: () => this.reconcileSchema(),
|
|
1039
|
-
recordError: (err) => this.recordError(err),
|
|
1040
|
-
onDrained: () => {
|
|
1041
|
-
this.lastError = null;
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
);
|
|
1045
|
-
this.pull = new PullStream(
|
|
1046
|
-
{
|
|
1047
|
-
wsBaseUrl: toWsUrl(this.baseUrl),
|
|
1048
|
-
databaseId: options.databaseId,
|
|
1049
|
-
tables: options.tables,
|
|
1050
|
-
headers: options.headers,
|
|
1051
|
-
ackIntervalMs: options.ackIntervalMs ?? DEFAULT_ACK_INTERVAL_MS,
|
|
1052
|
-
requestTimeout: options.requestTimeout,
|
|
1053
|
-
immediateAckAfterChanges: options.immediateAckAfterChanges,
|
|
1054
|
-
resolver: options.resolver
|
|
1131
|
+
const collaborators = createSyncCollaborators(this.baseUrl, options, {
|
|
1132
|
+
state: () => this.state,
|
|
1133
|
+
port: () => this.port,
|
|
1134
|
+
schemaVersion: () => this.schemaVersion ?? 0,
|
|
1135
|
+
reconcileSchema: () => this.reconcileSchema(),
|
|
1136
|
+
recordError: (err) => this.recordError(err),
|
|
1137
|
+
clearError: () => {
|
|
1138
|
+
this.lastError = null;
|
|
1055
1139
|
},
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
onResyncRequired: () => this.markResyncRequired(),
|
|
1061
|
-
onApplyFailure: (err) => this.handleApplyFailure(err),
|
|
1062
|
-
onApplySuccess: () => {
|
|
1063
|
-
this.consecutivePullFailures = 0;
|
|
1064
|
-
},
|
|
1065
|
-
recordError: (err) => this.recordError(err)
|
|
1066
|
-
}
|
|
1067
|
-
);
|
|
1068
|
-
this.resync = new ResyncScheduler(
|
|
1069
|
-
{
|
|
1070
|
-
autoResync: options.autoResync,
|
|
1071
|
-
retryDelayMs: options.snapshotRetryDelayMs ?? DEFAULT_SNAPSHOT_RETRY_DELAY_MS,
|
|
1072
|
-
maxRetryDelayMs: options.maxSnapshotRetryDelayMs ?? DEFAULT_MAX_SNAPSHOT_RETRY_DELAY_MS,
|
|
1073
|
-
onResyncRequired: options.onResyncRequired,
|
|
1074
|
-
onSnapshotComplete: options.onSnapshotComplete
|
|
1140
|
+
markResyncRequired: () => this.markResyncRequired(),
|
|
1141
|
+
onApplyFailure: (err) => this.handleApplyFailure(err),
|
|
1142
|
+
onApplySuccess: () => {
|
|
1143
|
+
this.consecutivePullFailures = 0;
|
|
1075
1144
|
},
|
|
1076
|
-
{
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
download: () => this.downloadSnapshot({
|
|
1082
|
-
pageSize: options.snapshotPageSize,
|
|
1083
|
-
onProgress: options.onSnapshotProgress
|
|
1084
|
-
})
|
|
1085
|
-
}
|
|
1086
|
-
);
|
|
1145
|
+
download: () => this.downloadSnapshot({ pageSize: options.snapshotPageSize, onProgress: options.onSnapshotProgress })
|
|
1146
|
+
});
|
|
1147
|
+
this.push = collaborators.push;
|
|
1148
|
+
this.pull = collaborators.pull;
|
|
1149
|
+
this.resync = collaborators.resync;
|
|
1087
1150
|
}
|
|
1088
1151
|
baseUrl;
|
|
1089
1152
|
pushIntervalMs;
|
|
@@ -1099,6 +1162,9 @@ var SyncController = class {
|
|
|
1099
1162
|
pullRetryTimer = null;
|
|
1100
1163
|
consecutivePullFailures = 0;
|
|
1101
1164
|
lastError = null;
|
|
1165
|
+
/**
|
|
1166
|
+
* Connects to the server and starts pushing and pulling changes.
|
|
1167
|
+
*/
|
|
1102
1168
|
async start() {
|
|
1103
1169
|
if (this.state === "running" || this.state === "starting") return;
|
|
1104
1170
|
this.state = "starting";
|
|
@@ -1138,23 +1204,37 @@ var SyncController = class {
|
|
|
1138
1204
|
this.resync.schedule();
|
|
1139
1205
|
}
|
|
1140
1206
|
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Holds pushing and pulling without disconnecting.
|
|
1209
|
+
*/
|
|
1141
1210
|
pause() {
|
|
1142
1211
|
if (this.state !== "running") return;
|
|
1143
1212
|
this.teardownStream();
|
|
1144
1213
|
this.state = "paused";
|
|
1145
1214
|
void this.pull.persist();
|
|
1146
1215
|
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Resumes pushing and pulling after a pause.
|
|
1218
|
+
*/
|
|
1147
1219
|
async resume() {
|
|
1148
1220
|
if (this.state !== "paused") return;
|
|
1149
1221
|
this.state = "stopped";
|
|
1150
1222
|
await this.start();
|
|
1151
1223
|
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Stops syncing and closes the connection to the server.
|
|
1226
|
+
*/
|
|
1152
1227
|
async stop() {
|
|
1153
1228
|
if (this.state === "stopped") return;
|
|
1154
1229
|
this.teardownStream();
|
|
1155
1230
|
this.state = "stopped";
|
|
1156
1231
|
await this.pull.persist();
|
|
1157
1232
|
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Reports where this device stands against the server.
|
|
1235
|
+
*
|
|
1236
|
+
* @returns The device's state, cursors, pending push count, and last failure.
|
|
1237
|
+
*/
|
|
1158
1238
|
async status() {
|
|
1159
1239
|
const pendingPushCount = this.port ? await this.port.countOutboxPending(this.push.cursor) : 0;
|
|
1160
1240
|
return {
|
|
@@ -1170,6 +1250,9 @@ var SyncController = class {
|
|
|
1170
1250
|
lastError: this.lastError
|
|
1171
1251
|
};
|
|
1172
1252
|
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Pushes local changes now instead of waiting for the next interval.
|
|
1255
|
+
*/
|
|
1173
1256
|
triggerPush() {
|
|
1174
1257
|
void this.push.drain();
|
|
1175
1258
|
}
|
|
@@ -1211,6 +1294,11 @@ var SyncController = class {
|
|
|
1211
1294
|
this.resync.markRequired();
|
|
1212
1295
|
this.resync.schedule();
|
|
1213
1296
|
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Replaces the local database with a fresh copy from the server and resumes syncing from it.
|
|
1299
|
+
*
|
|
1300
|
+
* @param options - Page size and the progress callback for this download.
|
|
1301
|
+
*/
|
|
1214
1302
|
async downloadSnapshot(options) {
|
|
1215
1303
|
if (this.state === "snapshotting") {
|
|
1216
1304
|
throw new Error("A snapshot download is already in progress");
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import '../
|
|
5
|
-
import '../
|
|
6
|
-
import '../
|
|
7
|
-
import '../types-
|
|
1
|
+
import { a as ReadConcernLevel } from '../query-types-DL3LtPvY.js';
|
|
2
|
+
import { C as ClientOptions } from '../server-options-Dab_Jvd_.js';
|
|
3
|
+
import { T as Transport, D as DatabaseClient } from '../client-base-CmZO0v3m.js';
|
|
4
|
+
import '../operation-registry-hlbhqu7q.js';
|
|
5
|
+
import '../types-CjhxcjhA.js';
|
|
6
|
+
import '../types-rVZKnKN-.js';
|
|
7
|
+
import '../types-BCejqzNA.js';
|
|
8
|
+
import '../protocol-rqANt-9Q.js';
|
|
8
9
|
|
|
9
10
|
interface TopologyRouting {
|
|
10
11
|
_getReadEndpoint(databaseId?: string, readConcern?: ReadConcernLevel): Promise<string>;
|
|
@@ -16,14 +17,42 @@ interface TopologyRouting {
|
|
|
16
17
|
_createTransportForEndpoint(url: string, databaseId: string): Transport;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
*
|
|
23
|
+
* Which nodes the client holds, how it finds the rest, and where it sends each read.
|
|
24
|
+
*/
|
|
19
25
|
interface TopologyAwareClientOptions extends ClientOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Nodes the client starts from when it discovers the group through the coordinator.
|
|
28
|
+
*/
|
|
20
29
|
endpoints?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Address of the primary, for a group you list by hand.
|
|
32
|
+
*/
|
|
21
33
|
primary?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Addresses of the replicas, for a group you list by hand.
|
|
36
|
+
*/
|
|
22
37
|
replicas?: string[];
|
|
38
|
+
/**
|
|
39
|
+
* Where reads go. Default: 'primary'.
|
|
40
|
+
*/
|
|
23
41
|
readPreference?: 'primary' | 'replica' | 'nearest';
|
|
42
|
+
/**
|
|
43
|
+
* Whether the client uses the nodes you listed or asks the group for them. Default: 'static'.
|
|
44
|
+
*/
|
|
24
45
|
discovery?: 'static' | 'coordinator';
|
|
46
|
+
/**
|
|
47
|
+
* Currency every read requires, which the client uses to choose a node.
|
|
48
|
+
*/
|
|
25
49
|
readConcern?: ReadConcernLevel;
|
|
26
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* @public
|
|
53
|
+
*
|
|
54
|
+
* Connects to a replication group rather than one server: it routes each read to a node that meets its read concern, and each write to the primary.
|
|
55
|
+
*/
|
|
27
56
|
declare class TopologyAwareClient extends DatabaseClient implements TopologyRouting {
|
|
28
57
|
private readonly baseUrl;
|
|
29
58
|
private readonly primaryUrl;
|
|
@@ -39,15 +68,34 @@ declare class TopologyAwareClient extends DatabaseClient implements TopologyRout
|
|
|
39
68
|
private latencyMeasuring;
|
|
40
69
|
private readonly removedReplicas;
|
|
41
70
|
constructor(options: TopologyAwareClientOptions);
|
|
71
|
+
/**
|
|
72
|
+
* Builds the routing transport a database's requests travel over.
|
|
73
|
+
*
|
|
74
|
+
* @param databaseId - Identifier of the database.
|
|
75
|
+
* @returns A transport that picks a node per request.
|
|
76
|
+
*/
|
|
42
77
|
protected createTransport(databaseId: string): Transport;
|
|
78
|
+
/** @internal */
|
|
43
79
|
_createTransportForEndpoint(url: string, databaseId: string): Transport;
|
|
80
|
+
/**
|
|
81
|
+
* Returns the address writes are sent to, which is the current primary.
|
|
82
|
+
*
|
|
83
|
+
* @param databaseId - Identifier of the database.
|
|
84
|
+
* @returns Address of the node that accepts writes.
|
|
85
|
+
*/
|
|
44
86
|
protected resolveServerUrl(databaseId: string): Promise<string>;
|
|
87
|
+
/** @internal */
|
|
45
88
|
_getReadEndpoint(databaseId?: string, readConcern?: ReadConcernLevel): Promise<string>;
|
|
46
89
|
private routedReadEndpoint;
|
|
90
|
+
/** @internal */
|
|
47
91
|
_getWriteEndpoint(databaseId?: string): Promise<string>;
|
|
92
|
+
/** @internal */
|
|
48
93
|
_getReadConcern(): ReadConcernLevel | undefined;
|
|
94
|
+
/** @internal */
|
|
49
95
|
_usesCoordinatorDiscovery(): boolean;
|
|
96
|
+
/** @internal */
|
|
50
97
|
_removeReplica(url: string): void;
|
|
98
|
+
/** @internal */
|
|
51
99
|
_refreshClusterRouting(databaseId: string): Promise<void>;
|
|
52
100
|
private fetchClusterRouting;
|
|
53
101
|
private ensureClusterRouting;
|
package/dist/client/topology.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DatabaseClient, toBaseUrl, createEndpointTransport, RemoteError, toServerBaseUrl, unrefTimer } from '../chunk-
|
|
1
|
+
import { DatabaseClient, toBaseUrl, createEndpointTransport, RemoteError, toServerBaseUrl, unrefTimer } from '../chunk-WJ67DTD6.mjs';
|
|
2
2
|
|
|
3
3
|
// src/client/cluster-routing.ts
|
|
4
4
|
function clusterRoutingFingerprint(state) {
|
|
@@ -484,6 +484,12 @@ var TopologyAwareClient = class extends DatabaseClient {
|
|
|
484
484
|
this.starterEndpoints = (options.endpoints ?? []).map(toBaseUrl);
|
|
485
485
|
this.baseUrl = this.primaryUrl ?? this.replicaUrls[0] ?? this.starterEndpoints[0] ?? "";
|
|
486
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* Builds the routing transport a database's requests travel over.
|
|
489
|
+
*
|
|
490
|
+
* @param databaseId - Identifier of the database.
|
|
491
|
+
* @returns A transport that picks a node per request.
|
|
492
|
+
*/
|
|
487
493
|
createTransport(databaseId) {
|
|
488
494
|
const transport = new TopologyAwareTransport(
|
|
489
495
|
databaseId,
|
|
@@ -493,12 +499,20 @@ var TopologyAwareClient = class extends DatabaseClient {
|
|
|
493
499
|
this.topologyTransports.set(databaseId, transport);
|
|
494
500
|
return transport;
|
|
495
501
|
}
|
|
502
|
+
/** @internal */
|
|
496
503
|
_createTransportForEndpoint(url, databaseId) {
|
|
497
504
|
return createEndpointTransport(this.settings, url, databaseId);
|
|
498
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* Returns the address writes are sent to, which is the current primary.
|
|
508
|
+
*
|
|
509
|
+
* @param databaseId - Identifier of the database.
|
|
510
|
+
* @returns Address of the node that accepts writes.
|
|
511
|
+
*/
|
|
499
512
|
async resolveServerUrl(databaseId) {
|
|
500
513
|
return this._getWriteEndpoint(databaseId);
|
|
501
514
|
}
|
|
515
|
+
/** @internal */
|
|
502
516
|
async _getReadEndpoint(databaseId, readConcern) {
|
|
503
517
|
if (this.discovery === "coordinator" && databaseId) {
|
|
504
518
|
return this.routedReadEndpoint(databaseId, readConcern);
|
|
@@ -541,6 +555,7 @@ var TopologyAwareClient = class extends DatabaseClient {
|
|
|
541
555
|
if (localReadable) return localReadable.url;
|
|
542
556
|
throw new RemoteError("ROUTING_ERROR", "No usable read endpoint is available");
|
|
543
557
|
}
|
|
558
|
+
/** @internal */
|
|
544
559
|
async _getWriteEndpoint(databaseId) {
|
|
545
560
|
if (this.discovery === "coordinator" && databaseId) {
|
|
546
561
|
const routing = await this.ensureClusterRouting(databaseId);
|
|
@@ -551,15 +566,19 @@ var TopologyAwareClient = class extends DatabaseClient {
|
|
|
551
566
|
}
|
|
552
567
|
return this.primaryUrl ?? this.baseUrl;
|
|
553
568
|
}
|
|
569
|
+
/** @internal */
|
|
554
570
|
_getReadConcern() {
|
|
555
571
|
return this.readConcern;
|
|
556
572
|
}
|
|
573
|
+
/** @internal */
|
|
557
574
|
_usesCoordinatorDiscovery() {
|
|
558
575
|
return this.discovery === "coordinator";
|
|
559
576
|
}
|
|
577
|
+
/** @internal */
|
|
560
578
|
_removeReplica(url) {
|
|
561
579
|
this.removedReplicas.add(url);
|
|
562
580
|
}
|
|
581
|
+
/** @internal */
|
|
563
582
|
async _refreshClusterRouting(databaseId) {
|
|
564
583
|
const encodedId = encodeURIComponent(databaseId);
|
|
565
584
|
for (const endpoint of this.clusterDiscoveryCandidates(databaseId)) {
|