@powersync/service-module-mongodb-storage 0.10.3 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/dist/storage/implementation/MongoBucketBatch.d.ts +20 -1
- package/dist/storage/implementation/MongoBucketBatch.js +59 -3
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoParameterCompactor.d.ts +17 -0
- package/dist/storage/implementation/MongoParameterCompactor.js +92 -0
- package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -0
- package/dist/storage/implementation/MongoStorageProvider.js +2 -0
- package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +12 -4
- package/dist/storage/implementation/MongoSyncBucketStorage.js +153 -109
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/db.js +5 -2
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +6 -0
- package/dist/storage/implementation/util.d.ts +1 -4
- package/dist/storage/implementation/util.js +14 -7
- package/dist/storage/implementation/util.js.map +1 -1
- package/package.json +7 -7
- package/src/storage/implementation/MongoBucketBatch.ts +74 -2
- package/src/storage/implementation/MongoParameterCompactor.ts +105 -0
- package/src/storage/implementation/MongoStorageProvider.ts +2 -1
- package/src/storage/implementation/MongoSyncBucketStorage.ts +169 -152
- package/src/storage/implementation/db.ts +8 -2
- package/src/storage/implementation/models.ts +6 -0
- package/src/storage/implementation/util.ts +14 -8
- package/test/src/storage_compacting.test.ts +2 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/storage/implementation/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
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.
|
|
5
|
+
"version": "0.11.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"license": "FSL-1.1-Apache-2.0",
|
|
8
8
|
"type": "module",
|
|
@@ -27,15 +27,15 @@
|
|
|
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.
|
|
30
|
+
"@powersync/lib-service-mongodb": "0.6.3",
|
|
31
|
+
"@powersync/lib-services-framework": "0.7.2",
|
|
32
|
+
"@powersync/service-core": "1.14.0",
|
|
33
33
|
"@powersync/service-jsonbig": "0.17.10",
|
|
34
|
-
"@powersync/service-sync-rules": "0.
|
|
35
|
-
"@powersync/service-types": "0.12.
|
|
34
|
+
"@powersync/service-sync-rules": "0.28.0",
|
|
35
|
+
"@powersync/service-types": "0.12.1"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@powersync/service-core-tests": "0.
|
|
38
|
+
"@powersync/service-core-tests": "0.11.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsc -b",
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
BucketStorageMarkRecordUnavailable,
|
|
17
17
|
deserializeBson,
|
|
18
18
|
InternalOpId,
|
|
19
|
+
isCompleteRow,
|
|
19
20
|
SaveOperationTag,
|
|
20
21
|
storage,
|
|
21
22
|
utils
|
|
@@ -49,6 +50,7 @@ export interface MongoBucketBatchOptions {
|
|
|
49
50
|
lastCheckpointLsn: string | null;
|
|
50
51
|
keepaliveOp: InternalOpId | null;
|
|
51
52
|
noCheckpointBeforeLsn: string;
|
|
53
|
+
resumeFromLsn: string | null;
|
|
52
54
|
storeCurrentData: boolean;
|
|
53
55
|
/**
|
|
54
56
|
* Set to true for initial replication.
|
|
@@ -99,6 +101,20 @@ export class MongoBucketBatch
|
|
|
99
101
|
*/
|
|
100
102
|
public last_flushed_op: InternalOpId | null = null;
|
|
101
103
|
|
|
104
|
+
/**
|
|
105
|
+
* lastCheckpointLsn is the last consistent commit.
|
|
106
|
+
*
|
|
107
|
+
* While that is generally a "safe" point to resume from, there are cases where we may want to resume from a different point:
|
|
108
|
+
* 1. After an initial snapshot, we don't have a consistent commit yet, but need to resume from the snapshot LSN.
|
|
109
|
+
* 2. If "no_checkpoint_before_lsn" is set far in advance, it may take a while to reach that point. We
|
|
110
|
+
* may want to resume at incremental points before that.
|
|
111
|
+
*
|
|
112
|
+
* This is set when creating the batch, but may not be updated afterwards.
|
|
113
|
+
*/
|
|
114
|
+
public resumeFromLsn: string | null = null;
|
|
115
|
+
|
|
116
|
+
private needsActivation = true;
|
|
117
|
+
|
|
102
118
|
constructor(options: MongoBucketBatchOptions) {
|
|
103
119
|
super();
|
|
104
120
|
this.logger = options.logger ?? defaultLogger;
|
|
@@ -107,6 +123,7 @@ export class MongoBucketBatch
|
|
|
107
123
|
this.group_id = options.groupId;
|
|
108
124
|
this.last_checkpoint_lsn = options.lastCheckpointLsn;
|
|
109
125
|
this.no_checkpoint_before_lsn = options.noCheckpointBeforeLsn;
|
|
126
|
+
this.resumeFromLsn = options.resumeFromLsn;
|
|
110
127
|
this.session = this.client.startSession();
|
|
111
128
|
this.slot_name = options.slotName;
|
|
112
129
|
this.sync_rules = options.syncRules;
|
|
@@ -332,7 +349,7 @@ export class MongoBucketBatch
|
|
|
332
349
|
// Not an error if we re-apply a transaction
|
|
333
350
|
existing_buckets = [];
|
|
334
351
|
existing_lookups = [];
|
|
335
|
-
if (this.storeCurrentData) {
|
|
352
|
+
if (!isCompleteRow(this.storeCurrentData, after!)) {
|
|
336
353
|
if (this.markRecordUnavailable != null) {
|
|
337
354
|
// This will trigger a "resnapshot" of the record.
|
|
338
355
|
// This is not relevant if storeCurrentData is false, since we'll get the full row
|
|
@@ -685,6 +702,7 @@ export class MongoBucketBatch
|
|
|
685
702
|
|
|
686
703
|
if (!createEmptyCheckpoints && this.persisted_op == null) {
|
|
687
704
|
// Nothing to commit - also return true
|
|
705
|
+
await this.autoActivate(lsn);
|
|
688
706
|
return true;
|
|
689
707
|
}
|
|
690
708
|
|
|
@@ -729,12 +747,65 @@ export class MongoBucketBatch
|
|
|
729
747
|
},
|
|
730
748
|
{ session: this.session }
|
|
731
749
|
);
|
|
750
|
+
await this.autoActivate(lsn);
|
|
732
751
|
await this.db.notifyCheckpoint();
|
|
733
752
|
this.persisted_op = null;
|
|
734
753
|
this.last_checkpoint_lsn = lsn;
|
|
735
754
|
return true;
|
|
736
755
|
}
|
|
737
756
|
|
|
757
|
+
/**
|
|
758
|
+
* Switch from processing -> active if relevant.
|
|
759
|
+
*
|
|
760
|
+
* Called on new commits.
|
|
761
|
+
*/
|
|
762
|
+
private async autoActivate(lsn: string) {
|
|
763
|
+
if (!this.needsActivation) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Activate the batch, so it can start processing.
|
|
768
|
+
// This is done automatically when the first save() is called.
|
|
769
|
+
|
|
770
|
+
const session = this.session;
|
|
771
|
+
let activated = false;
|
|
772
|
+
await session.withTransaction(async () => {
|
|
773
|
+
const doc = await this.db.sync_rules.findOne({ _id: this.group_id }, { session });
|
|
774
|
+
if (doc && doc.state == 'PROCESSING') {
|
|
775
|
+
await this.db.sync_rules.updateOne(
|
|
776
|
+
{
|
|
777
|
+
_id: this.group_id
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
$set: {
|
|
781
|
+
state: storage.SyncRuleState.ACTIVE
|
|
782
|
+
}
|
|
783
|
+
},
|
|
784
|
+
{ session }
|
|
785
|
+
);
|
|
786
|
+
|
|
787
|
+
await this.db.sync_rules.updateMany(
|
|
788
|
+
{
|
|
789
|
+
_id: { $ne: this.group_id },
|
|
790
|
+
state: { $in: [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED] }
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
$set: {
|
|
794
|
+
state: storage.SyncRuleState.STOP
|
|
795
|
+
}
|
|
796
|
+
},
|
|
797
|
+
{ session }
|
|
798
|
+
);
|
|
799
|
+
activated = true;
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
if (activated) {
|
|
803
|
+
this.logger.info(`Activated new sync rules at ${lsn}`);
|
|
804
|
+
await this.db.notifyCheckpoint();
|
|
805
|
+
}
|
|
806
|
+
this.needsActivation = false;
|
|
807
|
+
}
|
|
808
|
+
|
|
738
809
|
async keepalive(lsn: string): Promise<boolean> {
|
|
739
810
|
if (this.last_checkpoint_lsn != null && lsn <= this.last_checkpoint_lsn) {
|
|
740
811
|
// No-op
|
|
@@ -782,13 +853,14 @@ export class MongoBucketBatch
|
|
|
782
853
|
},
|
|
783
854
|
{ session: this.session }
|
|
784
855
|
);
|
|
856
|
+
await this.autoActivate(lsn);
|
|
785
857
|
await this.db.notifyCheckpoint();
|
|
786
858
|
this.last_checkpoint_lsn = lsn;
|
|
787
859
|
|
|
788
860
|
return true;
|
|
789
861
|
}
|
|
790
862
|
|
|
791
|
-
async
|
|
863
|
+
async setResumeLsn(lsn: string): Promise<void> {
|
|
792
864
|
const update: Partial<SyncRuleDocument> = {
|
|
793
865
|
snapshot_lsn: lsn
|
|
794
866
|
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
2
|
+
import { bson, CompactOptions, InternalOpId } from '@powersync/service-core';
|
|
3
|
+
import { LRUCache } from 'lru-cache';
|
|
4
|
+
import { PowerSyncMongo } from './db.js';
|
|
5
|
+
import { mongo } from '@powersync/lib-service-mongodb';
|
|
6
|
+
import { BucketParameterDocument } from './models.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Compacts parameter lookup data (the bucket_parameters collection).
|
|
10
|
+
*
|
|
11
|
+
* This scans through the entire collection to find data to compact.
|
|
12
|
+
*
|
|
13
|
+
* For background, see the `/docs/parameters-lookups.md` file.
|
|
14
|
+
*/
|
|
15
|
+
export class MongoParameterCompactor {
|
|
16
|
+
constructor(
|
|
17
|
+
private db: PowerSyncMongo,
|
|
18
|
+
private group_id: number,
|
|
19
|
+
private checkpoint: InternalOpId,
|
|
20
|
+
private options: CompactOptions
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
async compact() {
|
|
24
|
+
logger.info(`Compacting parameters for group ${this.group_id} up to checkpoint ${this.checkpoint}`);
|
|
25
|
+
// This is the currently-active checkpoint.
|
|
26
|
+
// We do not remove any data that may be used by this checkpoint.
|
|
27
|
+
// snapshot queries ensure that if any clients are still using older checkpoints, they would
|
|
28
|
+
// not be affected by this compaction.
|
|
29
|
+
const checkpoint = this.checkpoint;
|
|
30
|
+
|
|
31
|
+
// Index on {'key.g': 1, lookup: 1, _id: 1}
|
|
32
|
+
// In theory, we could let MongoDB do more of the work here, by grouping by (key, lookup)
|
|
33
|
+
// in MongoDB already. However, that risks running into cases where MongoDB needs to process
|
|
34
|
+
// very large amounts of data before returning results, which could lead to timeouts.
|
|
35
|
+
const cursor = this.db.bucket_parameters.find(
|
|
36
|
+
{
|
|
37
|
+
'key.g': this.group_id
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
sort: { lookup: 1, _id: 1 },
|
|
41
|
+
batchSize: 10_000,
|
|
42
|
+
projection: { _id: 1, key: 1, lookup: 1, bucket_parameters: 1 }
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// The index doesn't cover sorting by key, so we keep our own cache of the last seen key.
|
|
47
|
+
let lastByKey = new LRUCache<string, InternalOpId>({
|
|
48
|
+
max: this.options.compactParameterCacheLimit ?? 10_000
|
|
49
|
+
});
|
|
50
|
+
let removeIds: InternalOpId[] = [];
|
|
51
|
+
let removeDeleted: mongo.AnyBulkWriteOperation<BucketParameterDocument>[] = [];
|
|
52
|
+
|
|
53
|
+
const flush = async (force: boolean) => {
|
|
54
|
+
if (removeIds.length >= 1000 || (force && removeIds.length > 0)) {
|
|
55
|
+
const results = await this.db.bucket_parameters.deleteMany({ _id: { $in: removeIds } });
|
|
56
|
+
logger.info(`Removed ${results.deletedCount} (${removeIds.length}) superseded parameter entries`);
|
|
57
|
+
removeIds = [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (removeDeleted.length > 10 || (force && removeDeleted.length > 0)) {
|
|
61
|
+
const results = await this.db.bucket_parameters.bulkWrite(removeDeleted);
|
|
62
|
+
logger.info(`Removed ${results.deletedCount} (${removeDeleted.length}) deleted parameter entries`);
|
|
63
|
+
removeDeleted = [];
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
while (await cursor.hasNext()) {
|
|
68
|
+
const batch = cursor.readBufferedDocuments();
|
|
69
|
+
for (let doc of batch) {
|
|
70
|
+
if (doc._id >= checkpoint) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const uniqueKey = (
|
|
74
|
+
bson.serialize({
|
|
75
|
+
k: doc.key,
|
|
76
|
+
l: doc.lookup
|
|
77
|
+
}) as Buffer
|
|
78
|
+
).toString('base64');
|
|
79
|
+
const previous = lastByKey.get(uniqueKey);
|
|
80
|
+
if (previous != null && previous < doc._id) {
|
|
81
|
+
// We have a newer entry for the same key, so we can remove the old one.
|
|
82
|
+
removeIds.push(previous);
|
|
83
|
+
}
|
|
84
|
+
lastByKey.set(uniqueKey, doc._id);
|
|
85
|
+
|
|
86
|
+
if (doc.bucket_parameters?.length == 0) {
|
|
87
|
+
// This is a delete operation, so we can remove it completely.
|
|
88
|
+
// For this we cannot remove the operation itself only: There is a possibility that
|
|
89
|
+
// there is still an earlier operation with the same key and lookup, that we don't have
|
|
90
|
+
// in the cache due to cache size limits. So we need to explicitly remove all earlier operations.
|
|
91
|
+
removeDeleted.push({
|
|
92
|
+
deleteMany: {
|
|
93
|
+
filter: { 'key.g': doc.key.g, lookup: doc.lookup, _id: { $lte: doc._id }, key: doc.key }
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
await flush(false);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
await flush(true);
|
|
103
|
+
logger.info('Parameter compaction completed');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as lib_mongo from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { ErrorCode, logger, ServiceAssertionError, ServiceError } from '@powersync/lib-services-framework';
|
|
3
|
-
import { storage } from '@powersync/service-core';
|
|
3
|
+
import { POWERSYNC_VERSION, storage } from '@powersync/service-core';
|
|
4
4
|
import { MongoStorageConfig } from '../../types/types.js';
|
|
5
5
|
import { MongoBucketStorage } from '../MongoBucketStorage.js';
|
|
6
6
|
import { PowerSyncMongo } from './db.js';
|
|
@@ -23,6 +23,7 @@ export class MongoStorageProvider implements storage.BucketStorageProvider {
|
|
|
23
23
|
|
|
24
24
|
const decodedConfig = MongoStorageConfig.decode(storage as any);
|
|
25
25
|
const client = lib_mongo.db.createMongoClient(decodedConfig, {
|
|
26
|
+
powersyncVersion: POWERSYNC_VERSION,
|
|
26
27
|
maxPoolSize: resolvedConfig.storage.max_pool_size ?? 8
|
|
27
28
|
});
|
|
28
29
|
|