@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.
@@ -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 { ParameterLookup, SqliteJsonRow, SqlSyncRules } from '@powersync/service-sync-rules';
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: SqlSyncRules; options: storage.ParseSyncRulesOptions } | undefined;
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): SqlSyncRules {
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).sync_rules, 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).sync_rules,
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(checkpoint: MongoReplicationCheckpoint, lookups: ParameterLookup[]): Promise<SqliteJsonRow[]> {
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: ParameterLookup[]): Promise<SqliteJsonRow[]> {
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: ParameterLookup[]): Promise<SqliteJsonRow[]> {
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: ${sync_rules.id} have been locked by another process for replication, expiring at ${heldLock.lock.expires_at.toISOString()}.`
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: ${sync_rules.id} have been locked by another process for replication.`
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
+ });
@@ -19,13 +19,7 @@
19
19
  "path": "../"
20
20
  },
21
21
  {
22
- "path": "../../../packages/service-core/test"
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
  }