@powersync/service-module-mongodb-storage 0.12.7 → 0.12.8
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/dist/migrations/db/migrations/1760433882550-bucket-state-index2.d.ts +3 -0
- package/dist/migrations/db/migrations/1760433882550-bucket-state-index2.js +25 -0
- package/dist/migrations/db/migrations/1760433882550-bucket-state-index2.js.map +1 -0
- package/dist/storage/implementation/MongoCompactor.d.ts +13 -3
- package/dist/storage/implementation/MongoCompactor.js +86 -90
- package/dist/storage/implementation/MongoCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +2 -2
- package/dist/storage/implementation/MongoSyncBucketStorage.js +15 -4
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoTestStorageFactoryGenerator.js +1 -0
- package/dist/storage/implementation/MongoTestStorageFactoryGenerator.js.map +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js +6 -2
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/implementation/db.d.ts +4 -0
- package/dist/storage/implementation/db.js +10 -0
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/util.d.ts +1 -1
- package/dist/storage/implementation/util.js +1 -1
- package/package.json +7 -7
- package/src/migrations/db/migrations/1760433882550-bucket-state-index2.ts +34 -0
- package/src/storage/implementation/MongoCompactor.ts +100 -96
- package/src/storage/implementation/MongoSyncBucketStorage.ts +18 -5
- package/src/storage/implementation/MongoTestStorageFactoryGenerator.ts +1 -0
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +6 -2
- package/src/storage/implementation/db.ts +13 -0
- package/src/storage/implementation/util.ts +1 -1
- package/test/src/storage_compacting.test.ts +17 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MongoWriteCheckpointAPI.js","sourceRoot":"","sources":["../../../src/storage/implementation/MongoWriteCheckpointAPI.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MongoWriteCheckpointAPI.js","sourceRoot":"","sources":["../../../src/storage/implementation/MongoWriteCheckpointAPI.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,5 +48,9 @@ export declare class PowerSyncMongo {
|
|
|
48
48
|
* Only use in migrations and tests.
|
|
49
49
|
*/
|
|
50
50
|
createBucketStateIndex(): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Only use in migrations and tests.
|
|
53
|
+
*/
|
|
54
|
+
createBucketStateIndex2(): Promise<void>;
|
|
51
55
|
}
|
|
52
56
|
export declare function createPowerSyncMongo(config: MongoStorageConfig, options?: lib_mongo.MongoConnectionOptions): PowerSyncMongo;
|
|
@@ -105,6 +105,16 @@ export class PowerSyncMongo {
|
|
|
105
105
|
last_op: 1
|
|
106
106
|
}, { name: 'bucket_updates', unique: true });
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Only use in migrations and tests.
|
|
110
|
+
*/
|
|
111
|
+
async createBucketStateIndex2() {
|
|
112
|
+
// TODO: Implement a better mechanism to use migrations in tests
|
|
113
|
+
await this.bucket_state.createIndex({
|
|
114
|
+
'_id.g': 1,
|
|
115
|
+
'estimate_since_compact.count': -1
|
|
116
|
+
}, { name: 'dirty_count' });
|
|
117
|
+
}
|
|
108
118
|
}
|
|
109
119
|
export function createPowerSyncMongo(config, options) {
|
|
110
120
|
return new PowerSyncMongo(lib_mongo.createMongoClient(config, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/storage/implementation/db.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/storage/implementation/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ export declare function generateSlotName(prefix: string, sync_rules_id: number):
|
|
|
14
14
|
* However, that makes `has_more` detection very difficult, since the cursor is always closed
|
|
15
15
|
* after the first batch. Instead, we do a workaround to only fetch a single batch below.
|
|
16
16
|
*
|
|
17
|
-
* For this to be effective, set batchSize = limit in the find command.
|
|
17
|
+
* For this to be effective, set batchSize = limit + 1 in the find command.
|
|
18
18
|
*/
|
|
19
19
|
export declare function readSingleBatch<T>(cursor: mongo.AbstractCursor<T>): Promise<{
|
|
20
20
|
data: T[];
|
|
@@ -33,7 +33,7 @@ export function generateSlotName(prefix, sync_rules_id) {
|
|
|
33
33
|
* However, that makes `has_more` detection very difficult, since the cursor is always closed
|
|
34
34
|
* after the first batch. Instead, we do a workaround to only fetch a single batch below.
|
|
35
35
|
*
|
|
36
|
-
* For this to be effective, set batchSize = limit in the find command.
|
|
36
|
+
* For this to be effective, set batchSize = limit + 1 in the find command.
|
|
37
37
|
*/
|
|
38
38
|
export async function readSingleBatch(cursor) {
|
|
39
39
|
try {
|
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.12.
|
|
5
|
+
"version": "0.12.8",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"license": "FSL-1.1-ALv2",
|
|
8
8
|
"type": "module",
|
|
@@ -22,20 +22,20 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"bson": "^6.10.
|
|
25
|
+
"bson": "^6.10.4",
|
|
26
26
|
"ix": "^5.0.0",
|
|
27
27
|
"lru-cache": "^10.2.2",
|
|
28
28
|
"ts-codec": "^1.3.0",
|
|
29
29
|
"uuid": "^11.1.0",
|
|
30
|
-
"@powersync/lib-service-mongodb": "0.6.
|
|
31
|
-
"@powersync/lib-services-framework": "0.7.
|
|
32
|
-
"@powersync/service-core": "1.15.
|
|
30
|
+
"@powersync/lib-service-mongodb": "0.6.10",
|
|
31
|
+
"@powersync/lib-services-framework": "0.7.8",
|
|
32
|
+
"@powersync/service-core": "1.15.8",
|
|
33
33
|
"@powersync/service-jsonbig": "0.17.11",
|
|
34
|
-
"@powersync/service-sync-rules": "0.29.
|
|
34
|
+
"@powersync/service-sync-rules": "0.29.5",
|
|
35
35
|
"@powersync/service-types": "0.13.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@powersync/service-core-tests": "0.12.
|
|
38
|
+
"@powersync/service-core-tests": "0.12.8"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsc -b",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { migrations } from '@powersync/service-core';
|
|
2
|
+
import * as storage from '../../../storage/storage-index.js';
|
|
3
|
+
import { MongoStorageConfig } from '../../../types/types.js';
|
|
4
|
+
|
|
5
|
+
const INDEX_NAME = 'dirty_buckets';
|
|
6
|
+
|
|
7
|
+
export const up: migrations.PowerSyncMigrationFunction = async (context) => {
|
|
8
|
+
const {
|
|
9
|
+
service_context: { configuration }
|
|
10
|
+
} = context;
|
|
11
|
+
const db = storage.createPowerSyncMongo(configuration.storage as MongoStorageConfig);
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
await db.createBucketStateIndex2();
|
|
15
|
+
} finally {
|
|
16
|
+
await db.client.close();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const down: migrations.PowerSyncMigrationFunction = async (context) => {
|
|
21
|
+
const {
|
|
22
|
+
service_context: { configuration }
|
|
23
|
+
} = context;
|
|
24
|
+
|
|
25
|
+
const db = storage.createPowerSyncMongo(configuration.storage as MongoStorageConfig);
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
if (await db.bucket_state.indexExists(INDEX_NAME)) {
|
|
29
|
+
await db.bucket_state.dropIndex(INDEX_NAME);
|
|
30
|
+
}
|
|
31
|
+
} finally {
|
|
32
|
+
await db.client.close();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { mongo, MONGO_OPERATION_TIMEOUT_MS } from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { logger, ReplicationAssertionError, ServiceAssertionError } from '@powersync/lib-services-framework';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addChecksums,
|
|
5
|
+
InternalOpId,
|
|
6
|
+
isPartialChecksum,
|
|
7
|
+
PopulateChecksumCacheResults,
|
|
8
|
+
storage,
|
|
9
|
+
utils
|
|
10
|
+
} from '@powersync/service-core';
|
|
4
11
|
|
|
5
12
|
import { PowerSyncMongo } from './db.js';
|
|
6
13
|
import { BucketDataDocument, BucketDataKey, BucketStateDocument } from './models.js';
|
|
@@ -10,6 +17,7 @@ import { cacheKey } from './OperationBatch.js';
|
|
|
10
17
|
interface CurrentBucketState {
|
|
11
18
|
/** Bucket name */
|
|
12
19
|
bucket: string;
|
|
20
|
+
|
|
13
21
|
/**
|
|
14
22
|
* Rows seen in the bucket, with the last op_id of each.
|
|
15
23
|
*/
|
|
@@ -96,67 +104,56 @@ export class MongoCompactor {
|
|
|
96
104
|
// We can make this more efficient later on by iterating
|
|
97
105
|
// through the buckets in a single query.
|
|
98
106
|
// That makes batching more tricky, so we leave for later.
|
|
99
|
-
await this.
|
|
107
|
+
await this.compactSingleBucket(bucket);
|
|
100
108
|
}
|
|
101
109
|
} else {
|
|
102
|
-
await this.
|
|
110
|
+
await this.compactDirtyBuckets();
|
|
103
111
|
}
|
|
104
112
|
}
|
|
105
113
|
|
|
106
|
-
async
|
|
107
|
-
|
|
114
|
+
private async compactDirtyBuckets() {
|
|
115
|
+
while (!this.signal?.aborted) {
|
|
116
|
+
// Process all buckets with 1 or more changes since last time
|
|
117
|
+
const buckets = await this.dirtyBucketBatch({ minBucketChanges: 1 });
|
|
118
|
+
if (buckets.length == 0) {
|
|
119
|
+
// All done
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
for (let bucket of buckets) {
|
|
123
|
+
await this.compactSingleBucket(bucket);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
108
127
|
|
|
109
|
-
|
|
128
|
+
private async compactSingleBucket(bucket: string) {
|
|
129
|
+
const idLimitBytes = this.idLimitBytes;
|
|
110
130
|
|
|
111
|
-
let
|
|
112
|
-
|
|
131
|
+
let currentState: CurrentBucketState = {
|
|
132
|
+
bucket,
|
|
133
|
+
seen: new Map(),
|
|
134
|
+
trackingSize: 0,
|
|
135
|
+
lastNotPut: null,
|
|
136
|
+
opsSincePut: 0,
|
|
113
137
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
// Exact bucket name
|
|
119
|
-
bucketLower = bucket;
|
|
120
|
-
bucketUpper = bucket;
|
|
121
|
-
} else {
|
|
122
|
-
// Bucket definition name
|
|
123
|
-
bucketLower = `${bucket}[`;
|
|
124
|
-
bucketUpper = `${bucket}[\uFFFF`;
|
|
125
|
-
}
|
|
138
|
+
checksum: 0,
|
|
139
|
+
opCount: 0,
|
|
140
|
+
opBytes: 0
|
|
141
|
+
};
|
|
126
142
|
|
|
127
143
|
// Constant lower bound
|
|
128
144
|
const lowerBound: BucketDataKey = {
|
|
129
145
|
g: this.group_id,
|
|
130
|
-
b:
|
|
146
|
+
b: bucket,
|
|
131
147
|
o: new mongo.MinKey() as any
|
|
132
148
|
};
|
|
133
149
|
|
|
134
150
|
// Upper bound is adjusted for each batch
|
|
135
151
|
let upperBound: BucketDataKey = {
|
|
136
152
|
g: this.group_id,
|
|
137
|
-
b:
|
|
153
|
+
b: bucket,
|
|
138
154
|
o: new mongo.MaxKey() as any
|
|
139
155
|
};
|
|
140
156
|
|
|
141
|
-
const doneWithBucket = async () => {
|
|
142
|
-
if (currentState == null) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
// Free memory before clearing bucket
|
|
146
|
-
currentState.seen.clear();
|
|
147
|
-
if (currentState.lastNotPut != null && currentState.opsSincePut >= 1) {
|
|
148
|
-
logger.info(
|
|
149
|
-
`Inserting CLEAR at ${this.group_id}:${currentState.bucket}:${currentState.lastNotPut} to remove ${currentState.opsSincePut} operations`
|
|
150
|
-
);
|
|
151
|
-
// Need flush() before clear()
|
|
152
|
-
await this.flush();
|
|
153
|
-
await this.clearBucket(currentState);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Do this _after_ clearBucket so that we have accurate counts.
|
|
157
|
-
this.updateBucketChecksums(currentState);
|
|
158
|
-
};
|
|
159
|
-
|
|
160
157
|
while (!this.signal?.aborted) {
|
|
161
158
|
// Query one batch at a time, to avoid cursor timeouts
|
|
162
159
|
const cursor = this.db.bucket_data.aggregate<BucketDataDocument & { size: number | bigint }>(
|
|
@@ -184,7 +181,11 @@ export class MongoCompactor {
|
|
|
184
181
|
}
|
|
185
182
|
}
|
|
186
183
|
],
|
|
187
|
-
{
|
|
184
|
+
{
|
|
185
|
+
// batchSize is 1 more than limit to auto-close the cursor.
|
|
186
|
+
// See https://github.com/mongodb/node-mongodb-native/pull/4580
|
|
187
|
+
batchSize: this.moveBatchQueryLimit + 1
|
|
188
|
+
}
|
|
188
189
|
);
|
|
189
190
|
// We don't limit to a single batch here, since that often causes MongoDB to scan through more than it returns.
|
|
190
191
|
// Instead, we load up to the limit.
|
|
@@ -199,22 +200,6 @@ export class MongoCompactor {
|
|
|
199
200
|
upperBound = batch[batch.length - 1]._id;
|
|
200
201
|
|
|
201
202
|
for (let doc of batch) {
|
|
202
|
-
if (currentState == null || doc._id.b != currentState.bucket) {
|
|
203
|
-
await doneWithBucket();
|
|
204
|
-
|
|
205
|
-
currentState = {
|
|
206
|
-
bucket: doc._id.b,
|
|
207
|
-
seen: new Map(),
|
|
208
|
-
trackingSize: 0,
|
|
209
|
-
lastNotPut: null,
|
|
210
|
-
opsSincePut: 0,
|
|
211
|
-
|
|
212
|
-
checksum: 0,
|
|
213
|
-
opCount: 0,
|
|
214
|
-
opBytes: 0
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
203
|
if (doc._id.o > this.maxOpId) {
|
|
219
204
|
continue;
|
|
220
205
|
}
|
|
@@ -285,12 +270,22 @@ export class MongoCompactor {
|
|
|
285
270
|
}
|
|
286
271
|
}
|
|
287
272
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
273
|
+
logger.info(`Processed batch of length ${batch.length} current bucket: ${bucket}`);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Free memory before clearing bucket
|
|
277
|
+
currentState.seen.clear();
|
|
278
|
+
if (currentState.lastNotPut != null && currentState.opsSincePut >= 1) {
|
|
279
|
+
logger.info(
|
|
280
|
+
`Inserting CLEAR at ${this.group_id}:${bucket}:${currentState.lastNotPut} to remove ${currentState.opsSincePut} operations`
|
|
281
|
+
);
|
|
282
|
+
// Need flush() before clear()
|
|
283
|
+
await this.flush();
|
|
284
|
+
await this.clearBucket(currentState);
|
|
291
285
|
}
|
|
292
286
|
|
|
293
|
-
|
|
287
|
+
// Do this _after_ clearBucket so that we have accurate counts.
|
|
288
|
+
this.updateBucketChecksums(currentState);
|
|
294
289
|
|
|
295
290
|
// Need another flush after updateBucketChecksums()
|
|
296
291
|
await this.flush();
|
|
@@ -478,50 +473,55 @@ export class MongoCompactor {
|
|
|
478
473
|
/**
|
|
479
474
|
* Subset of compact, only populating checksums where relevant.
|
|
480
475
|
*/
|
|
481
|
-
async populateChecksums() {
|
|
482
|
-
|
|
483
|
-
let lowerBound: BucketStateDocument['_id'] = {
|
|
484
|
-
g: this.group_id,
|
|
485
|
-
b: new mongo.MinKey() as any
|
|
486
|
-
};
|
|
487
|
-
// This is static
|
|
488
|
-
const upperBound: BucketStateDocument['_id'] = {
|
|
489
|
-
g: this.group_id,
|
|
490
|
-
b: new mongo.MaxKey() as any
|
|
491
|
-
};
|
|
476
|
+
async populateChecksums(options: { minBucketChanges: number }): Promise<PopulateChecksumCacheResults> {
|
|
477
|
+
let count = 0;
|
|
492
478
|
while (!this.signal?.aborted) {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
479
|
+
const buckets = await this.dirtyBucketBatch(options);
|
|
480
|
+
if (buckets.length == 0) {
|
|
481
|
+
// All done
|
|
482
|
+
break;
|
|
483
|
+
}
|
|
484
|
+
const start = Date.now();
|
|
485
|
+
logger.info(`Calculating checksums for batch of ${buckets.length} buckets, starting at ${buckets[0]}`);
|
|
486
|
+
|
|
487
|
+
await this.updateChecksumsBatch(buckets);
|
|
488
|
+
logger.info(`Updated checksums for batch of ${buckets.length} buckets in ${Date.now() - start}ms`);
|
|
489
|
+
count += buckets.length;
|
|
490
|
+
}
|
|
491
|
+
return { buckets: count };
|
|
492
|
+
}
|
|
501
493
|
|
|
502
|
-
|
|
503
|
-
|
|
494
|
+
/**
|
|
495
|
+
* Returns a batch of dirty buckets - buckets with most changes first.
|
|
496
|
+
*
|
|
497
|
+
* This cannot be used to iterate on its own - the client is expected to process these buckets and
|
|
498
|
+
* set estimate_since_compact.count: 0 when done, before fetching the next batch.
|
|
499
|
+
*/
|
|
500
|
+
private async dirtyBucketBatch(options: { minBucketChanges: number }): Promise<string[]> {
|
|
501
|
+
if (options.minBucketChanges <= 0) {
|
|
502
|
+
throw new ReplicationAssertionError('minBucketChanges must be >= 1');
|
|
503
|
+
}
|
|
504
|
+
// We make use of an index on {_id.g: 1, 'estimate_since_compact.count': -1}
|
|
505
|
+
const dirtyBuckets = await this.db.bucket_state
|
|
506
|
+
.find(
|
|
507
|
+
{
|
|
508
|
+
'_id.g': this.group_id,
|
|
509
|
+
'estimate_since_compact.count': { $gte: options.minBucketChanges }
|
|
510
|
+
},
|
|
511
|
+
{
|
|
504
512
|
projection: {
|
|
505
513
|
_id: 1
|
|
506
514
|
},
|
|
507
515
|
sort: {
|
|
508
|
-
|
|
516
|
+
'estimate_since_compact.count': -1
|
|
509
517
|
},
|
|
510
518
|
limit: 5_000,
|
|
511
519
|
maxTimeMS: MONGO_OPERATION_TIMEOUT_MS
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
// All done
|
|
516
|
-
break;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
logger.info(`Calculating checksums for batch of ${bucketsWithoutChecksums.length} buckets`);
|
|
520
|
-
|
|
521
|
-
await this.updateChecksumsBatch(bucketsWithoutChecksums.map((b) => b._id.b));
|
|
520
|
+
}
|
|
521
|
+
)
|
|
522
|
+
.toArray();
|
|
522
523
|
|
|
523
|
-
|
|
524
|
-
}
|
|
524
|
+
return dirtyBuckets.map((bucket) => bucket._id.b);
|
|
525
525
|
}
|
|
526
526
|
|
|
527
527
|
private async updateChecksumsBatch(buckets: string[]) {
|
|
@@ -555,6 +555,10 @@ export class MongoCompactor {
|
|
|
555
555
|
count: bucketChecksum.count,
|
|
556
556
|
checksum: BigInt(bucketChecksum.checksum),
|
|
557
557
|
bytes: null
|
|
558
|
+
},
|
|
559
|
+
estimate_since_compact: {
|
|
560
|
+
count: 0,
|
|
561
|
+
bytes: 0
|
|
558
562
|
}
|
|
559
563
|
}
|
|
560
564
|
},
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
InternalOpId,
|
|
17
17
|
internalToExternalOpId,
|
|
18
18
|
maxLsn,
|
|
19
|
+
PopulateChecksumCacheOptions,
|
|
20
|
+
PopulateChecksumCacheResults,
|
|
19
21
|
ProtocolOpId,
|
|
20
22
|
ReplicationCheckpoint,
|
|
21
23
|
storage,
|
|
@@ -403,7 +405,9 @@ export class MongoSyncBucketStorage
|
|
|
403
405
|
limit: batchLimit,
|
|
404
406
|
// Increase batch size above the default 101, so that we can fill an entire batch in
|
|
405
407
|
// one go.
|
|
406
|
-
batchSize
|
|
408
|
+
// batchSize is 1 more than limit to auto-close the cursor.
|
|
409
|
+
// See https://github.com/mongodb/node-mongodb-native/pull/4580
|
|
410
|
+
batchSize: batchLimit + 1,
|
|
407
411
|
// Raw mode is returns an array of Buffer instead of parsed documents.
|
|
408
412
|
// We use it so that:
|
|
409
413
|
// 1. We can calculate the document size accurately without serializing again.
|
|
@@ -663,7 +667,7 @@ export class MongoSyncBucketStorage
|
|
|
663
667
|
}
|
|
664
668
|
}
|
|
665
669
|
|
|
666
|
-
async populatePersistentChecksumCache(options:
|
|
670
|
+
async populatePersistentChecksumCache(options: PopulateChecksumCacheOptions): Promise<PopulateChecksumCacheResults> {
|
|
667
671
|
logger.info(`Populating persistent checksum cache...`);
|
|
668
672
|
const start = Date.now();
|
|
669
673
|
// We do a minimal compact here.
|
|
@@ -674,9 +678,14 @@ export class MongoSyncBucketStorage
|
|
|
674
678
|
memoryLimitMB: 0
|
|
675
679
|
});
|
|
676
680
|
|
|
677
|
-
await compactor.populateChecksums(
|
|
681
|
+
const result = await compactor.populateChecksums({
|
|
682
|
+
// There are cases with millions of small buckets, in which case it can take very long to
|
|
683
|
+
// populate the checksums, with minimal benefit. We skip the small buckets here.
|
|
684
|
+
minBucketChanges: options.minBucketChanges ?? 10
|
|
685
|
+
});
|
|
678
686
|
const duration = Date.now() - start;
|
|
679
687
|
logger.info(`Populated persistent checksum cache in ${(duration / 1000).toFixed(1)}s`);
|
|
688
|
+
return result;
|
|
680
689
|
}
|
|
681
690
|
|
|
682
691
|
/**
|
|
@@ -905,7 +914,9 @@ export class MongoSyncBucketStorage
|
|
|
905
914
|
'_id.b': 1
|
|
906
915
|
},
|
|
907
916
|
limit: limit + 1,
|
|
908
|
-
batchSize
|
|
917
|
+
// batchSize is 1 more than limit to auto-close the cursor.
|
|
918
|
+
// See https://github.com/mongodb/node-mongodb-native/pull/4580
|
|
919
|
+
batchSize: limit + 2,
|
|
909
920
|
singleBatch: true
|
|
910
921
|
}
|
|
911
922
|
)
|
|
@@ -935,7 +946,9 @@ export class MongoSyncBucketStorage
|
|
|
935
946
|
lookup: 1
|
|
936
947
|
},
|
|
937
948
|
limit: limit + 1,
|
|
938
|
-
batchSize
|
|
949
|
+
// batchSize is 1 more than limit to auto-close the cursor.
|
|
950
|
+
// See https://github.com/mongodb/node-mongodb-native/pull/4580
|
|
951
|
+
batchSize: limit + 2,
|
|
939
952
|
singleBatch: true
|
|
940
953
|
}
|
|
941
954
|
)
|
|
@@ -25,6 +25,7 @@ export const MongoTestStorageFactoryGenerator = (factoryOptions: MongoTestStorag
|
|
|
25
25
|
// Full migrations are not currently run for tests, so we manually create the important ones
|
|
26
26
|
await db.createCheckpointEventsCollection();
|
|
27
27
|
await db.createBucketStateIndex();
|
|
28
|
+
await db.createBucketStateIndex2();
|
|
28
29
|
|
|
29
30
|
return new MongoBucketStorage(db, { slot_name_prefix: 'test_' }, factoryOptions.internalOptions);
|
|
30
31
|
};
|
|
@@ -111,7 +111,9 @@ export class MongoWriteCheckpointAPI implements storage.WriteCheckpointAPI {
|
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
limit: limit + 1,
|
|
114
|
-
batchSize
|
|
114
|
+
// batchSize is 1 more than limit to auto-close the cursor.
|
|
115
|
+
// See https://github.com/mongodb/node-mongodb-native/pull/4580
|
|
116
|
+
batchSize: limit + 2,
|
|
115
117
|
singleBatch: true
|
|
116
118
|
}
|
|
117
119
|
)
|
|
@@ -140,7 +142,9 @@ export class MongoWriteCheckpointAPI implements storage.WriteCheckpointAPI {
|
|
|
140
142
|
},
|
|
141
143
|
{
|
|
142
144
|
limit: limit + 1,
|
|
143
|
-
batchSize
|
|
145
|
+
// batchSize is 1 more than limit to auto-close the cursor.
|
|
146
|
+
// See https://github.com/mongodb/node-mongodb-native/pull/4580
|
|
147
|
+
batchSize: limit + 2,
|
|
144
148
|
singleBatch: true
|
|
145
149
|
}
|
|
146
150
|
)
|
|
@@ -141,6 +141,19 @@ export class PowerSyncMongo {
|
|
|
141
141
|
{ name: 'bucket_updates', unique: true }
|
|
142
142
|
);
|
|
143
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Only use in migrations and tests.
|
|
146
|
+
*/
|
|
147
|
+
async createBucketStateIndex2() {
|
|
148
|
+
// TODO: Implement a better mechanism to use migrations in tests
|
|
149
|
+
await this.bucket_state.createIndex(
|
|
150
|
+
{
|
|
151
|
+
'_id.g': 1,
|
|
152
|
+
'estimate_since_compact.count': -1
|
|
153
|
+
},
|
|
154
|
+
{ name: 'dirty_count' }
|
|
155
|
+
);
|
|
156
|
+
}
|
|
144
157
|
}
|
|
145
158
|
|
|
146
159
|
export function createPowerSyncMongo(config: MongoStorageConfig, options?: lib_mongo.MongoConnectionOptions) {
|
|
@@ -41,7 +41,7 @@ export function generateSlotName(prefix: string, sync_rules_id: number) {
|
|
|
41
41
|
* However, that makes `has_more` detection very difficult, since the cursor is always closed
|
|
42
42
|
* after the first batch. Instead, we do a workaround to only fetch a single batch below.
|
|
43
43
|
*
|
|
44
|
-
* For this to be effective, set batchSize = limit in the find command.
|
|
44
|
+
* For this to be effective, set batchSize = limit + 1 in the find command.
|
|
45
45
|
*/
|
|
46
46
|
export async function readSingleBatch<T>(cursor: mongo.AbstractCursor<T>): Promise<{ data: T[]; hasMore: boolean }> {
|
|
47
47
|
try {
|
|
@@ -97,10 +97,25 @@ bucket_definitions:
|
|
|
97
97
|
await populate(bucketStorage);
|
|
98
98
|
const { checkpoint } = await bucketStorage.getCheckpoint();
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
// Default is to small small numbers - should be a no-op
|
|
101
|
+
const result0 = await bucketStorage.populatePersistentChecksumCache({
|
|
102
|
+
maxOpId: checkpoint
|
|
103
|
+
});
|
|
104
|
+
expect(result0.buckets).toEqual(0);
|
|
105
|
+
|
|
106
|
+
// This should cache the checksums for the two buckets
|
|
107
|
+
const result1 = await bucketStorage.populatePersistentChecksumCache({
|
|
108
|
+
maxOpId: checkpoint,
|
|
109
|
+
minBucketChanges: 1
|
|
110
|
+
});
|
|
111
|
+
expect(result1.buckets).toEqual(2);
|
|
112
|
+
|
|
113
|
+
// This should be a no-op, as the checksums are already cached
|
|
114
|
+
const result2 = await bucketStorage.populatePersistentChecksumCache({
|
|
101
115
|
maxOpId: checkpoint,
|
|
102
|
-
|
|
116
|
+
minBucketChanges: 1
|
|
103
117
|
});
|
|
118
|
+
expect(result2.buckets).toEqual(0);
|
|
104
119
|
|
|
105
120
|
const checksumAfter = await bucketStorage.getChecksums(checkpoint, ['by_user2["u1"]', 'by_user2["u2"]']);
|
|
106
121
|
expect(checksumAfter.get('by_user2["u1"]')).toEqual({
|