@powersync/service-module-mongodb 0.0.0-dev-20241001150444
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/CHANGELOG.md +15 -0
- package/LICENSE +67 -0
- package/README.md +3 -0
- package/dist/api/MongoRouteAPIAdapter.d.ts +22 -0
- package/dist/api/MongoRouteAPIAdapter.js +64 -0
- package/dist/api/MongoRouteAPIAdapter.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/module/MongoModule.d.ts +13 -0
- package/dist/module/MongoModule.js +46 -0
- package/dist/module/MongoModule.js.map +1 -0
- package/dist/replication/ChangeStream.d.ts +53 -0
- package/dist/replication/ChangeStream.js +389 -0
- package/dist/replication/ChangeStream.js.map +1 -0
- package/dist/replication/ChangeStreamReplicationJob.d.ts +16 -0
- package/dist/replication/ChangeStreamReplicationJob.js +90 -0
- package/dist/replication/ChangeStreamReplicationJob.js.map +1 -0
- package/dist/replication/ChangeStreamReplicator.d.ts +13 -0
- package/dist/replication/ChangeStreamReplicator.js +26 -0
- package/dist/replication/ChangeStreamReplicator.js.map +1 -0
- package/dist/replication/ConnectionManagerFactory.d.ts +9 -0
- package/dist/replication/ConnectionManagerFactory.js +21 -0
- package/dist/replication/ConnectionManagerFactory.js.map +1 -0
- package/dist/replication/MongoErrorRateLimiter.d.ts +11 -0
- package/dist/replication/MongoErrorRateLimiter.js +44 -0
- package/dist/replication/MongoErrorRateLimiter.js.map +1 -0
- package/dist/replication/MongoManager.d.ts +14 -0
- package/dist/replication/MongoManager.js +36 -0
- package/dist/replication/MongoManager.js.map +1 -0
- package/dist/replication/MongoRelation.d.ts +9 -0
- package/dist/replication/MongoRelation.js +174 -0
- package/dist/replication/MongoRelation.js.map +1 -0
- package/dist/replication/replication-index.d.ts +4 -0
- package/dist/replication/replication-index.js +5 -0
- package/dist/replication/replication-index.js.map +1 -0
- package/dist/types/types.d.ts +51 -0
- package/dist/types/types.js +37 -0
- package/dist/types/types.js.map +1 -0
- package/package.json +47 -0
- package/src/api/MongoRouteAPIAdapter.ts +86 -0
- package/src/index.ts +5 -0
- package/src/module/MongoModule.ts +52 -0
- package/src/replication/ChangeStream.ts +503 -0
- package/src/replication/ChangeStreamReplicationJob.ts +104 -0
- package/src/replication/ChangeStreamReplicator.ts +36 -0
- package/src/replication/ConnectionManagerFactory.ts +27 -0
- package/src/replication/MongoErrorRateLimiter.ts +45 -0
- package/src/replication/MongoManager.ts +47 -0
- package/src/replication/MongoRelation.ts +156 -0
- package/src/replication/replication-index.ts +4 -0
- package/src/types/types.ts +65 -0
- package/test/src/change_stream.test.ts +306 -0
- package/test/src/change_stream_utils.ts +148 -0
- package/test/src/env.ts +7 -0
- package/test/src/mongo_test.test.ts +219 -0
- package/test/src/setup.ts +7 -0
- package/test/src/util.ts +52 -0
- package/test/tsconfig.json +28 -0
- package/tsconfig.json +28 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { container, logger } from '@powersync/lib-services-framework';
|
|
2
|
+
import { Metrics } from '@powersync/service-core';
|
|
3
|
+
import { constructAfterRecord, createCheckpoint, getMongoLsn, getMongoRelation, mongoLsnToTimestamp } from './MongoRelation.js';
|
|
4
|
+
export const ZERO_LSN = '0000000000000000';
|
|
5
|
+
export class MissingReplicationSlotError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class ChangeStream {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.connection_id = 1;
|
|
13
|
+
this.relation_cache = new Map();
|
|
14
|
+
this.storage = options.storage;
|
|
15
|
+
this.group_id = options.storage.group_id;
|
|
16
|
+
this.connections = options.connections;
|
|
17
|
+
this.client = this.connections.client;
|
|
18
|
+
this.defaultDb = this.connections.db;
|
|
19
|
+
this.sync_rules = options.storage.getParsedSyncRules({
|
|
20
|
+
defaultSchema: this.defaultDb.databaseName
|
|
21
|
+
});
|
|
22
|
+
this.abort_signal = options.abort_signal;
|
|
23
|
+
this.abort_signal.addEventListener('abort', () => {
|
|
24
|
+
// TODO: Fast abort?
|
|
25
|
+
}, { once: true });
|
|
26
|
+
}
|
|
27
|
+
get stopped() {
|
|
28
|
+
return this.abort_signal.aborted;
|
|
29
|
+
}
|
|
30
|
+
async getQualifiedTableNames(batch, tablePattern) {
|
|
31
|
+
const schema = tablePattern.schema;
|
|
32
|
+
if (tablePattern.connectionTag != this.connections.connectionTag) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
let nameFilter;
|
|
36
|
+
if (tablePattern.isWildcard) {
|
|
37
|
+
nameFilter = new RegExp('^' + escapeRegExp(tablePattern.tablePrefix));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
nameFilter = tablePattern.name;
|
|
41
|
+
}
|
|
42
|
+
let result = [];
|
|
43
|
+
// Check if the collection exists
|
|
44
|
+
const collections = await this.client
|
|
45
|
+
.db(schema)
|
|
46
|
+
.listCollections({
|
|
47
|
+
name: nameFilter
|
|
48
|
+
}, { nameOnly: true })
|
|
49
|
+
.toArray();
|
|
50
|
+
for (let collection of collections) {
|
|
51
|
+
const table = await this.handleRelation(batch, {
|
|
52
|
+
name: collection.name,
|
|
53
|
+
schema,
|
|
54
|
+
objectId: collection.name,
|
|
55
|
+
replicationColumns: [{ name: '_id' }]
|
|
56
|
+
},
|
|
57
|
+
// This is done as part of the initial setup - snapshot is handled elsewhere
|
|
58
|
+
{ snapshot: false });
|
|
59
|
+
result.push(table);
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
async initSlot() {
|
|
64
|
+
const status = await this.storage.getStatus();
|
|
65
|
+
if (status.snapshot_done && status.checkpoint_lsn) {
|
|
66
|
+
logger.info(`Initial replication already done`);
|
|
67
|
+
return { needsInitialSync: false };
|
|
68
|
+
}
|
|
69
|
+
return { needsInitialSync: true };
|
|
70
|
+
}
|
|
71
|
+
async estimatedCount(table) {
|
|
72
|
+
const db = this.client.db(table.schema);
|
|
73
|
+
const count = db.collection(table.table).estimatedDocumentCount();
|
|
74
|
+
return `~${count}`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Start initial replication.
|
|
78
|
+
*
|
|
79
|
+
* If (partial) replication was done before on this slot, this clears the state
|
|
80
|
+
* and starts again from scratch.
|
|
81
|
+
*/
|
|
82
|
+
async startInitialReplication() {
|
|
83
|
+
await this.storage.clear();
|
|
84
|
+
await this.initialReplication();
|
|
85
|
+
}
|
|
86
|
+
async initialReplication() {
|
|
87
|
+
const sourceTables = this.sync_rules.getSourceTables();
|
|
88
|
+
await this.client.connect();
|
|
89
|
+
const hello = await this.defaultDb.command({ hello: 1 });
|
|
90
|
+
const startTime = hello.lastWrite?.majorityOpTime?.ts;
|
|
91
|
+
if (hello.msg == 'isdbgrid') {
|
|
92
|
+
throw new Error('Sharded MongoDB Clusters are not supported yet (including MongoDB Serverless instances).');
|
|
93
|
+
}
|
|
94
|
+
else if (hello.setName == null) {
|
|
95
|
+
throw new Error('Standalone MongoDB instances are not supported - use a replicaset.');
|
|
96
|
+
}
|
|
97
|
+
else if (startTime == null) {
|
|
98
|
+
// Not known where this would happen apart from the above cases
|
|
99
|
+
throw new Error('MongoDB lastWrite timestamp not found.');
|
|
100
|
+
}
|
|
101
|
+
const session = await this.client.startSession({
|
|
102
|
+
snapshot: true
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
await this.storage.startBatch({ zeroLSN: ZERO_LSN, defaultSchema: this.defaultDb.databaseName }, async (batch) => {
|
|
106
|
+
for (let tablePattern of sourceTables) {
|
|
107
|
+
const tables = await this.getQualifiedTableNames(batch, tablePattern);
|
|
108
|
+
for (let table of tables) {
|
|
109
|
+
await this.snapshotTable(batch, table, session);
|
|
110
|
+
await batch.markSnapshotDone([table], ZERO_LSN);
|
|
111
|
+
await touch();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const snapshotTime = session.clusterTime?.clusterTime ?? startTime;
|
|
115
|
+
if (snapshotTime != null) {
|
|
116
|
+
const lsn = getMongoLsn(snapshotTime);
|
|
117
|
+
logger.info(`Snapshot commit at ${snapshotTime.inspect()} / ${lsn}`);
|
|
118
|
+
// keepalive() does an auto-commit if there is data
|
|
119
|
+
await batch.flush();
|
|
120
|
+
await batch.keepalive(lsn);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
throw new Error(`No snapshot clusterTime available.`);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
session.endSession();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
getSourceNamespaceFilters() {
|
|
132
|
+
const sourceTables = this.sync_rules.getSourceTables();
|
|
133
|
+
let $inFilters = [{ db: this.defaultDb.databaseName, coll: '_powersync_checkpoints' }];
|
|
134
|
+
let $refilters = [];
|
|
135
|
+
for (let tablePattern of sourceTables) {
|
|
136
|
+
if (tablePattern.connectionTag != this.connections.connectionTag) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (tablePattern.isWildcard) {
|
|
140
|
+
$refilters.push({ db: tablePattern.schema, coll: new RegExp('^' + escapeRegExp(tablePattern.tablePrefix)) });
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
$inFilters.push({
|
|
144
|
+
db: tablePattern.schema,
|
|
145
|
+
coll: tablePattern.name
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if ($refilters.length > 0) {
|
|
150
|
+
return { $or: [{ ns: { $in: $inFilters } }, ...$refilters] };
|
|
151
|
+
}
|
|
152
|
+
return { ns: { $in: $inFilters } };
|
|
153
|
+
}
|
|
154
|
+
static *getQueryData(results) {
|
|
155
|
+
for (let row of results) {
|
|
156
|
+
yield constructAfterRecord(row);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async snapshotTable(batch, table, session) {
|
|
160
|
+
logger.info(`Replicating ${table.qualifiedName}`);
|
|
161
|
+
const estimatedCount = await this.estimatedCount(table);
|
|
162
|
+
let at = 0;
|
|
163
|
+
const db = this.client.db(table.schema);
|
|
164
|
+
const collection = db.collection(table.table);
|
|
165
|
+
const query = collection.find({}, { session });
|
|
166
|
+
const cursor = query.stream();
|
|
167
|
+
for await (let document of cursor) {
|
|
168
|
+
if (this.abort_signal.aborted) {
|
|
169
|
+
throw new Error(`Aborted initial replication`);
|
|
170
|
+
}
|
|
171
|
+
const record = constructAfterRecord(document);
|
|
172
|
+
// This auto-flushes when the batch reaches its size limit
|
|
173
|
+
await batch.save({
|
|
174
|
+
tag: 'insert',
|
|
175
|
+
sourceTable: table,
|
|
176
|
+
before: undefined,
|
|
177
|
+
beforeReplicaId: undefined,
|
|
178
|
+
after: record,
|
|
179
|
+
afterReplicaId: document._id
|
|
180
|
+
});
|
|
181
|
+
at += 1;
|
|
182
|
+
Metrics.getInstance().rows_replicated_total.add(1);
|
|
183
|
+
await touch();
|
|
184
|
+
}
|
|
185
|
+
await batch.flush();
|
|
186
|
+
}
|
|
187
|
+
async getRelation(batch, descriptor) {
|
|
188
|
+
const existing = this.relation_cache.get(descriptor.objectId);
|
|
189
|
+
if (existing != null) {
|
|
190
|
+
return existing;
|
|
191
|
+
}
|
|
192
|
+
return this.handleRelation(batch, descriptor, { snapshot: false });
|
|
193
|
+
}
|
|
194
|
+
async handleRelation(batch, descriptor, options) {
|
|
195
|
+
const snapshot = options.snapshot;
|
|
196
|
+
if (!descriptor.objectId && typeof descriptor.objectId != 'string') {
|
|
197
|
+
throw new Error('objectId expected');
|
|
198
|
+
}
|
|
199
|
+
const result = await this.storage.resolveTable({
|
|
200
|
+
group_id: this.group_id,
|
|
201
|
+
connection_id: this.connection_id,
|
|
202
|
+
connection_tag: this.connections.connectionTag,
|
|
203
|
+
entity_descriptor: descriptor,
|
|
204
|
+
sync_rules: this.sync_rules
|
|
205
|
+
});
|
|
206
|
+
this.relation_cache.set(descriptor.objectId, result.table);
|
|
207
|
+
// Drop conflicting tables. This includes for example renamed tables.
|
|
208
|
+
await batch.drop(result.dropTables);
|
|
209
|
+
// Snapshot if:
|
|
210
|
+
// 1. Snapshot is requested (false for initial snapshot, since that process handles it elsewhere)
|
|
211
|
+
// 2. Snapshot is not already done, AND:
|
|
212
|
+
// 3. The table is used in sync rules.
|
|
213
|
+
const shouldSnapshot = snapshot && !result.table.snapshotComplete && result.table.syncAny;
|
|
214
|
+
if (shouldSnapshot) {
|
|
215
|
+
// Truncate this table, in case a previous snapshot was interrupted.
|
|
216
|
+
await batch.truncate([result.table]);
|
|
217
|
+
await this.snapshotTable(batch, result.table);
|
|
218
|
+
const no_checkpoint_before_lsn = await createCheckpoint(this.client, this.defaultDb);
|
|
219
|
+
const [table] = await batch.markSnapshotDone([result.table], no_checkpoint_before_lsn);
|
|
220
|
+
return table;
|
|
221
|
+
}
|
|
222
|
+
return result.table;
|
|
223
|
+
}
|
|
224
|
+
async writeChange(batch, table, change) {
|
|
225
|
+
if (!table.syncAny) {
|
|
226
|
+
logger.debug(`Collection ${table.qualifiedName} not used in sync rules - skipping`);
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
Metrics.getInstance().rows_replicated_total.add(1);
|
|
230
|
+
if (change.operationType == 'insert') {
|
|
231
|
+
const baseRecord = constructAfterRecord(change.fullDocument);
|
|
232
|
+
return await batch.save({
|
|
233
|
+
tag: 'insert',
|
|
234
|
+
sourceTable: table,
|
|
235
|
+
before: undefined,
|
|
236
|
+
beforeReplicaId: undefined,
|
|
237
|
+
after: baseRecord,
|
|
238
|
+
afterReplicaId: change.documentKey._id
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
else if (change.operationType == 'update' || change.operationType == 'replace') {
|
|
242
|
+
if (change.fullDocument == null) {
|
|
243
|
+
// Treat as delete
|
|
244
|
+
return await batch.save({
|
|
245
|
+
tag: 'delete',
|
|
246
|
+
sourceTable: table,
|
|
247
|
+
before: undefined,
|
|
248
|
+
beforeReplicaId: change.documentKey._id
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
const after = constructAfterRecord(change.fullDocument);
|
|
252
|
+
return await batch.save({
|
|
253
|
+
tag: 'update',
|
|
254
|
+
sourceTable: table,
|
|
255
|
+
before: undefined,
|
|
256
|
+
beforeReplicaId: undefined,
|
|
257
|
+
after: after,
|
|
258
|
+
afterReplicaId: change.documentKey._id
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
else if (change.operationType == 'delete') {
|
|
262
|
+
return await batch.save({
|
|
263
|
+
tag: 'delete',
|
|
264
|
+
sourceTable: table,
|
|
265
|
+
before: undefined,
|
|
266
|
+
beforeReplicaId: change.documentKey._id
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
throw new Error(`Unsupported operation: ${change.operationType}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async replicate() {
|
|
274
|
+
try {
|
|
275
|
+
// If anything errors here, the entire replication process is halted, and
|
|
276
|
+
// all connections automatically closed, including this one.
|
|
277
|
+
await this.initReplication();
|
|
278
|
+
await this.streamChanges();
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
await this.storage.reportError(e);
|
|
282
|
+
throw e;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async initReplication() {
|
|
286
|
+
const result = await this.initSlot();
|
|
287
|
+
if (result.needsInitialSync) {
|
|
288
|
+
await this.startInitialReplication();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async streamChanges() {
|
|
292
|
+
// Auto-activate as soon as initial replication is done
|
|
293
|
+
await this.storage.autoActivate();
|
|
294
|
+
await this.storage.startBatch({ zeroLSN: ZERO_LSN, defaultSchema: this.defaultDb.databaseName }, async (batch) => {
|
|
295
|
+
const lastLsn = batch.lastCheckpointLsn;
|
|
296
|
+
const startAfter = mongoLsnToTimestamp(lastLsn) ?? undefined;
|
|
297
|
+
logger.info(`Resume streaming at ${startAfter?.inspect()} / ${lastLsn}`);
|
|
298
|
+
// TODO: Use changeStreamSplitLargeEvent
|
|
299
|
+
const pipeline = [
|
|
300
|
+
{
|
|
301
|
+
$match: this.getSourceNamespaceFilters()
|
|
302
|
+
}
|
|
303
|
+
];
|
|
304
|
+
const stream = this.client.watch(pipeline, {
|
|
305
|
+
startAtOperationTime: startAfter,
|
|
306
|
+
showExpandedEvents: true,
|
|
307
|
+
useBigInt64: true,
|
|
308
|
+
maxAwaitTimeMS: 200,
|
|
309
|
+
fullDocument: 'updateLookup'
|
|
310
|
+
});
|
|
311
|
+
if (this.abort_signal.aborted) {
|
|
312
|
+
stream.close();
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
this.abort_signal.addEventListener('abort', () => {
|
|
316
|
+
stream.close();
|
|
317
|
+
});
|
|
318
|
+
let waitForCheckpointLsn = null;
|
|
319
|
+
while (true) {
|
|
320
|
+
if (this.abort_signal.aborted) {
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
const changeDocument = await stream.tryNext();
|
|
324
|
+
if (changeDocument == null || this.abort_signal.aborted) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
await touch();
|
|
328
|
+
if (startAfter != null && changeDocument.clusterTime?.lte(startAfter)) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
// console.log('event', changeDocument);
|
|
332
|
+
if ((changeDocument.operationType == 'insert' ||
|
|
333
|
+
changeDocument.operationType == 'update' ||
|
|
334
|
+
changeDocument.operationType == 'replace') &&
|
|
335
|
+
changeDocument.ns.coll == '_powersync_checkpoints') {
|
|
336
|
+
const lsn = getMongoLsn(changeDocument.clusterTime);
|
|
337
|
+
if (waitForCheckpointLsn != null && lsn >= waitForCheckpointLsn) {
|
|
338
|
+
waitForCheckpointLsn = null;
|
|
339
|
+
}
|
|
340
|
+
await batch.flush();
|
|
341
|
+
await batch.keepalive(lsn);
|
|
342
|
+
}
|
|
343
|
+
else if (changeDocument.operationType == 'insert' ||
|
|
344
|
+
changeDocument.operationType == 'update' ||
|
|
345
|
+
changeDocument.operationType == 'replace' ||
|
|
346
|
+
changeDocument.operationType == 'delete') {
|
|
347
|
+
if (waitForCheckpointLsn == null) {
|
|
348
|
+
waitForCheckpointLsn = await createCheckpoint(this.client, this.defaultDb);
|
|
349
|
+
}
|
|
350
|
+
const rel = getMongoRelation(changeDocument.ns);
|
|
351
|
+
const table = await this.getRelation(batch, rel);
|
|
352
|
+
if (table.syncAny) {
|
|
353
|
+
await this.writeChange(batch, table, changeDocument);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
else if (changeDocument.operationType == 'drop') {
|
|
357
|
+
const rel = getMongoRelation(changeDocument.ns);
|
|
358
|
+
const table = await this.getRelation(batch, rel);
|
|
359
|
+
if (table.syncAny) {
|
|
360
|
+
await batch.drop([table]);
|
|
361
|
+
this.relation_cache.delete(table.objectId);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
else if (changeDocument.operationType == 'rename') {
|
|
365
|
+
const relFrom = getMongoRelation(changeDocument.ns);
|
|
366
|
+
const relTo = getMongoRelation(changeDocument.to);
|
|
367
|
+
const tableFrom = await this.getRelation(batch, relFrom);
|
|
368
|
+
if (tableFrom.syncAny) {
|
|
369
|
+
await batch.drop([tableFrom]);
|
|
370
|
+
this.relation_cache.delete(tableFrom.objectId);
|
|
371
|
+
}
|
|
372
|
+
// Here we do need to snapshot the new table
|
|
373
|
+
await this.handleRelation(batch, relTo, { snapshot: true });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
async function touch() {
|
|
380
|
+
// FIXME: The hosted Kubernetes probe does not actually check the timestamp on this.
|
|
381
|
+
// FIXME: We need a timeout of around 5+ minutes in Kubernetes if we do start checking the timestamp,
|
|
382
|
+
// or reduce PING_INTERVAL here.
|
|
383
|
+
return container.probes.touch();
|
|
384
|
+
}
|
|
385
|
+
function escapeRegExp(string) {
|
|
386
|
+
// https://stackoverflow.com/a/3561711/214837
|
|
387
|
+
return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=ChangeStream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChangeStream.js","sourceRoot":"","sources":["../../src/replication/ChangeStream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { replication } from '@powersync/service-core';
|
|
2
|
+
import { ConnectionManagerFactory } from './ConnectionManagerFactory.js';
|
|
3
|
+
export interface ChangeStreamReplicationJobOptions extends replication.AbstractReplicationJobOptions {
|
|
4
|
+
connectionFactory: ConnectionManagerFactory;
|
|
5
|
+
}
|
|
6
|
+
export declare class ChangeStreamReplicationJob extends replication.AbstractReplicationJob {
|
|
7
|
+
private connectionFactory;
|
|
8
|
+
private readonly connectionManager;
|
|
9
|
+
constructor(options: ChangeStreamReplicationJobOptions);
|
|
10
|
+
cleanUp(): Promise<void>;
|
|
11
|
+
keepAlive(): Promise<void>;
|
|
12
|
+
private get slotName();
|
|
13
|
+
replicate(): Promise<void>;
|
|
14
|
+
replicateLoop(): Promise<void>;
|
|
15
|
+
replicateOnce(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { container } from '@powersync/lib-services-framework';
|
|
2
|
+
import { MissingReplicationSlotError, ChangeStream } from './ChangeStream.js';
|
|
3
|
+
import { replication } from '@powersync/service-core';
|
|
4
|
+
import * as mongo from 'mongodb';
|
|
5
|
+
export class ChangeStreamReplicationJob extends replication.AbstractReplicationJob {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
super(options);
|
|
8
|
+
this.connectionFactory = options.connectionFactory;
|
|
9
|
+
this.connectionManager = this.connectionFactory.create();
|
|
10
|
+
}
|
|
11
|
+
async cleanUp() {
|
|
12
|
+
// TODO: Implement?
|
|
13
|
+
}
|
|
14
|
+
async keepAlive() {
|
|
15
|
+
// TODO: Implement?
|
|
16
|
+
}
|
|
17
|
+
get slotName() {
|
|
18
|
+
return this.options.storage.slot_name;
|
|
19
|
+
}
|
|
20
|
+
async replicate() {
|
|
21
|
+
try {
|
|
22
|
+
await this.replicateLoop();
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
// Fatal exception
|
|
26
|
+
container.reporter.captureException(e, {
|
|
27
|
+
metadata: {}
|
|
28
|
+
});
|
|
29
|
+
this.logger.error(`Replication failed`, e);
|
|
30
|
+
if (e instanceof MissingReplicationSlotError) {
|
|
31
|
+
// This stops replication on this slot, and creates a new slot
|
|
32
|
+
await this.options.storage.factory.slotRemoved(this.slotName);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
this.abortController.abort();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async replicateLoop() {
|
|
40
|
+
while (!this.isStopped) {
|
|
41
|
+
await this.replicateOnce();
|
|
42
|
+
if (!this.isStopped) {
|
|
43
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async replicateOnce() {
|
|
48
|
+
// New connections on every iteration (every error with retry),
|
|
49
|
+
// otherwise we risk repeating errors related to the connection,
|
|
50
|
+
// such as caused by cached PG schemas.
|
|
51
|
+
const connectionManager = this.connectionFactory.create();
|
|
52
|
+
try {
|
|
53
|
+
await this.rateLimiter?.waitUntilAllowed({ signal: this.abortController.signal });
|
|
54
|
+
if (this.isStopped) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const stream = new ChangeStream({
|
|
58
|
+
abort_signal: this.abortController.signal,
|
|
59
|
+
storage: this.options.storage,
|
|
60
|
+
connections: connectionManager
|
|
61
|
+
});
|
|
62
|
+
await stream.replicate();
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
if (this.abortController.signal.aborted) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.logger.error(`Replication error`, e);
|
|
69
|
+
if (e.cause != null) {
|
|
70
|
+
// Without this additional log, the cause may not be visible in the logs.
|
|
71
|
+
this.logger.error(`cause`, e.cause);
|
|
72
|
+
}
|
|
73
|
+
if (e instanceof mongo.MongoError && e.hasErrorLabel('NonResumableChangeStreamError')) {
|
|
74
|
+
throw new MissingReplicationSlotError(e.message);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// Report the error if relevant, before retrying
|
|
78
|
+
container.reporter.captureException(e, {
|
|
79
|
+
metadata: {}
|
|
80
|
+
});
|
|
81
|
+
// This sets the retry delay
|
|
82
|
+
this.rateLimiter?.reportError(e);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
await connectionManager.end();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=ChangeStreamReplicationJob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChangeStreamReplicationJob.js","sourceRoot":"","sources":["../../src/replication/ChangeStreamReplicationJob.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { storage, replication } from '@powersync/service-core';
|
|
2
|
+
import { ChangeStreamReplicationJob } from './ChangeStreamReplicationJob.js';
|
|
3
|
+
import { ConnectionManagerFactory } from './ConnectionManagerFactory.js';
|
|
4
|
+
export interface WalStreamReplicatorOptions extends replication.AbstractReplicatorOptions {
|
|
5
|
+
connectionFactory: ConnectionManagerFactory;
|
|
6
|
+
}
|
|
7
|
+
export declare class ChangeStreamReplicator extends replication.AbstractReplicator<ChangeStreamReplicationJob> {
|
|
8
|
+
private readonly connectionFactory;
|
|
9
|
+
constructor(options: WalStreamReplicatorOptions);
|
|
10
|
+
createJob(options: replication.CreateJobOptions): ChangeStreamReplicationJob;
|
|
11
|
+
cleanUp(syncRulesStorage: storage.SyncRulesBucketStorage): Promise<void>;
|
|
12
|
+
stop(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { replication } from '@powersync/service-core';
|
|
2
|
+
import { ChangeStreamReplicationJob } from './ChangeStreamReplicationJob.js';
|
|
3
|
+
import { MongoErrorRateLimiter } from './MongoErrorRateLimiter.js';
|
|
4
|
+
export class ChangeStreamReplicator extends replication.AbstractReplicator {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super(options);
|
|
7
|
+
this.connectionFactory = options.connectionFactory;
|
|
8
|
+
}
|
|
9
|
+
createJob(options) {
|
|
10
|
+
return new ChangeStreamReplicationJob({
|
|
11
|
+
id: this.createJobId(options.storage.group_id),
|
|
12
|
+
storage: options.storage,
|
|
13
|
+
connectionFactory: this.connectionFactory,
|
|
14
|
+
lock: options.lock,
|
|
15
|
+
rateLimiter: new MongoErrorRateLimiter()
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async cleanUp(syncRulesStorage) {
|
|
19
|
+
// TODO: Implement anything?
|
|
20
|
+
}
|
|
21
|
+
async stop() {
|
|
22
|
+
await super.stop();
|
|
23
|
+
await this.connectionFactory.shutdown();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ChangeStreamReplicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChangeStreamReplicator.js","sourceRoot":"","sources":["../../src/replication/ChangeStreamReplicator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAE7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAMnE,MAAM,OAAO,sBAAuB,SAAQ,WAAW,CAAC,kBAA8C;IAGpG,YAAY,OAAmC;QAC7C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IACrD,CAAC;IAED,SAAS,CAAC,OAAqC;QAC7C,OAAO,IAAI,0BAA0B,CAAC;YACpC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC9C,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,WAAW,EAAE,IAAI,qBAAqB,EAAE;SACzC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,gBAAgD;QAC5D,4BAA4B;IAC9B,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;IAC1C,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NormalizedMongoConnectionConfig } from '../types/types.js';
|
|
2
|
+
import { MongoManager } from './MongoManager.js';
|
|
3
|
+
export declare class ConnectionManagerFactory {
|
|
4
|
+
private readonly connectionManagers;
|
|
5
|
+
private readonly dbConnectionConfig;
|
|
6
|
+
constructor(dbConnectionConfig: NormalizedMongoConnectionConfig);
|
|
7
|
+
create(): MongoManager;
|
|
8
|
+
shutdown(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
2
|
+
import { MongoManager } from './MongoManager.js';
|
|
3
|
+
export class ConnectionManagerFactory {
|
|
4
|
+
constructor(dbConnectionConfig) {
|
|
5
|
+
this.dbConnectionConfig = dbConnectionConfig;
|
|
6
|
+
this.connectionManagers = [];
|
|
7
|
+
}
|
|
8
|
+
create() {
|
|
9
|
+
const manager = new MongoManager(this.dbConnectionConfig);
|
|
10
|
+
this.connectionManagers.push(manager);
|
|
11
|
+
return manager;
|
|
12
|
+
}
|
|
13
|
+
async shutdown() {
|
|
14
|
+
logger.info('Shutting down MongoDB connection Managers...');
|
|
15
|
+
for (const manager of this.connectionManagers) {
|
|
16
|
+
await manager.end();
|
|
17
|
+
}
|
|
18
|
+
logger.info('MongoDB connection Managers shutdown completed.');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ConnectionManagerFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConnectionManagerFactory.js","sourceRoot":"","sources":["../../src/replication/ConnectionManagerFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,OAAO,wBAAwB;IAInC,YAAY,kBAAmD;QAC7D,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC1D,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC5D,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC7C,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC;SACrB;QACD,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACjE,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { ErrorRateLimiter } from '@powersync/service-core';
|
|
3
|
+
export declare class MongoErrorRateLimiter implements ErrorRateLimiter {
|
|
4
|
+
nextAllowed: number;
|
|
5
|
+
waitUntilAllowed(options?: {
|
|
6
|
+
signal?: AbortSignal | undefined;
|
|
7
|
+
} | undefined): Promise<void>;
|
|
8
|
+
mayPing(): boolean;
|
|
9
|
+
reportError(e: any): void;
|
|
10
|
+
private setDelay;
|
|
11
|
+
}
|