@powersync/service-module-mongodb-storage 0.6.0 → 0.6.2
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 +24 -0
- package/dist/storage/MongoBucketStorage.d.ts +3 -3
- package/dist/storage/MongoBucketStorage.js +26 -13
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.js +1 -1
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoCompactor.d.ts +0 -6
- package/dist/storage/implementation/MongoCompactor.js +1 -2
- package/dist/storage/implementation/MongoCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.js +20 -14
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js +1 -2
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/implementation/OperationBatch.d.ts +1 -0
- package/dist/storage/implementation/OperationBatch.js +3 -0
- package/dist/storage/implementation/OperationBatch.js.map +1 -1
- package/dist/storage/implementation/PersistedBatch.js +7 -6
- package/dist/storage/implementation/PersistedBatch.js.map +1 -1
- package/dist/storage/implementation/util.d.ts +0 -14
- package/dist/storage/implementation/util.js +0 -38
- package/dist/storage/implementation/util.js.map +1 -1
- package/package.json +6 -6
- package/src/storage/MongoBucketStorage.ts +31 -14
- package/src/storage/implementation/MongoBucketBatch.ts +1 -1
- package/src/storage/implementation/MongoCompactor.ts +2 -10
- package/src/storage/implementation/MongoSyncBucketStorage.ts +46 -35
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +1 -3
- package/src/storage/implementation/OperationBatch.ts +4 -0
- package/src/storage/implementation/PersistedBatch.ts +7 -6
- package/src/storage/implementation/util.ts +0 -45
- package/test/src/__snapshots__/storage_sync.test.ts.snap +56 -0
- package/test/src/storage_compacting.test.ts +1 -7
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -31,6 +31,9 @@ export class OperationBatch {
|
|
|
31
31
|
shouldFlush() {
|
|
32
32
|
return this.batch.length >= MAX_BATCH_COUNT || this.currentSize > MAX_RECORD_BATCH_SIZE;
|
|
33
33
|
}
|
|
34
|
+
hasData() {
|
|
35
|
+
return this.length > 0;
|
|
36
|
+
}
|
|
34
37
|
/**
|
|
35
38
|
*
|
|
36
39
|
* @param sizes Map of source key to estimated size of the current_data document, or undefined if current_data is not persisted.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationBatch.js","sourceRoot":"","sources":["../../../src/storage/implementation/OperationBatch.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OperationBatch.js","sourceRoot":"","sources":["../../../src/storage/implementation/OperationBatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { JSONBig } from '@powersync/service-jsonbig';
|
|
|
2
2
|
import { logger } from '@powersync/lib-services-framework';
|
|
3
3
|
import { storage, utils } from '@powersync/service-core';
|
|
4
4
|
import { currentBucketKey } from './MongoBucketBatch.js';
|
|
5
|
-
import { replicaIdToSubkey
|
|
5
|
+
import { replicaIdToSubkey } from './util.js';
|
|
6
6
|
/**
|
|
7
7
|
* Maximum size of operations we write in a single transaction.
|
|
8
8
|
*
|
|
@@ -191,29 +191,30 @@ export class PersistedBatch {
|
|
|
191
191
|
this.bucketParameters.length >= MAX_TRANSACTION_DOC_COUNT);
|
|
192
192
|
}
|
|
193
193
|
async flush(db, session) {
|
|
194
|
+
const startAt = performance.now();
|
|
194
195
|
if (this.bucketData.length > 0) {
|
|
195
|
-
|
|
196
|
-
await safeBulkWrite(db.bucket_data, this.bucketData, {
|
|
196
|
+
await db.bucket_data.bulkWrite(this.bucketData, {
|
|
197
197
|
session,
|
|
198
198
|
// inserts only - order doesn't matter
|
|
199
199
|
ordered: false
|
|
200
200
|
});
|
|
201
201
|
}
|
|
202
202
|
if (this.bucketParameters.length > 0) {
|
|
203
|
-
await
|
|
203
|
+
await db.bucket_parameters.bulkWrite(this.bucketParameters, {
|
|
204
204
|
session,
|
|
205
205
|
// inserts only - order doesn't matter
|
|
206
206
|
ordered: false
|
|
207
207
|
});
|
|
208
208
|
}
|
|
209
209
|
if (this.currentData.length > 0) {
|
|
210
|
-
await
|
|
210
|
+
await db.current_data.bulkWrite(this.currentData, {
|
|
211
211
|
session,
|
|
212
212
|
// may update and delete data within the same batch - order matters
|
|
213
213
|
ordered: true
|
|
214
214
|
});
|
|
215
215
|
}
|
|
216
|
-
|
|
216
|
+
const duration = performance.now() - startAt;
|
|
217
|
+
logger.info(`powersync_${this.group_id} Flushed ${this.bucketData.length} + ${this.bucketParameters.length} + ${this.currentData.length} updates, ${Math.round(this.currentSize / 1024)}kb in ${duration.toFixed(0)}ms. Last op_id: ${this.debugLastOpId}`);
|
|
217
218
|
this.bucketData = [];
|
|
218
219
|
this.bucketParameters = [];
|
|
219
220
|
this.currentData = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersistedBatch.js","sourceRoot":"","sources":["../../../src/storage/implementation/PersistedBatch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAIrD,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAUzD,OAAO,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"PersistedBatch.js","sourceRoot":"","sources":["../../../src/storage/implementation/PersistedBatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,17 +30,3 @@ export declare const createMongoClient: (url: string, options?: mongo.MongoClien
|
|
|
30
30
|
* Helper for unit tests
|
|
31
31
|
*/
|
|
32
32
|
export declare const connectMongoForTests: (url: string, isCI: boolean) => PowerSyncMongo;
|
|
33
|
-
/**
|
|
34
|
-
* MongoDB bulkWrite internally splits the operations into batches
|
|
35
|
-
* so that no batch exceeds 16MB. However, there are cases where
|
|
36
|
-
* the batch size is very close to 16MB, where additional metadata
|
|
37
|
-
* on the server pushes it over the limit, resulting in this error
|
|
38
|
-
* from the server:
|
|
39
|
-
*
|
|
40
|
-
* > MongoBulkWriteError: BSONObj size: 16814023 (0x1008FC7) is invalid. Size must be between 0 and 16793600(16MB) First element: insert: "bucket_data"
|
|
41
|
-
*
|
|
42
|
-
* We work around the issue by doing our own batching, limiting the
|
|
43
|
-
* batch size to 15MB. This does add additional overhead with
|
|
44
|
-
* BSON.calculateObjectSize.
|
|
45
|
-
*/
|
|
46
|
-
export declare function safeBulkWrite<T extends mongo.Document>(collection: mongo.Collection<T>, operations: mongo.AnyBulkWriteOperation<T>[], options: mongo.BulkWriteOptions): Promise<void>;
|
|
@@ -114,42 +114,4 @@ export const connectMongoForTests = (url, isCI) => {
|
|
|
114
114
|
});
|
|
115
115
|
return new PowerSyncMongo(client);
|
|
116
116
|
};
|
|
117
|
-
/**
|
|
118
|
-
* MongoDB bulkWrite internally splits the operations into batches
|
|
119
|
-
* so that no batch exceeds 16MB. However, there are cases where
|
|
120
|
-
* the batch size is very close to 16MB, where additional metadata
|
|
121
|
-
* on the server pushes it over the limit, resulting in this error
|
|
122
|
-
* from the server:
|
|
123
|
-
*
|
|
124
|
-
* > MongoBulkWriteError: BSONObj size: 16814023 (0x1008FC7) is invalid. Size must be between 0 and 16793600(16MB) First element: insert: "bucket_data"
|
|
125
|
-
*
|
|
126
|
-
* We work around the issue by doing our own batching, limiting the
|
|
127
|
-
* batch size to 15MB. This does add additional overhead with
|
|
128
|
-
* BSON.calculateObjectSize.
|
|
129
|
-
*/
|
|
130
|
-
export async function safeBulkWrite(collection, operations, options) {
|
|
131
|
-
// Must be below 16MB.
|
|
132
|
-
// We could probably go a little closer, but 15MB is a safe threshold.
|
|
133
|
-
const BULK_WRITE_LIMIT = 15 * 1024 * 1024;
|
|
134
|
-
let batch = [];
|
|
135
|
-
let currentSize = 0;
|
|
136
|
-
// Estimated overhead per operation, should be smaller in reality.
|
|
137
|
-
const keySize = 8;
|
|
138
|
-
for (let op of operations) {
|
|
139
|
-
const bsonSize = mongo.BSON.calculateObjectSize(op, {
|
|
140
|
-
checkKeys: false,
|
|
141
|
-
ignoreUndefined: true
|
|
142
|
-
}) + keySize;
|
|
143
|
-
if (batch.length > 0 && currentSize + bsonSize > BULK_WRITE_LIMIT) {
|
|
144
|
-
await collection.bulkWrite(batch, options);
|
|
145
|
-
currentSize = 0;
|
|
146
|
-
batch = [];
|
|
147
|
-
}
|
|
148
|
-
batch.push(op);
|
|
149
|
-
currentSize += bsonSize;
|
|
150
|
-
}
|
|
151
|
-
if (batch.length > 0) {
|
|
152
|
-
await collection.bulkWrite(batch, options);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
117
|
//# sourceMappingURL=util.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/storage/implementation/util.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/storage/implementation/util.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@powersync/service-module-mongodb-storage",
|
|
3
3
|
"repository": "https://github.com/powersync-ja/powersync-service",
|
|
4
4
|
"types": "dist/index.d.ts",
|
|
5
|
-
"version": "0.6.
|
|
5
|
+
"version": "0.6.2",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"license": "FSL-1.1-Apache-2.0",
|
|
8
8
|
"type": "module",
|
|
@@ -22,21 +22,21 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"bson": "^6.
|
|
25
|
+
"bson": "^6.10.3",
|
|
26
26
|
"ts-codec": "^1.3.0",
|
|
27
27
|
"ix": "^5.0.0",
|
|
28
28
|
"lru-cache": "^10.2.2",
|
|
29
29
|
"uuid": "^9.0.1",
|
|
30
|
-
"@powersync/lib-services-framework": "0.5.
|
|
31
|
-
"@powersync/service-core": "1.7.
|
|
30
|
+
"@powersync/lib-services-framework": "0.5.3",
|
|
31
|
+
"@powersync/service-core": "1.7.2",
|
|
32
32
|
"@powersync/service-jsonbig": "0.17.10",
|
|
33
33
|
"@powersync/service-sync-rules": "0.24.0",
|
|
34
34
|
"@powersync/service-types": "0.8.0",
|
|
35
|
-
"@powersync/lib-service-mongodb": "0.4.
|
|
35
|
+
"@powersync/lib-service-mongodb": "0.4.3"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/uuid": "^9.0.4",
|
|
39
|
-
"@powersync/service-core-tests": "0.
|
|
39
|
+
"@powersync/service-core-tests": "0.6.1"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "tsc -b",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SqlSyncRules } from '@powersync/service-sync-rules';
|
|
2
2
|
|
|
3
|
-
import { storage } from '@powersync/service-core';
|
|
3
|
+
import { GetIntanceOptions, storage } from '@powersync/service-core';
|
|
4
4
|
|
|
5
5
|
import { BaseObserver, ErrorCode, logger, ServiceError } from '@powersync/lib-services-framework';
|
|
6
6
|
import { v4 as uuid } from 'uuid';
|
|
@@ -44,13 +44,15 @@ export class MongoBucketStorage
|
|
|
44
44
|
// No-op
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
getInstance(
|
|
48
|
-
let { id, slot_name } =
|
|
47
|
+
getInstance(syncRules: storage.PersistedSyncRulesContent, options?: GetIntanceOptions): MongoSyncBucketStorage {
|
|
48
|
+
let { id, slot_name } = syncRules;
|
|
49
49
|
if ((typeof id as any) == 'bigint') {
|
|
50
50
|
id = Number(id);
|
|
51
51
|
}
|
|
52
|
-
const storage = new MongoSyncBucketStorage(this, id,
|
|
53
|
-
|
|
52
|
+
const storage = new MongoSyncBucketStorage(this, id, syncRules, slot_name);
|
|
53
|
+
if (!options?.skipLifecycleHooks) {
|
|
54
|
+
this.iterateListeners((cb) => cb.syncStorageCreated?.(storage));
|
|
55
|
+
}
|
|
54
56
|
storage.registerListener({
|
|
55
57
|
batchStarted: (batch) => {
|
|
56
58
|
batch.registerListener({
|
|
@@ -95,13 +97,11 @@ export class MongoBucketStorage
|
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
|
|
98
|
-
async
|
|
100
|
+
async restartReplication(sync_rules_group_id: number) {
|
|
99
101
|
const next = await this.getNextSyncRulesContent();
|
|
100
102
|
const active = await this.getActiveSyncRulesContent();
|
|
101
103
|
|
|
102
|
-
|
|
103
|
-
// The current one will continue erroring until the next one has finished processing.
|
|
104
|
-
if (next != null && next.slot_name == slot_name) {
|
|
104
|
+
if (next != null && next.id == sync_rules_group_id) {
|
|
105
105
|
// We need to redo the "next" sync rules
|
|
106
106
|
await this.updateSyncRules({
|
|
107
107
|
content: next.sync_rules_content,
|
|
@@ -119,14 +119,17 @@ export class MongoBucketStorage
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
);
|
|
122
|
-
} else if (next == null && active?.
|
|
122
|
+
} else if (next == null && active?.id == sync_rules_group_id) {
|
|
123
123
|
// Slot removed for "active" sync rules, while there is no "next" one.
|
|
124
124
|
await this.updateSyncRules({
|
|
125
125
|
content: active.sync_rules_content,
|
|
126
126
|
validate: false
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
//
|
|
129
|
+
// In this case we keep the old one as active for clients, so that that existing clients
|
|
130
|
+
// can still get the latest data while we replicate the new ones.
|
|
131
|
+
// It will however not replicate anymore.
|
|
132
|
+
|
|
130
133
|
await this.db.sync_rules.updateOne(
|
|
131
134
|
{
|
|
132
135
|
_id: active.id,
|
|
@@ -134,7 +137,21 @@ export class MongoBucketStorage
|
|
|
134
137
|
},
|
|
135
138
|
{
|
|
136
139
|
$set: {
|
|
137
|
-
state: storage.SyncRuleState.
|
|
140
|
+
state: storage.SyncRuleState.ERRORED
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
} else if (next != null && active?.id == sync_rules_group_id) {
|
|
145
|
+
// Already have next sync rules, but need to stop replicating the active one.
|
|
146
|
+
|
|
147
|
+
await this.db.sync_rules.updateOne(
|
|
148
|
+
{
|
|
149
|
+
_id: active.id,
|
|
150
|
+
state: storage.SyncRuleState.ACTIVE
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
$set: {
|
|
154
|
+
state: storage.SyncRuleState.ERRORED
|
|
138
155
|
}
|
|
139
156
|
}
|
|
140
157
|
);
|
|
@@ -211,7 +228,7 @@ export class MongoBucketStorage
|
|
|
211
228
|
async getActiveSyncRulesContent(): Promise<MongoPersistedSyncRulesContent | null> {
|
|
212
229
|
const doc = await this.db.sync_rules.findOne(
|
|
213
230
|
{
|
|
214
|
-
state: storage.SyncRuleState.ACTIVE
|
|
231
|
+
state: { $in: [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED] }
|
|
215
232
|
},
|
|
216
233
|
{ sort: { _id: -1 }, limit: 1 }
|
|
217
234
|
);
|
|
@@ -249,7 +266,7 @@ export class MongoBucketStorage
|
|
|
249
266
|
async getReplicatingSyncRules(): Promise<storage.PersistedSyncRulesContent[]> {
|
|
250
267
|
const docs = await this.db.sync_rules
|
|
251
268
|
.find({
|
|
252
|
-
|
|
269
|
+
state: { $in: [storage.SyncRuleState.PROCESSING, storage.SyncRuleState.ACTIVE] }
|
|
253
270
|
})
|
|
254
271
|
.toArray();
|
|
255
272
|
|
|
@@ -5,7 +5,6 @@ import { storage, utils } from '@powersync/service-core';
|
|
|
5
5
|
import { PowerSyncMongo } from './db.js';
|
|
6
6
|
import { BucketDataDocument, BucketDataKey } from './models.js';
|
|
7
7
|
import { cacheKey } from './OperationBatch.js';
|
|
8
|
-
import { safeBulkWrite } from './util.js';
|
|
9
8
|
|
|
10
9
|
interface CurrentBucketState {
|
|
11
10
|
/** Bucket name */
|
|
@@ -33,14 +32,7 @@ interface CurrentBucketState {
|
|
|
33
32
|
/**
|
|
34
33
|
* Additional options, primarily for testing.
|
|
35
34
|
*/
|
|
36
|
-
export interface MongoCompactOptions extends storage.CompactOptions {
|
|
37
|
-
/** Minimum of 2 */
|
|
38
|
-
clearBatchLimit?: number;
|
|
39
|
-
/** Minimum of 1 */
|
|
40
|
-
moveBatchLimit?: number;
|
|
41
|
-
/** Minimum of 1 */
|
|
42
|
-
moveBatchQueryLimit?: number;
|
|
43
|
-
}
|
|
35
|
+
export interface MongoCompactOptions extends storage.CompactOptions {}
|
|
44
36
|
|
|
45
37
|
const DEFAULT_CLEAR_BATCH_LIMIT = 5000;
|
|
46
38
|
const DEFAULT_MOVE_BATCH_LIMIT = 2000;
|
|
@@ -265,7 +257,7 @@ export class MongoCompactor {
|
|
|
265
257
|
private async flush() {
|
|
266
258
|
if (this.updates.length > 0) {
|
|
267
259
|
logger.info(`Compacting ${this.updates.length} ops`);
|
|
268
|
-
await
|
|
260
|
+
await this.db.bucket_data.bulkWrite(this.updates, {
|
|
269
261
|
// Order is not important.
|
|
270
262
|
// Since checksums are not affected, these operations can happen in any order,
|
|
271
263
|
// and it's fine if the operations are partially applied.
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
CheckpointChanges,
|
|
14
14
|
GetCheckpointChangesOptions,
|
|
15
15
|
ReplicationCheckpoint,
|
|
16
|
+
SourceTable,
|
|
16
17
|
storage,
|
|
17
18
|
utils,
|
|
18
19
|
WatchWriteCheckpointOptions
|
|
@@ -23,7 +24,14 @@ import { wrapWithAbort } from 'ix/asynciterable/operators/withabort.js';
|
|
|
23
24
|
import * as timers from 'timers/promises';
|
|
24
25
|
import { MongoBucketStorage } from '../MongoBucketStorage.js';
|
|
25
26
|
import { PowerSyncMongo } from './db.js';
|
|
26
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
BucketDataDocument,
|
|
29
|
+
BucketDataKey,
|
|
30
|
+
SourceKey,
|
|
31
|
+
SourceTableDocument,
|
|
32
|
+
SyncRuleCheckpointState,
|
|
33
|
+
SyncRuleDocument
|
|
34
|
+
} from './models.js';
|
|
27
35
|
import { MongoBucketBatch } from './MongoBucketBatch.js';
|
|
28
36
|
import { MongoCompactor } from './MongoCompactor.js';
|
|
29
37
|
import { MongoWriteCheckpointAPI } from './MongoWriteCheckpointAPI.js';
|
|
@@ -163,17 +171,17 @@ export class MongoSyncBucketStorage
|
|
|
163
171
|
let result: storage.ResolveTableResult | null = null;
|
|
164
172
|
await this.db.client.withSession(async (session) => {
|
|
165
173
|
const col = this.db.source_tables;
|
|
166
|
-
let
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
);
|
|
174
|
+
let filter: Partial<SourceTableDocument> = {
|
|
175
|
+
group_id: group_id,
|
|
176
|
+
connection_id: connection_id,
|
|
177
|
+
schema_name: schema,
|
|
178
|
+
table_name: table,
|
|
179
|
+
replica_id_columns2: columns
|
|
180
|
+
};
|
|
181
|
+
if (objectId != null) {
|
|
182
|
+
filter.relation_id = objectId;
|
|
183
|
+
}
|
|
184
|
+
let doc = await col.findOne(filter, { session });
|
|
177
185
|
if (doc == null) {
|
|
178
186
|
doc = {
|
|
179
187
|
_id: new bson.ObjectId(),
|
|
@@ -202,31 +210,40 @@ export class MongoSyncBucketStorage
|
|
|
202
210
|
sourceTable.syncData = options.sync_rules.tableSyncsData(sourceTable);
|
|
203
211
|
sourceTable.syncParameters = options.sync_rules.tableSyncsParameters(sourceTable);
|
|
204
212
|
|
|
213
|
+
let dropTables: storage.SourceTable[] = [];
|
|
214
|
+
// Detect tables that are either renamed, or have different replica_id_columns
|
|
215
|
+
let truncateFilter = [{ schema_name: schema, table_name: table }] as any[];
|
|
216
|
+
if (objectId != null) {
|
|
217
|
+
// Only detect renames if the source uses relation ids.
|
|
218
|
+
truncateFilter.push({ relation_id: objectId });
|
|
219
|
+
}
|
|
205
220
|
const truncate = await col
|
|
206
221
|
.find(
|
|
207
222
|
{
|
|
208
223
|
group_id: group_id,
|
|
209
224
|
connection_id: connection_id,
|
|
210
225
|
_id: { $ne: doc._id },
|
|
211
|
-
$or:
|
|
226
|
+
$or: truncateFilter
|
|
212
227
|
},
|
|
213
228
|
{ session }
|
|
214
229
|
)
|
|
215
230
|
.toArray();
|
|
231
|
+
dropTables = truncate.map(
|
|
232
|
+
(doc) =>
|
|
233
|
+
new storage.SourceTable(
|
|
234
|
+
doc._id,
|
|
235
|
+
connection_tag,
|
|
236
|
+
doc.relation_id,
|
|
237
|
+
doc.schema_name,
|
|
238
|
+
doc.table_name,
|
|
239
|
+
doc.replica_id_columns2?.map((c) => ({ name: c.name, typeOid: c.type_oid, type: c.type })) ?? [],
|
|
240
|
+
doc.snapshot_done ?? true
|
|
241
|
+
)
|
|
242
|
+
);
|
|
243
|
+
|
|
216
244
|
result = {
|
|
217
245
|
table: sourceTable,
|
|
218
|
-
dropTables:
|
|
219
|
-
(doc) =>
|
|
220
|
-
new storage.SourceTable(
|
|
221
|
-
doc._id,
|
|
222
|
-
connection_tag,
|
|
223
|
-
doc.relation_id ?? 0,
|
|
224
|
-
doc.schema_name,
|
|
225
|
-
doc.table_name,
|
|
226
|
-
doc.replica_id_columns2?.map((c) => ({ name: c.name, typeOid: c.type_oid, type: c.type })) ?? [],
|
|
227
|
-
doc.snapshot_done ?? true
|
|
228
|
-
)
|
|
229
|
-
)
|
|
246
|
+
dropTables: dropTables
|
|
230
247
|
};
|
|
231
248
|
});
|
|
232
249
|
return result!;
|
|
@@ -313,13 +330,7 @@ export class MongoSyncBucketStorage
|
|
|
313
330
|
// 1. We can calculate the document size accurately without serializing again.
|
|
314
331
|
// 2. We can delay parsing the results until it's needed.
|
|
315
332
|
// We manually use bson.deserialize below
|
|
316
|
-
raw: true
|
|
317
|
-
|
|
318
|
-
// Since we're using raw: true and parsing ourselves later, we don't need bigint
|
|
319
|
-
// support here.
|
|
320
|
-
// Disabling due to https://jira.mongodb.org/browse/NODE-6165, and the fact that this
|
|
321
|
-
// is one of our most common queries.
|
|
322
|
-
useBigInt64: false
|
|
333
|
+
raw: true
|
|
323
334
|
}
|
|
324
335
|
) as unknown as mongo.FindCursor<Buffer>;
|
|
325
336
|
|
|
@@ -593,7 +604,7 @@ export class MongoSyncBucketStorage
|
|
|
593
604
|
await this.db.sync_rules.updateMany(
|
|
594
605
|
{
|
|
595
606
|
_id: { $ne: this.group_id },
|
|
596
|
-
state: storage.SyncRuleState.ACTIVE
|
|
607
|
+
state: { $in: [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED] }
|
|
597
608
|
},
|
|
598
609
|
{
|
|
599
610
|
$set: {
|
|
@@ -646,7 +657,7 @@ export class MongoSyncBucketStorage
|
|
|
646
657
|
doc = await this.db.sync_rules.findOne(
|
|
647
658
|
{
|
|
648
659
|
_id: syncRulesId,
|
|
649
|
-
state: storage.SyncRuleState.ACTIVE
|
|
660
|
+
state: { $in: [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED] }
|
|
650
661
|
},
|
|
651
662
|
{
|
|
652
663
|
session,
|
|
@@ -717,7 +728,7 @@ export class MongoSyncBucketStorage
|
|
|
717
728
|
// Irrelevant update
|
|
718
729
|
continue;
|
|
719
730
|
}
|
|
720
|
-
if (doc.state != storage.SyncRuleState.ACTIVE) {
|
|
731
|
+
if (doc.state != storage.SyncRuleState.ACTIVE && doc.state != storage.SyncRuleState.ERRORED) {
|
|
721
732
|
// Sync rules have changed - abort and restart.
|
|
722
733
|
// Should this error instead?
|
|
723
734
|
break;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as framework from '@powersync/lib-services-framework';
|
|
2
2
|
import { storage } from '@powersync/service-core';
|
|
3
3
|
import { PowerSyncMongo } from './db.js';
|
|
4
|
-
import { safeBulkWrite } from './util.js';
|
|
5
4
|
|
|
6
5
|
export type MongoCheckpointAPIOptions = {
|
|
7
6
|
db: PowerSyncMongo;
|
|
@@ -127,8 +126,7 @@ export async function batchCreateCustomWriteCheckpoints(
|
|
|
127
126
|
return;
|
|
128
127
|
}
|
|
129
128
|
|
|
130
|
-
await
|
|
131
|
-
db.custom_write_checkpoints,
|
|
129
|
+
await db.custom_write_checkpoints.bulkWrite(
|
|
132
130
|
checkpoints.map((checkpointOptions) => ({
|
|
133
131
|
updateOne: {
|
|
134
132
|
filter: { user_id: checkpointOptions.user_id, sync_rules_id: checkpointOptions.sync_rules_id },
|
|
@@ -41,6 +41,10 @@ export class OperationBatch {
|
|
|
41
41
|
return this.batch.length >= MAX_BATCH_COUNT || this.currentSize > MAX_RECORD_BATCH_SIZE;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
hasData() {
|
|
45
|
+
return this.length > 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
44
48
|
/**
|
|
45
49
|
*
|
|
46
50
|
* @param sizes Map of source key to estimated size of the current_data document, or undefined if current_data is not persisted.
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
CurrentDataDocument,
|
|
16
16
|
SourceKey
|
|
17
17
|
} from './models.js';
|
|
18
|
-
import { replicaIdToSubkey
|
|
18
|
+
import { replicaIdToSubkey } from './util.js';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Maximum size of operations we write in a single transaction.
|
|
@@ -245,33 +245,34 @@ export class PersistedBatch {
|
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
async flush(db: PowerSyncMongo, session: mongo.ClientSession) {
|
|
248
|
+
const startAt = performance.now();
|
|
248
249
|
if (this.bucketData.length > 0) {
|
|
249
|
-
|
|
250
|
-
await safeBulkWrite(db.bucket_data, this.bucketData, {
|
|
250
|
+
await db.bucket_data.bulkWrite(this.bucketData, {
|
|
251
251
|
session,
|
|
252
252
|
// inserts only - order doesn't matter
|
|
253
253
|
ordered: false
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
256
|
if (this.bucketParameters.length > 0) {
|
|
257
|
-
await
|
|
257
|
+
await db.bucket_parameters.bulkWrite(this.bucketParameters, {
|
|
258
258
|
session,
|
|
259
259
|
// inserts only - order doesn't matter
|
|
260
260
|
ordered: false
|
|
261
261
|
});
|
|
262
262
|
}
|
|
263
263
|
if (this.currentData.length > 0) {
|
|
264
|
-
await
|
|
264
|
+
await db.current_data.bulkWrite(this.currentData, {
|
|
265
265
|
session,
|
|
266
266
|
// may update and delete data within the same batch - order matters
|
|
267
267
|
ordered: true
|
|
268
268
|
});
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
+
const duration = performance.now() - startAt;
|
|
271
272
|
logger.info(
|
|
272
273
|
`powersync_${this.group_id} Flushed ${this.bucketData.length} + ${this.bucketParameters.length} + ${
|
|
273
274
|
this.currentData.length
|
|
274
|
-
} updates, ${Math.round(this.currentSize / 1024)}kb. Last op_id: ${this.debugLastOpId}`
|
|
275
|
+
} updates, ${Math.round(this.currentSize / 1024)}kb in ${duration.toFixed(0)}ms. Last op_id: ${this.debugLastOpId}`
|
|
275
276
|
);
|
|
276
277
|
|
|
277
278
|
this.bucketData = [];
|
|
@@ -124,48 +124,3 @@ export const connectMongoForTests = (url: string, isCI: boolean) => {
|
|
|
124
124
|
});
|
|
125
125
|
return new PowerSyncMongo(client);
|
|
126
126
|
};
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* MongoDB bulkWrite internally splits the operations into batches
|
|
130
|
-
* so that no batch exceeds 16MB. However, there are cases where
|
|
131
|
-
* the batch size is very close to 16MB, where additional metadata
|
|
132
|
-
* on the server pushes it over the limit, resulting in this error
|
|
133
|
-
* from the server:
|
|
134
|
-
*
|
|
135
|
-
* > MongoBulkWriteError: BSONObj size: 16814023 (0x1008FC7) is invalid. Size must be between 0 and 16793600(16MB) First element: insert: "bucket_data"
|
|
136
|
-
*
|
|
137
|
-
* We work around the issue by doing our own batching, limiting the
|
|
138
|
-
* batch size to 15MB. This does add additional overhead with
|
|
139
|
-
* BSON.calculateObjectSize.
|
|
140
|
-
*/
|
|
141
|
-
export async function safeBulkWrite<T extends mongo.Document>(
|
|
142
|
-
collection: mongo.Collection<T>,
|
|
143
|
-
operations: mongo.AnyBulkWriteOperation<T>[],
|
|
144
|
-
options: mongo.BulkWriteOptions
|
|
145
|
-
) {
|
|
146
|
-
// Must be below 16MB.
|
|
147
|
-
// We could probably go a little closer, but 15MB is a safe threshold.
|
|
148
|
-
const BULK_WRITE_LIMIT = 15 * 1024 * 1024;
|
|
149
|
-
|
|
150
|
-
let batch: mongo.AnyBulkWriteOperation<T>[] = [];
|
|
151
|
-
let currentSize = 0;
|
|
152
|
-
// Estimated overhead per operation, should be smaller in reality.
|
|
153
|
-
const keySize = 8;
|
|
154
|
-
for (let op of operations) {
|
|
155
|
-
const bsonSize =
|
|
156
|
-
mongo.BSON.calculateObjectSize(op, {
|
|
157
|
-
checkKeys: false,
|
|
158
|
-
ignoreUndefined: true
|
|
159
|
-
} as any) + keySize;
|
|
160
|
-
if (batch.length > 0 && currentSize + bsonSize > BULK_WRITE_LIMIT) {
|
|
161
|
-
await collection.bulkWrite(batch, options);
|
|
162
|
-
currentSize = 0;
|
|
163
|
-
batch = [];
|
|
164
|
-
}
|
|
165
|
-
batch.push(op);
|
|
166
|
-
currentSize += bsonSize;
|
|
167
|
-
}
|
|
168
|
-
if (batch.length > 0) {
|
|
169
|
-
await collection.bulkWrite(batch, options);
|
|
170
|
-
}
|
|
171
|
-
}
|