@powersync/service-module-mongodb-storage 0.12.15 → 0.13.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 +35 -0
- package/dist/storage/implementation/MongoBucketBatch.d.ts +2 -2
- package/dist/storage/implementation/MongoBucketBatch.js +3 -5
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoPersistedSyncRules.d.ts +2 -1
- package/dist/storage/implementation/MongoPersistedSyncRules.js +4 -0
- package/dist/storage/implementation/MongoPersistedSyncRules.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +4 -4
- package/dist/storage/implementation/MongoSyncBucketStorage.js +3 -3
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.js +3 -2
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/utils/util.js.map +1 -1
- package/package.json +7 -7
- package/src/storage/implementation/MongoBucketBatch.ts +6 -7
- package/src/storage/implementation/MongoPersistedSyncRules.ts +5 -1
- package/src/storage/implementation/MongoSyncBucketStorage.ts +12 -10
- package/src/storage/implementation/MongoSyncRulesLock.ts +3 -2
- package/src/utils/util.ts +0 -1
- package/test/src/compression.test.ts +17 -0
- package/test/tsconfig.json +1 -7
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +2 -14
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
BroadcastIterable,
|
|
11
11
|
CHECKPOINT_INVALIDATE_ALL,
|
|
12
12
|
CheckpointChanges,
|
|
13
|
-
CompactOptions,
|
|
14
13
|
deserializeParameterLookup,
|
|
15
14
|
GetCheckpointChangesOptions,
|
|
16
15
|
InternalOpId,
|
|
@@ -25,10 +24,11 @@ import {
|
|
|
25
24
|
WatchWriteCheckpointOptions
|
|
26
25
|
} from '@powersync/service-core';
|
|
27
26
|
import { JSONBig } from '@powersync/service-jsonbig';
|
|
28
|
-
import {
|
|
27
|
+
import { HydratedSyncRules, ScopedParameterLookup, SqliteJsonRow } from '@powersync/service-sync-rules';
|
|
29
28
|
import * as bson from 'bson';
|
|
30
29
|
import { LRUCache } from 'lru-cache';
|
|
31
30
|
import * as timers from 'timers/promises';
|
|
31
|
+
import { idPrefixFilter, mapOpEntry, readSingleBatch, setSessionSnapshotTime } from '../../utils/util.js';
|
|
32
32
|
import { MongoBucketStorage } from '../MongoBucketStorage.js';
|
|
33
33
|
import { PowerSyncMongo } from './db.js';
|
|
34
34
|
import { BucketDataDocument, BucketDataKey, BucketStateDocument, SourceKey, SourceTableDocument } from './models.js';
|
|
@@ -37,7 +37,6 @@ import { MongoChecksumOptions, MongoChecksums } from './MongoChecksums.js';
|
|
|
37
37
|
import { MongoCompactor } from './MongoCompactor.js';
|
|
38
38
|
import { MongoParameterCompactor } from './MongoParameterCompactor.js';
|
|
39
39
|
import { MongoWriteCheckpointAPI } from './MongoWriteCheckpointAPI.js';
|
|
40
|
-
import { idPrefixFilter, mapOpEntry, readSingleBatch, setSessionSnapshotTime } from '../../utils/util.js';
|
|
41
40
|
|
|
42
41
|
export interface MongoSyncBucketStorageOptions {
|
|
43
42
|
checksumOptions?: MongoChecksumOptions;
|
|
@@ -61,7 +60,7 @@ export class MongoSyncBucketStorage
|
|
|
61
60
|
private readonly db: PowerSyncMongo;
|
|
62
61
|
readonly checksums: MongoChecksums;
|
|
63
62
|
|
|
64
|
-
private parsedSyncRulesCache: { parsed:
|
|
63
|
+
private parsedSyncRulesCache: { parsed: HydratedSyncRules; options: storage.ParseSyncRulesOptions } | undefined;
|
|
65
64
|
private writeCheckpointAPI: MongoWriteCheckpointAPI;
|
|
66
65
|
|
|
67
66
|
constructor(
|
|
@@ -101,14 +100,14 @@ export class MongoSyncBucketStorage
|
|
|
101
100
|
});
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
getParsedSyncRules(options: storage.ParseSyncRulesOptions):
|
|
103
|
+
getParsedSyncRules(options: storage.ParseSyncRulesOptions): HydratedSyncRules {
|
|
105
104
|
const { parsed, options: cachedOptions } = this.parsedSyncRulesCache ?? {};
|
|
106
105
|
/**
|
|
107
106
|
* Check if the cached sync rules, if present, had the same options.
|
|
108
107
|
* Parse sync rules if the options are different or if there is no cached value.
|
|
109
108
|
*/
|
|
110
109
|
if (!parsed || options.defaultSchema != cachedOptions?.defaultSchema) {
|
|
111
|
-
this.parsedSyncRulesCache = { parsed: this.sync_rules.parsed(options).
|
|
110
|
+
this.parsedSyncRulesCache = { parsed: this.sync_rules.parsed(options).hydratedSyncRules(), options };
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
return this.parsedSyncRulesCache!.parsed;
|
|
@@ -170,7 +169,7 @@ export class MongoSyncBucketStorage
|
|
|
170
169
|
await using batch = new MongoBucketBatch({
|
|
171
170
|
logger: options.logger,
|
|
172
171
|
db: this.db,
|
|
173
|
-
syncRules: this.sync_rules.parsed(options).
|
|
172
|
+
syncRules: this.sync_rules.parsed(options).hydratedSyncRules(),
|
|
174
173
|
groupId: this.group_id,
|
|
175
174
|
slotName: this.slot_name,
|
|
176
175
|
lastCheckpointLsn: checkpoint_lsn,
|
|
@@ -293,7 +292,10 @@ export class MongoSyncBucketStorage
|
|
|
293
292
|
return result!;
|
|
294
293
|
}
|
|
295
294
|
|
|
296
|
-
async getParameterSets(
|
|
295
|
+
async getParameterSets(
|
|
296
|
+
checkpoint: MongoReplicationCheckpoint,
|
|
297
|
+
lookups: ScopedParameterLookup[]
|
|
298
|
+
): Promise<SqliteJsonRow[]> {
|
|
297
299
|
return this.db.client.withSession({ snapshot: true }, async (session) => {
|
|
298
300
|
// Set the session's snapshot time to the checkpoint's snapshot time.
|
|
299
301
|
// An alternative would be to create the session when the checkpoint is created, but managing
|
|
@@ -1025,7 +1027,7 @@ class MongoReplicationCheckpoint implements ReplicationCheckpoint {
|
|
|
1025
1027
|
public snapshotTime: mongo.Timestamp
|
|
1026
1028
|
) {}
|
|
1027
1029
|
|
|
1028
|
-
async getParameterSets(lookups:
|
|
1030
|
+
async getParameterSets(lookups: ScopedParameterLookup[]): Promise<SqliteJsonRow[]> {
|
|
1029
1031
|
return this.storage.getParameterSets(this, lookups);
|
|
1030
1032
|
}
|
|
1031
1033
|
}
|
|
@@ -1034,7 +1036,7 @@ class EmptyReplicationCheckpoint implements ReplicationCheckpoint {
|
|
|
1034
1036
|
readonly checkpoint: InternalOpId = 0n;
|
|
1035
1037
|
readonly lsn: string | null = null;
|
|
1036
1038
|
|
|
1037
|
-
async getParameterSets(lookups:
|
|
1039
|
+
async getParameterSets(lookups: ScopedParameterLookup[]): Promise<SqliteJsonRow[]> {
|
|
1038
1040
|
return [];
|
|
1039
1041
|
}
|
|
1040
1042
|
}
|
|
@@ -38,15 +38,16 @@ export class MongoSyncRulesLock implements storage.ReplicationLock {
|
|
|
38
38
|
if (heldLock?.lock?.expires_at) {
|
|
39
39
|
throw new ServiceError(
|
|
40
40
|
ErrorCode.PSYNC_S1003,
|
|
41
|
-
`Sync rules
|
|
41
|
+
`Sync rules ${sync_rules.id} have been locked by another process for replication, expiring at ${heldLock.lock.expires_at.toISOString()}.`
|
|
42
42
|
);
|
|
43
43
|
} else {
|
|
44
44
|
throw new ServiceError(
|
|
45
45
|
ErrorCode.PSYNC_S1003,
|
|
46
|
-
`Sync rules
|
|
46
|
+
`Sync rules ${sync_rules.id} have been locked by another process for replication.`
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
logger.info(`Sync rules ${sync_rules.id} has been locked for replication with lock ID ${lockId}.`);
|
|
50
51
|
return new MongoSyncRulesLock(db, sync_rules.id, lockId);
|
|
51
52
|
}
|
|
52
53
|
|
package/src/utils/util.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as bson from 'bson';
|
|
2
2
|
import * as crypto from 'crypto';
|
|
3
3
|
import * as uuid from 'uuid';
|
|
4
|
-
|
|
5
4
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
6
5
|
import { storage, utils } from '@powersync/service-core';
|
|
7
6
|
import { ServiceAssertionError } from '@powersync/lib-services-framework';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createMongoClient } from '@powersync/lib-service-mongodb';
|
|
2
|
+
import { describe, test } from 'vitest';
|
|
3
|
+
import { env } from './env.js';
|
|
4
|
+
|
|
5
|
+
describe('MongoDB connection compression', () => {
|
|
6
|
+
for (let compressor of ['none', 'zlib', 'zstd', 'snappy']) {
|
|
7
|
+
test(`connection with compressors=${compressor}`, async () => {
|
|
8
|
+
const client = createMongoClient({
|
|
9
|
+
uri: env.MONGO_TEST_URL + '?compressors=' + compressor,
|
|
10
|
+
type: 'mongodb'
|
|
11
|
+
});
|
|
12
|
+
await client.connect();
|
|
13
|
+
await client.db('admin').command({ ping: 1 });
|
|
14
|
+
await client.close();
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
package/test/tsconfig.json
CHANGED
|
@@ -19,13 +19,7 @@
|
|
|
19
19
|
"path": "../"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
|
-
"path": "../../../packages/service-core
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"path": "../../../packages/service-core/"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"path": "../../../packages/service-core-tests/"
|
|
22
|
+
"path": "../../../packages/service-core-tests"
|
|
29
23
|
}
|
|
30
24
|
]
|
|
31
25
|
}
|