@powersync/service-core 0.0.0-dev-20240725112650 → 0.0.0-dev-20240918082156
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 +80 -2
- package/dist/api/RouteAPI.d.ts +68 -0
- package/dist/api/RouteAPI.js +2 -0
- package/dist/api/RouteAPI.js.map +1 -0
- package/dist/api/api-index.d.ts +1 -0
- package/dist/api/api-index.js +1 -0
- package/dist/api/api-index.js.map +1 -1
- package/dist/api/diagnostics.d.ts +4 -4
- package/dist/api/diagnostics.js +11 -65
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/api/schema.d.ts +3 -5
- package/dist/api/schema.js +9 -79
- package/dist/api/schema.js.map +1 -1
- package/dist/auth/KeyStore.d.ts +7 -4
- package/dist/auth/KeyStore.js +1 -1
- package/dist/auth/KeyStore.js.map +1 -1
- package/dist/auth/auth-index.d.ts +0 -1
- package/dist/auth/auth-index.js +0 -1
- package/dist/auth/auth-index.js.map +1 -1
- package/dist/entry/cli-entry.js +3 -2
- package/dist/entry/cli-entry.js.map +1 -1
- package/dist/entry/commands/compact-action.js +12 -8
- package/dist/entry/commands/compact-action.js.map +1 -1
- package/dist/entry/commands/migrate-action.js +4 -5
- package/dist/entry/commands/migrate-action.js.map +1 -1
- package/dist/entry/commands/teardown-action.js +2 -2
- package/dist/entry/commands/teardown-action.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/metrics/Metrics.d.ts +2 -2
- package/dist/metrics/Metrics.js +5 -13
- package/dist/metrics/Metrics.js.map +1 -1
- package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
- package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
- package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
- package/dist/migrations/migrations.d.ts +8 -0
- package/dist/migrations/migrations.js +19 -7
- package/dist/migrations/migrations.js.map +1 -1
- package/dist/modules/AbstractModule.d.ts +26 -0
- package/dist/modules/AbstractModule.js +11 -0
- package/dist/modules/AbstractModule.js.map +1 -0
- package/dist/modules/ModuleManager.d.ts +11 -0
- package/dist/modules/ModuleManager.js +32 -0
- package/dist/modules/ModuleManager.js.map +1 -0
- package/dist/modules/modules-index.d.ts +2 -0
- package/dist/modules/modules-index.js +3 -0
- package/dist/modules/modules-index.js.map +1 -0
- package/dist/replication/AbstractReplicationJob.d.ts +38 -0
- package/dist/replication/AbstractReplicationJob.js +51 -0
- package/dist/replication/AbstractReplicationJob.js.map +1 -0
- package/dist/replication/AbstractReplicator.d.ts +53 -0
- package/dist/replication/AbstractReplicator.js +187 -0
- package/dist/replication/AbstractReplicator.js.map +1 -0
- package/dist/replication/ErrorRateLimiter.d.ts +0 -9
- package/dist/replication/ErrorRateLimiter.js +1 -42
- package/dist/replication/ErrorRateLimiter.js.map +1 -1
- package/dist/replication/ReplicationEngine.d.ts +18 -0
- package/dist/replication/ReplicationEngine.js +41 -0
- package/dist/replication/ReplicationEngine.js.map +1 -0
- package/dist/replication/ReplicationModule.d.ts +39 -0
- package/dist/replication/ReplicationModule.js +65 -0
- package/dist/replication/ReplicationModule.js.map +1 -0
- package/dist/replication/replication-index.d.ts +4 -6
- package/dist/replication/replication-index.js +4 -6
- package/dist/replication/replication-index.js.map +1 -1
- package/dist/routes/RouterEngine.d.ts +42 -0
- package/dist/routes/RouterEngine.js +80 -0
- package/dist/routes/RouterEngine.js.map +1 -0
- package/dist/routes/auth.d.ts +2 -2
- package/dist/routes/auth.js +11 -11
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/configure-fastify.d.ts +30 -176
- package/dist/routes/configure-fastify.js +10 -11
- package/dist/routes/configure-fastify.js.map +1 -1
- package/dist/routes/configure-rsocket.d.ts +3 -3
- package/dist/routes/configure-rsocket.js +6 -5
- package/dist/routes/configure-rsocket.js.map +1 -1
- package/dist/routes/endpoints/admin.d.ts +0 -34
- package/dist/routes/endpoints/admin.js +48 -89
- package/dist/routes/endpoints/admin.js.map +1 -1
- package/dist/routes/endpoints/checkpointing.d.ts +56 -16
- package/dist/routes/endpoints/checkpointing.js +33 -12
- package/dist/routes/endpoints/checkpointing.js.map +1 -1
- package/dist/routes/endpoints/route-endpoints-index.d.ts +0 -1
- package/dist/routes/endpoints/route-endpoints-index.js +0 -1
- package/dist/routes/endpoints/route-endpoints-index.js.map +1 -1
- package/dist/routes/endpoints/socket-route.js +40 -25
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-rules.d.ts +1 -1
- package/dist/routes/endpoints/sync-rules.js +32 -23
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.d.ts +10 -0
- package/dist/routes/endpoints/sync-stream.js +13 -8
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/routes/router-socket.d.ts +1 -0
- package/dist/routes/router-socket.js +2 -1
- package/dist/routes/router-socket.js.map +1 -1
- package/dist/routes/router.d.ts +6 -2
- package/dist/routes/router.js.map +1 -1
- package/dist/routes/routes-index.d.ts +1 -0
- package/dist/routes/routes-index.js +1 -0
- package/dist/routes/routes-index.js.map +1 -1
- package/dist/runner/teardown.js +47 -76
- package/dist/runner/teardown.js.map +1 -1
- package/dist/storage/BucketStorage.d.ts +30 -19
- package/dist/storage/BucketStorage.js +0 -10
- package/dist/storage/BucketStorage.js.map +1 -1
- package/dist/storage/MongoBucketStorage.d.ts +4 -4
- package/dist/storage/MongoBucketStorage.js +19 -24
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/SourceEntity.d.ts +20 -0
- package/dist/storage/SourceEntity.js +2 -0
- package/dist/storage/SourceEntity.js.map +1 -0
- package/dist/storage/SourceTable.d.ts +4 -5
- package/dist/storage/SourceTable.js +3 -4
- package/dist/storage/SourceTable.js.map +1 -1
- package/dist/storage/StorageEngine.d.ts +24 -0
- package/dist/storage/StorageEngine.js +43 -0
- package/dist/storage/StorageEngine.js.map +1 -0
- package/dist/storage/StorageProvider.d.ts +21 -0
- package/dist/storage/StorageProvider.js +2 -0
- package/dist/storage/StorageProvider.js.map +1 -0
- package/dist/storage/mongo/MongoBucketBatch.d.ts +1 -1
- package/dist/storage/mongo/MongoBucketBatch.js +6 -7
- package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
- package/dist/storage/mongo/MongoCompactor.js +2 -1
- package/dist/storage/mongo/MongoCompactor.js.map +1 -1
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
- package/dist/storage/mongo/MongoStorageProvider.js +26 -0
- package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +7 -6
- package/dist/storage/mongo/MongoSyncBucketStorage.js +24 -15
- package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
- package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/mongo/OperationBatch.d.ts +7 -3
- package/dist/storage/mongo/OperationBatch.js +16 -7
- package/dist/storage/mongo/OperationBatch.js.map +1 -1
- package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
- package/dist/storage/mongo/PersistedBatch.js +2 -2
- package/dist/storage/mongo/PersistedBatch.js.map +1 -1
- package/dist/storage/mongo/models.d.ts +13 -4
- package/dist/storage/mongo/models.js.map +1 -1
- package/dist/storage/mongo/util.d.ts +12 -1
- package/dist/storage/mongo/util.js +50 -2
- package/dist/storage/mongo/util.js.map +1 -1
- package/dist/storage/storage-index.d.ts +5 -2
- package/dist/storage/storage-index.js +5 -2
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/sync/sync.d.ts +2 -1
- package/dist/sync/sync.js +36 -10
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/util.js.map +1 -1
- package/dist/system/ServiceContext.d.ts +37 -0
- package/dist/system/ServiceContext.js +48 -0
- package/dist/system/ServiceContext.js.map +1 -0
- package/dist/system/system-index.d.ts +1 -1
- package/dist/system/system-index.js +1 -1
- package/dist/system/system-index.js.map +1 -1
- package/dist/util/config/compound-config-collector.d.ts +9 -2
- package/dist/util/config/compound-config-collector.js +14 -23
- package/dist/util/config/compound-config-collector.js.map +1 -1
- package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
- package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
- package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
- package/dist/util/config/types.d.ts +6 -4
- package/dist/util/config/types.js.map +1 -1
- package/dist/util/config.d.ts +3 -4
- package/dist/util/config.js +5 -20
- package/dist/util/config.js.map +1 -1
- package/dist/util/protocol-types.d.ts +4 -0
- package/dist/util/protocol-types.js +5 -1
- package/dist/util/protocol-types.js.map +1 -1
- package/dist/util/util-index.d.ts +3 -6
- package/dist/util/util-index.js +3 -6
- package/dist/util/util-index.js.map +1 -1
- package/dist/util/utils.d.ts +10 -6
- package/dist/util/utils.js +45 -25
- package/dist/util/utils.js.map +1 -1
- package/package.json +5 -7
- package/src/api/RouteAPI.ts +78 -0
- package/src/api/api-index.ts +1 -0
- package/src/api/diagnostics.ts +16 -71
- package/src/api/schema.ts +13 -89
- package/src/auth/KeyStore.ts +9 -6
- package/src/auth/auth-index.ts +0 -1
- package/src/entry/cli-entry.ts +3 -2
- package/src/entry/commands/compact-action.ts +12 -9
- package/src/entry/commands/migrate-action.ts +5 -8
- package/src/entry/commands/teardown-action.ts +2 -2
- package/src/index.ts +5 -2
- package/src/metrics/Metrics.ts +6 -16
- package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
- package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
- package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
- package/src/migrations/migrations.ts +24 -8
- package/src/modules/AbstractModule.ts +37 -0
- package/src/modules/ModuleManager.ts +34 -0
- package/src/modules/modules-index.ts +2 -0
- package/src/replication/AbstractReplicationJob.ts +79 -0
- package/src/replication/AbstractReplicator.ts +227 -0
- package/src/replication/ErrorRateLimiter.ts +0 -44
- package/src/replication/ReplicationEngine.ts +43 -0
- package/src/replication/ReplicationModule.ts +101 -0
- package/src/replication/replication-index.ts +4 -6
- package/src/routes/RouterEngine.ts +120 -0
- package/src/routes/auth.ts +21 -12
- package/src/routes/configure-fastify.ts +13 -14
- package/src/routes/configure-rsocket.ts +9 -8
- package/src/routes/endpoints/admin.ts +74 -100
- package/src/routes/endpoints/checkpointing.ts +46 -12
- package/src/routes/endpoints/route-endpoints-index.ts +0 -1
- package/src/routes/endpoints/socket-route.ts +44 -27
- package/src/routes/endpoints/sync-rules.ts +41 -25
- package/src/routes/endpoints/sync-stream.ts +13 -8
- package/src/routes/router-socket.ts +2 -1
- package/src/routes/router.ts +6 -3
- package/src/routes/routes-index.ts +1 -0
- package/src/runner/teardown.ts +50 -88
- package/src/storage/BucketStorage.ts +38 -25
- package/src/storage/MongoBucketStorage.ts +23 -26
- package/src/storage/SourceEntity.ts +22 -0
- package/src/storage/SourceTable.ts +4 -6
- package/src/storage/StorageEngine.ts +55 -0
- package/src/storage/StorageProvider.ts +27 -0
- package/src/storage/mongo/MongoBucketBatch.ts +8 -8
- package/src/storage/mongo/MongoCompactor.ts +2 -1
- package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +3 -3
- package/src/storage/mongo/MongoStorageProvider.ts +31 -0
- package/src/storage/mongo/MongoSyncBucketStorage.ts +39 -20
- package/src/storage/mongo/MongoSyncRulesLock.ts +1 -1
- package/src/storage/mongo/OperationBatch.ts +18 -11
- package/src/storage/mongo/PersistedBatch.ts +6 -5
- package/src/storage/mongo/models.ts +13 -4
- package/src/storage/mongo/util.ts +49 -4
- package/src/storage/storage-index.ts +5 -2
- package/src/sync/sync.ts +46 -11
- package/src/sync/util.ts +0 -1
- package/src/system/ServiceContext.ts +68 -0
- package/src/system/system-index.ts +1 -1
- package/src/util/config/compound-config-collector.ts +30 -31
- package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
- package/src/util/config/types.ts +6 -5
- package/src/util/config.ts +6 -23
- package/src/util/protocol-types.ts +6 -1
- package/src/util/util-index.ts +3 -6
- package/src/util/utils.ts +55 -39
- package/test/src/__snapshots__/sync.test.ts.snap +7 -7
- package/test/src/auth.test.ts +7 -7
- package/test/src/broadcast_iterable.test.ts +1 -1
- package/test/src/checksum_cache.test.ts +3 -3
- package/test/src/compacting.test.ts +26 -17
- package/test/src/data_storage.test.ts +258 -146
- package/test/src/env.ts +1 -3
- package/test/src/merge_iterable.test.ts +1 -6
- package/test/src/setup.ts +1 -1
- package/test/src/stream_utils.ts +42 -0
- package/test/src/sync.test.ts +52 -31
- package/test/src/util.ts +48 -51
- package/test/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
- package/dist/auth/SupabaseKeyCollector.js +0 -61
- package/dist/auth/SupabaseKeyCollector.js.map +0 -1
- package/dist/replication/PgRelation.d.ts +0 -16
- package/dist/replication/PgRelation.js +0 -26
- package/dist/replication/PgRelation.js.map +0 -1
- package/dist/replication/WalConnection.d.ts +0 -34
- package/dist/replication/WalConnection.js +0 -190
- package/dist/replication/WalConnection.js.map +0 -1
- package/dist/replication/WalStream.d.ts +0 -57
- package/dist/replication/WalStream.js +0 -515
- package/dist/replication/WalStream.js.map +0 -1
- package/dist/replication/WalStreamManager.d.ts +0 -30
- package/dist/replication/WalStreamManager.js +0 -198
- package/dist/replication/WalStreamManager.js.map +0 -1
- package/dist/replication/WalStreamRunner.d.ts +0 -38
- package/dist/replication/WalStreamRunner.js +0 -155
- package/dist/replication/WalStreamRunner.js.map +0 -1
- package/dist/replication/util.d.ts +0 -9
- package/dist/replication/util.js +0 -62
- package/dist/replication/util.js.map +0 -1
- package/dist/routes/endpoints/dev.d.ts +0 -312
- package/dist/routes/endpoints/dev.js +0 -172
- package/dist/routes/endpoints/dev.js.map +0 -1
- package/dist/system/CorePowerSyncSystem.d.ts +0 -23
- package/dist/system/CorePowerSyncSystem.js +0 -52
- package/dist/system/CorePowerSyncSystem.js.map +0 -1
- package/dist/util/PgManager.d.ts +0 -24
- package/dist/util/PgManager.js +0 -55
- package/dist/util/PgManager.js.map +0 -1
- package/dist/util/migration_lib.d.ts +0 -11
- package/dist/util/migration_lib.js +0 -64
- package/dist/util/migration_lib.js.map +0 -1
- package/dist/util/pgwire_utils.d.ts +0 -24
- package/dist/util/pgwire_utils.js +0 -117
- package/dist/util/pgwire_utils.js.map +0 -1
- package/dist/util/populate_test_data.d.ts +0 -8
- package/dist/util/populate_test_data.js +0 -65
- package/dist/util/populate_test_data.js.map +0 -1
- package/src/auth/SupabaseKeyCollector.ts +0 -67
- package/src/replication/PgRelation.ts +0 -42
- package/src/replication/WalConnection.ts +0 -227
- package/src/replication/WalStream.ts +0 -624
- package/src/replication/WalStreamManager.ts +0 -213
- package/src/replication/WalStreamRunner.ts +0 -180
- package/src/replication/util.ts +0 -76
- package/src/routes/endpoints/dev.ts +0 -199
- package/src/system/CorePowerSyncSystem.ts +0 -64
- package/src/util/PgManager.ts +0 -64
- package/src/util/migration_lib.ts +0 -79
- package/src/util/pgwire_utils.ts +0 -139
- package/src/util/populate_test_data.ts +0 -78
- package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
- package/test/src/large_batch.test.ts +0 -194
- package/test/src/pg_test.test.ts +0 -450
- package/test/src/schema_changes.test.ts +0 -545
- package/test/src/slow_tests.test.ts +0 -338
- package/test/src/validation.test.ts +0 -63
- package/test/src/wal_stream.test.ts +0 -319
- package/test/src/wal_stream_utils.ts +0 -156
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import * as mongo from 'mongodb';
|
|
2
|
-
import * as timers from 'timers/promises';
|
|
3
|
-
import { LRUCache } from 'lru-cache/min';
|
|
4
1
|
import { SqlSyncRules } from '@powersync/service-sync-rules';
|
|
5
2
|
import { wrapWithAbort } from 'ix/asynciterable/operators/withabort.js';
|
|
3
|
+
import { LRUCache } from 'lru-cache/min';
|
|
4
|
+
import * as mongo from 'mongodb';
|
|
5
|
+
import * as timers from 'timers/promises';
|
|
6
6
|
|
|
7
|
-
import * as
|
|
7
|
+
import * as locks from '../locks/locks-index.js';
|
|
8
8
|
import * as sync from '../sync/sync-index.js';
|
|
9
9
|
import * as util from '../util/util-index.js';
|
|
10
|
-
import * as locks from '../locks/locks-index.js';
|
|
11
10
|
|
|
11
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
12
|
+
import { v4 as uuid } from 'uuid';
|
|
12
13
|
import {
|
|
13
14
|
ActiveCheckpoint,
|
|
14
15
|
BucketStorageFactory,
|
|
16
|
+
ParseSyncRulesOptions,
|
|
15
17
|
PersistedSyncRules,
|
|
16
18
|
PersistedSyncRulesContent,
|
|
17
19
|
StorageMetrics,
|
|
@@ -23,14 +25,13 @@ import { MongoSyncBucketStorage } from './mongo/MongoSyncBucketStorage.js';
|
|
|
23
25
|
import { PowerSyncMongo, PowerSyncMongoOptions } from './mongo/db.js';
|
|
24
26
|
import { SyncRuleDocument, SyncRuleState } from './mongo/models.js';
|
|
25
27
|
import { generateSlotName } from './mongo/util.js';
|
|
26
|
-
import { v4 as uuid } from 'uuid';
|
|
27
|
-
import { logger } from '@powersync/lib-services-framework';
|
|
28
28
|
|
|
29
29
|
export interface MongoBucketStorageOptions extends PowerSyncMongoOptions {}
|
|
30
30
|
|
|
31
31
|
export class MongoBucketStorage implements BucketStorageFactory {
|
|
32
32
|
private readonly client: mongo.MongoClient;
|
|
33
33
|
private readonly session: mongo.ClientSession;
|
|
34
|
+
// TODO: This is still Postgres specific and needs to be reworked
|
|
34
35
|
public readonly slot_name_prefix: string;
|
|
35
36
|
|
|
36
37
|
private readonly storageCache = new LRUCache<number, MongoSyncBucketStorage>({
|
|
@@ -47,8 +48,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
|
|
|
47
48
|
return undefined;
|
|
48
49
|
}
|
|
49
50
|
const rules = new MongoPersistedSyncRulesContent(this.db, doc2);
|
|
50
|
-
|
|
51
|
-
return storage;
|
|
51
|
+
return this.getInstance(rules);
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
|
|
@@ -61,12 +61,12 @@ export class MongoBucketStorage implements BucketStorageFactory {
|
|
|
61
61
|
this.slot_name_prefix = options.slot_name_prefix;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
getInstance(options:
|
|
65
|
-
let { id,
|
|
64
|
+
getInstance(options: PersistedSyncRulesContent): MongoSyncBucketStorage {
|
|
65
|
+
let { id, slot_name } = options;
|
|
66
66
|
if ((typeof id as any) == 'bigint') {
|
|
67
67
|
id = Number(id);
|
|
68
68
|
}
|
|
69
|
-
return new MongoSyncBucketStorage(this, id,
|
|
69
|
+
return new MongoSyncBucketStorage(this, id, options, slot_name);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
async configureSyncRules(sync_rules: string, options?: { lock?: boolean }) {
|
|
@@ -136,7 +136,12 @@ export class MongoBucketStorage implements BucketStorageFactory {
|
|
|
136
136
|
|
|
137
137
|
async updateSyncRules(options: UpdateSyncRulesOptions): Promise<MongoPersistedSyncRulesContent> {
|
|
138
138
|
// Parse and validate before applying any changes
|
|
139
|
-
const parsed = SqlSyncRules.fromYaml(options.content
|
|
139
|
+
const parsed = SqlSyncRules.fromYaml(options.content, {
|
|
140
|
+
// No schema-based validation at this point
|
|
141
|
+
schema: undefined,
|
|
142
|
+
defaultSchema: 'not_applicable', // Not needed for validation
|
|
143
|
+
throwOnError: true
|
|
144
|
+
});
|
|
140
145
|
|
|
141
146
|
let rules: MongoPersistedSyncRulesContent | undefined = undefined;
|
|
142
147
|
|
|
@@ -204,9 +209,9 @@ export class MongoBucketStorage implements BucketStorageFactory {
|
|
|
204
209
|
return new MongoPersistedSyncRulesContent(this.db, doc);
|
|
205
210
|
}
|
|
206
211
|
|
|
207
|
-
async getActiveSyncRules(): Promise<PersistedSyncRules | null> {
|
|
212
|
+
async getActiveSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null> {
|
|
208
213
|
const content = await this.getActiveSyncRulesContent();
|
|
209
|
-
return content?.parsed() ?? null;
|
|
214
|
+
return content?.parsed(options) ?? null;
|
|
210
215
|
}
|
|
211
216
|
|
|
212
217
|
async getNextSyncRulesContent(): Promise<MongoPersistedSyncRulesContent | null> {
|
|
@@ -223,9 +228,9 @@ export class MongoBucketStorage implements BucketStorageFactory {
|
|
|
223
228
|
return new MongoPersistedSyncRulesContent(this.db, doc);
|
|
224
229
|
}
|
|
225
230
|
|
|
226
|
-
async getNextSyncRules(): Promise<PersistedSyncRules | null> {
|
|
231
|
+
async getNextSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null> {
|
|
227
232
|
const content = await this.getNextSyncRulesContent();
|
|
228
|
-
return content?.parsed() ?? null;
|
|
233
|
+
return content?.parsed(options) ?? null;
|
|
229
234
|
}
|
|
230
235
|
|
|
231
236
|
async getReplicatingSyncRules(): Promise<PersistedSyncRulesContent[]> {
|
|
@@ -294,14 +299,6 @@ export class MongoBucketStorage implements BucketStorageFactory {
|
|
|
294
299
|
}
|
|
295
300
|
|
|
296
301
|
async getStorageMetrics(): Promise<StorageMetrics> {
|
|
297
|
-
const active_sync_rules = await this.getActiveSyncRules();
|
|
298
|
-
if (active_sync_rules == null) {
|
|
299
|
-
return {
|
|
300
|
-
operations_size_bytes: 0,
|
|
301
|
-
parameters_size_bytes: 0,
|
|
302
|
-
replication_size_bytes: 0
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
302
|
const operations_aggregate = await this.db.bucket_data
|
|
306
303
|
|
|
307
304
|
.aggregate([
|
|
@@ -370,7 +367,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
|
|
|
370
367
|
private makeActiveCheckpoint(doc: SyncRuleDocument | null) {
|
|
371
368
|
return {
|
|
372
369
|
checkpoint: util.timestampToOpId(doc?.last_checkpoint ?? 0n),
|
|
373
|
-
lsn: doc?.last_checkpoint_lsn ??
|
|
370
|
+
lsn: doc?.last_checkpoint_lsn ?? null,
|
|
374
371
|
hasSyncRules() {
|
|
375
372
|
return doc != null;
|
|
376
373
|
},
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ColumnDescriptor {
|
|
2
|
+
name: string;
|
|
3
|
+
/**
|
|
4
|
+
* The type of the column ie VARCHAR, INT, etc
|
|
5
|
+
*/
|
|
6
|
+
type?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Some data sources have a type id that can be used to identify the type of the column
|
|
9
|
+
*/
|
|
10
|
+
typeId?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// TODO: This needs to be consolidated with SourceTable into something new.
|
|
14
|
+
export interface SourceEntityDescriptor {
|
|
15
|
+
/**
|
|
16
|
+
* The internal id of the data source structure in the database
|
|
17
|
+
*/
|
|
18
|
+
objectId: number | string;
|
|
19
|
+
schema: string;
|
|
20
|
+
name: string;
|
|
21
|
+
replicationColumns: ColumnDescriptor[];
|
|
22
|
+
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import * as replication from '../replication/replication-index.js';
|
|
1
|
+
import { DEFAULT_TAG } from '@powersync/service-sync-rules';
|
|
4
2
|
import * as util from '../util/util-index.js';
|
|
3
|
+
import { ColumnDescriptor } from './SourceEntity.js';
|
|
5
4
|
|
|
6
5
|
export class SourceTable {
|
|
7
|
-
static readonly DEFAULT_SCHEMA = DEFAULT_SCHEMA;
|
|
8
6
|
static readonly DEFAULT_TAG = DEFAULT_TAG;
|
|
9
7
|
|
|
10
8
|
/**
|
|
@@ -28,11 +26,11 @@ export class SourceTable {
|
|
|
28
26
|
constructor(
|
|
29
27
|
public readonly id: any,
|
|
30
28
|
public readonly connectionTag: string,
|
|
31
|
-
public readonly
|
|
29
|
+
public readonly objectId: number | string,
|
|
32
30
|
public readonly schema: string,
|
|
33
31
|
public readonly table: string,
|
|
34
32
|
|
|
35
|
-
public readonly replicaIdColumns:
|
|
33
|
+
public readonly replicaIdColumns: ColumnDescriptor[],
|
|
36
34
|
public readonly snapshotComplete: boolean
|
|
37
35
|
) {}
|
|
38
36
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ResolvedPowerSyncConfig } from '../util/util-index.js';
|
|
2
|
+
import { BucketStorageFactory } from './BucketStorage.js';
|
|
3
|
+
import { BucketStorageProvider, ActiveStorage } from './StorageProvider.js';
|
|
4
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
5
|
+
|
|
6
|
+
export type StorageEngineOptions = {
|
|
7
|
+
configuration: ResolvedPowerSyncConfig;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class StorageEngine {
|
|
11
|
+
// TODO: This will need to revisited when we actually support multiple storage providers.
|
|
12
|
+
private storageProviders: Map<string, BucketStorageProvider> = new Map();
|
|
13
|
+
private currentActiveStorage: ActiveStorage | null = null;
|
|
14
|
+
|
|
15
|
+
constructor(private options: StorageEngineOptions) {}
|
|
16
|
+
|
|
17
|
+
get activeBucketStorage(): BucketStorageFactory {
|
|
18
|
+
return this.activeStorage.storage;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get activeStorage(): ActiveStorage {
|
|
22
|
+
if (!this.currentActiveStorage) {
|
|
23
|
+
throw new Error(`No storage provider has been initialized yet.`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return this.currentActiveStorage;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Register a provider which generates a {@link BucketStorageFactory}
|
|
31
|
+
* given the matching config specified in the loaded {@link ResolvedPowerSyncConfig}
|
|
32
|
+
*/
|
|
33
|
+
registerProvider(provider: BucketStorageProvider) {
|
|
34
|
+
this.storageProviders.set(provider.type, provider);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public async start(): Promise<void> {
|
|
38
|
+
logger.info('Starting Storage Engine...');
|
|
39
|
+
const { configuration } = this.options;
|
|
40
|
+
this.currentActiveStorage = await this.storageProviders.get(configuration.storage.type)!.getStorage({
|
|
41
|
+
resolvedConfig: configuration
|
|
42
|
+
});
|
|
43
|
+
logger.info(`Successfully activated storage: ${configuration.storage.type}.`);
|
|
44
|
+
logger.info('Successfully started Storage Engine.');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Shutdown the storage engine, safely shutting down any activated storage providers.
|
|
49
|
+
*/
|
|
50
|
+
public async shutDown(): Promise<void> {
|
|
51
|
+
logger.info('Shutting down Storage Engine...');
|
|
52
|
+
await this.currentActiveStorage?.shutDown();
|
|
53
|
+
logger.info('Successfully shut down Storage Engine.');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BucketStorageFactory } from './BucketStorage.js';
|
|
2
|
+
import * as util from '../util/util-index.js';
|
|
3
|
+
|
|
4
|
+
export interface ActiveStorage {
|
|
5
|
+
storage: BucketStorageFactory;
|
|
6
|
+
shutDown(): Promise<void>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Tear down / drop the storage permanently
|
|
10
|
+
*/
|
|
11
|
+
tearDown(): Promise<boolean>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface GetStorageOptions {
|
|
15
|
+
// TODO: This should just be the storage config. Update once the slot name prefix coupling has been removed from the storage
|
|
16
|
+
resolvedConfig: util.ResolvedPowerSyncConfig;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface BucketStorageProvider {
|
|
20
|
+
/**
|
|
21
|
+
* The storage type that this provider provides.
|
|
22
|
+
* The type should match the `type` field in the config.
|
|
23
|
+
*/
|
|
24
|
+
type: string;
|
|
25
|
+
|
|
26
|
+
getStorage(options: GetStorageOptions): Promise<ActiveStorage>;
|
|
27
|
+
}
|
|
@@ -2,9 +2,8 @@ import { SqliteRow, SqlSyncRules } from '@powersync/service-sync-rules';
|
|
|
2
2
|
import * as bson from 'bson';
|
|
3
3
|
import * as mongo from 'mongodb';
|
|
4
4
|
|
|
5
|
-
import * as util from '../../util/util-index.js';
|
|
6
|
-
import * as replication from '../../replication/replication-index.js';
|
|
7
5
|
import { container, errors, logger } from '@powersync/lib-services-framework';
|
|
6
|
+
import * as util from '../../util/util-index.js';
|
|
8
7
|
import { BucketStorageBatch, FlushedResult, mergeToast, SaveOptions } from '../BucketStorage.js';
|
|
9
8
|
import { SourceTable } from '../SourceTable.js';
|
|
10
9
|
import { PowerSyncMongo } from './db.js';
|
|
@@ -12,7 +11,7 @@ import { CurrentBucket, CurrentDataDocument, SourceKey } from './models.js';
|
|
|
12
11
|
import { MongoIdSequence } from './MongoIdSequence.js';
|
|
13
12
|
import { cacheKey, OperationBatch, RecordOperation } from './OperationBatch.js';
|
|
14
13
|
import { PersistedBatch } from './PersistedBatch.js';
|
|
15
|
-
import { BSON_DESERIALIZE_OPTIONS, idPrefixFilter, serializeLookup } from './util.js';
|
|
14
|
+
import { BSON_DESERIALIZE_OPTIONS, idPrefixFilter, replicaIdEquals, serializeLookup } from './util.js';
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* 15MB
|
|
@@ -25,6 +24,7 @@ const MAX_ROW_SIZE = 15 * 1024 * 1024;
|
|
|
25
24
|
//
|
|
26
25
|
// In the future, we can investigate allowing multiple replication streams operating independently.
|
|
27
26
|
const replicationMutex = new util.Mutex();
|
|
27
|
+
|
|
28
28
|
export class MongoBucketBatch implements BucketStorageBatch {
|
|
29
29
|
private readonly client: mongo.MongoClient;
|
|
30
30
|
public readonly db: PowerSyncMongo;
|
|
@@ -61,7 +61,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
|
|
|
61
61
|
group_id: number,
|
|
62
62
|
slot_name: string,
|
|
63
63
|
last_checkpoint_lsn: string | null,
|
|
64
|
-
no_checkpoint_before_lsn: string
|
|
64
|
+
no_checkpoint_before_lsn: string
|
|
65
65
|
) {
|
|
66
66
|
this.db = db;
|
|
67
67
|
this.client = db.client;
|
|
@@ -70,7 +70,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
|
|
|
70
70
|
this.slot_name = slot_name;
|
|
71
71
|
this.session = this.client.startSession();
|
|
72
72
|
this.last_checkpoint_lsn = last_checkpoint_lsn;
|
|
73
|
-
this.no_checkpoint_before_lsn = no_checkpoint_before_lsn
|
|
73
|
+
this.no_checkpoint_before_lsn = no_checkpoint_before_lsn;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
async flush(): Promise<FlushedResult | null> {
|
|
@@ -301,7 +301,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
|
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
// 2. Save bucket data
|
|
304
|
-
if (beforeId != null && (afterId == null || !beforeId
|
|
304
|
+
if (beforeId != null && (afterId == null || !replicaIdEquals(beforeId, afterId))) {
|
|
305
305
|
// Source ID updated
|
|
306
306
|
if (sourceTable.syncData) {
|
|
307
307
|
// Delete old record
|
|
@@ -431,7 +431,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
|
|
|
431
431
|
};
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
-
if (afterId == null || !beforeId
|
|
434
|
+
if (afterId == null || !replicaIdEquals(beforeId, afterId)) {
|
|
435
435
|
// Either a delete (afterId == null), or replaced the old replication id
|
|
436
436
|
batch.deleteCurrentData(before_key);
|
|
437
437
|
}
|
|
@@ -743,7 +743,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
|
|
|
743
743
|
const copy = new SourceTable(
|
|
744
744
|
table.id,
|
|
745
745
|
table.connectionTag,
|
|
746
|
-
table.
|
|
746
|
+
table.objectId,
|
|
747
747
|
table.schema,
|
|
748
748
|
table.table,
|
|
749
749
|
table.replicaIdColumns,
|
|
@@ -4,6 +4,7 @@ import { addChecksums } from '../../util/utils.js';
|
|
|
4
4
|
import { PowerSyncMongo } from './db.js';
|
|
5
5
|
import { BucketDataDocument, BucketDataKey } from './models.js';
|
|
6
6
|
import { CompactOptions } from '../BucketStorage.js';
|
|
7
|
+
import { cacheKey } from './OperationBatch.js';
|
|
7
8
|
|
|
8
9
|
interface CurrentBucketState {
|
|
9
10
|
/** Bucket name */
|
|
@@ -168,7 +169,7 @@ export class MongoCompactor {
|
|
|
168
169
|
let isPersistentPut = doc.op == 'PUT';
|
|
169
170
|
|
|
170
171
|
if (doc.op == 'REMOVE' || doc.op == 'PUT') {
|
|
171
|
-
const key = `${doc.table}/${doc.row_id}/${doc.source_table
|
|
172
|
+
const key = `${doc.table}/${doc.row_id}/${cacheKey(doc.source_table!, doc.source_key!)}`;
|
|
172
173
|
const targetOp = currentState.seen.get(key);
|
|
173
174
|
if (targetOp) {
|
|
174
175
|
// Will convert to MOVE, so don't count as PUT
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SqlSyncRules } from '@powersync/service-sync-rules';
|
|
2
2
|
import * as mongo from 'mongodb';
|
|
3
3
|
|
|
4
|
-
import { PersistedSyncRulesContent } from '../BucketStorage.js';
|
|
4
|
+
import { ParseSyncRulesOptions, PersistedSyncRulesContent } from '../BucketStorage.js';
|
|
5
5
|
import { MongoPersistedSyncRules } from './MongoPersistedSyncRules.js';
|
|
6
6
|
import { MongoSyncRulesLock } from './MongoSyncRulesLock.js';
|
|
7
7
|
import { PowerSyncMongo } from './db.js';
|
|
@@ -30,10 +30,10 @@ export class MongoPersistedSyncRulesContent implements PersistedSyncRulesContent
|
|
|
30
30
|
this.last_keepalive_ts = doc.last_keepalive_ts;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
parsed() {
|
|
33
|
+
parsed(options: ParseSyncRulesOptions) {
|
|
34
34
|
return new MongoPersistedSyncRules(
|
|
35
35
|
this.id,
|
|
36
|
-
SqlSyncRules.fromYaml(this.sync_rules_content),
|
|
36
|
+
SqlSyncRules.fromYaml(this.sync_rules_content, options),
|
|
37
37
|
this.last_checkpoint_lsn,
|
|
38
38
|
this.slot_name
|
|
39
39
|
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as db from '../../db/db-index.js';
|
|
2
|
+
import { MongoBucketStorage } from '../MongoBucketStorage.js';
|
|
3
|
+
import { BucketStorageProvider, ActiveStorage, GetStorageOptions } from '../StorageProvider.js';
|
|
4
|
+
import { PowerSyncMongo } from './db.js';
|
|
5
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
6
|
+
|
|
7
|
+
export class MongoStorageProvider implements BucketStorageProvider {
|
|
8
|
+
get type() {
|
|
9
|
+
return 'mongodb';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async getStorage(options: GetStorageOptions): Promise<ActiveStorage> {
|
|
13
|
+
const { resolvedConfig } = options;
|
|
14
|
+
|
|
15
|
+
const client = db.mongo.createMongoClient(resolvedConfig.storage);
|
|
16
|
+
|
|
17
|
+
const database = new PowerSyncMongo(client, { database: resolvedConfig.storage.database });
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
storage: new MongoBucketStorage(database, {
|
|
21
|
+
// TODO currently need the entire resolved config due to this
|
|
22
|
+
slot_name_prefix: resolvedConfig.slot_name_prefix
|
|
23
|
+
}),
|
|
24
|
+
shutDown: () => client.close(),
|
|
25
|
+
tearDown: () => {
|
|
26
|
+
logger.info(`Tearing down storage: ${database.db.namespace}...`);
|
|
27
|
+
return database.db.dropDatabase();
|
|
28
|
+
}
|
|
29
|
+
} satisfies ActiveStorage;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -3,7 +3,6 @@ import * as bson from 'bson';
|
|
|
3
3
|
import * as mongo from 'mongodb';
|
|
4
4
|
|
|
5
5
|
import * as db from '../../db/db-index.js';
|
|
6
|
-
import * as replication from '../../replication/WalStream.js';
|
|
7
6
|
import * as util from '../../util/util-index.js';
|
|
8
7
|
import {
|
|
9
8
|
BucketDataBatchOptions,
|
|
@@ -12,11 +11,16 @@ import {
|
|
|
12
11
|
DEFAULT_DOCUMENT_BATCH_LIMIT,
|
|
13
12
|
DEFAULT_DOCUMENT_CHUNK_LIMIT_BYTES,
|
|
14
13
|
FlushedResult,
|
|
14
|
+
ParseSyncRulesOptions,
|
|
15
|
+
PersistedSyncRules,
|
|
16
|
+
PersistedSyncRulesContent,
|
|
15
17
|
ResolveTableOptions,
|
|
16
18
|
ResolveTableResult,
|
|
19
|
+
StartBatchOptions,
|
|
17
20
|
SyncBucketDataBatch,
|
|
18
21
|
SyncRulesBucketStorage,
|
|
19
|
-
SyncRuleStatus
|
|
22
|
+
SyncRuleStatus,
|
|
23
|
+
TerminateOptions
|
|
20
24
|
} from '../BucketStorage.js';
|
|
21
25
|
import { ChecksumCache, FetchPartialBucketChecksum } from '../ChecksumCache.js';
|
|
22
26
|
import { MongoBucketStorage } from '../MongoBucketStorage.js';
|
|
@@ -35,29 +39,38 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
35
39
|
}
|
|
36
40
|
});
|
|
37
41
|
|
|
42
|
+
private parsedSyncRulesCache: SqlSyncRules | undefined;
|
|
43
|
+
|
|
38
44
|
constructor(
|
|
39
45
|
public readonly factory: MongoBucketStorage,
|
|
40
46
|
public readonly group_id: number,
|
|
41
|
-
|
|
47
|
+
private readonly sync_rules: PersistedSyncRulesContent,
|
|
42
48
|
public readonly slot_name: string
|
|
43
49
|
) {
|
|
44
50
|
this.db = factory.db;
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
getParsedSyncRules(options: ParseSyncRulesOptions): SqlSyncRules {
|
|
54
|
+
this.parsedSyncRulesCache ??= this.sync_rules.parsed(options).sync_rules;
|
|
55
|
+
return this.parsedSyncRulesCache;
|
|
56
|
+
}
|
|
57
|
+
|
|
47
58
|
async getCheckpoint() {
|
|
48
59
|
const doc = await this.db.sync_rules.findOne(
|
|
49
60
|
{ _id: this.group_id },
|
|
50
61
|
{
|
|
51
|
-
projection: { last_checkpoint: 1
|
|
62
|
+
projection: { last_checkpoint: 1 }
|
|
52
63
|
}
|
|
53
64
|
);
|
|
54
65
|
return {
|
|
55
|
-
checkpoint: util.timestampToOpId(doc?.last_checkpoint ?? 0n)
|
|
56
|
-
lsn: doc?.last_checkpoint_lsn ?? replication.ZERO_LSN
|
|
66
|
+
checkpoint: util.timestampToOpId(doc?.last_checkpoint ?? 0n)
|
|
57
67
|
};
|
|
58
68
|
}
|
|
59
69
|
|
|
60
|
-
async startBatch(
|
|
70
|
+
async startBatch(
|
|
71
|
+
options: StartBatchOptions,
|
|
72
|
+
callback: (batch: BucketStorageBatch) => Promise<void>
|
|
73
|
+
): Promise<FlushedResult | null> {
|
|
61
74
|
const doc = await this.db.sync_rules.findOne(
|
|
62
75
|
{
|
|
63
76
|
_id: this.group_id
|
|
@@ -68,11 +81,11 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
68
81
|
|
|
69
82
|
const batch = new MongoBucketBatch(
|
|
70
83
|
this.db,
|
|
71
|
-
this.sync_rules,
|
|
84
|
+
this.sync_rules.parsed(options).sync_rules,
|
|
72
85
|
this.group_id,
|
|
73
86
|
this.slot_name,
|
|
74
87
|
checkpoint_lsn,
|
|
75
|
-
doc?.no_checkpoint_before ??
|
|
88
|
+
doc?.no_checkpoint_before ?? options.zeroLSN
|
|
76
89
|
);
|
|
77
90
|
try {
|
|
78
91
|
await callback(batch);
|
|
@@ -90,11 +103,15 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
async resolveTable(options: ResolveTableOptions): Promise<ResolveTableResult> {
|
|
93
|
-
const { group_id, connection_id, connection_tag,
|
|
106
|
+
const { group_id, connection_id, connection_tag, entity_descriptor } = options;
|
|
94
107
|
|
|
95
|
-
const { schema, name: table,
|
|
108
|
+
const { schema, name: table, objectId, replicationColumns } = entity_descriptor;
|
|
96
109
|
|
|
97
|
-
const columns = replicationColumns.map((column) => ({
|
|
110
|
+
const columns = replicationColumns.map((column) => ({
|
|
111
|
+
name: column.name,
|
|
112
|
+
type: column.type,
|
|
113
|
+
type_oid: column.typeId
|
|
114
|
+
}));
|
|
98
115
|
let result: ResolveTableResult | null = null;
|
|
99
116
|
await this.db.client.withSession(async (session) => {
|
|
100
117
|
const col = this.db.source_tables;
|
|
@@ -102,7 +119,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
102
119
|
{
|
|
103
120
|
group_id: group_id,
|
|
104
121
|
connection_id: connection_id,
|
|
105
|
-
relation_id:
|
|
122
|
+
relation_id: objectId,
|
|
106
123
|
schema_name: schema,
|
|
107
124
|
table_name: table,
|
|
108
125
|
replica_id_columns2: columns
|
|
@@ -114,7 +131,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
114
131
|
_id: new bson.ObjectId(),
|
|
115
132
|
group_id: group_id,
|
|
116
133
|
connection_id: connection_id,
|
|
117
|
-
relation_id:
|
|
134
|
+
relation_id: objectId,
|
|
118
135
|
schema_name: schema,
|
|
119
136
|
table_name: table,
|
|
120
137
|
replica_id_columns: null,
|
|
@@ -127,7 +144,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
127
144
|
const sourceTable = new SourceTable(
|
|
128
145
|
doc._id,
|
|
129
146
|
connection_tag,
|
|
130
|
-
|
|
147
|
+
objectId,
|
|
131
148
|
schema,
|
|
132
149
|
table,
|
|
133
150
|
replicationColumns,
|
|
@@ -142,7 +159,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
142
159
|
group_id: group_id,
|
|
143
160
|
connection_id: connection_id,
|
|
144
161
|
_id: { $ne: doc._id },
|
|
145
|
-
$or: [{ relation_id:
|
|
162
|
+
$or: [{ relation_id: objectId }, { schema_name: schema, table_name: table }]
|
|
146
163
|
},
|
|
147
164
|
{ session }
|
|
148
165
|
)
|
|
@@ -157,7 +174,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
157
174
|
doc.relation_id ?? 0,
|
|
158
175
|
doc.schema_name,
|
|
159
176
|
doc.table_name,
|
|
160
|
-
doc.replica_id_columns2?.map((c) => ({ name: c.name, typeOid: c.type_oid })) ?? [],
|
|
177
|
+
doc.replica_id_columns2?.map((c) => ({ name: c.name, typeOid: c.type_oid, type: c.type })) ?? [],
|
|
161
178
|
doc.snapshot_done ?? true
|
|
162
179
|
)
|
|
163
180
|
)
|
|
@@ -386,9 +403,11 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
|
|
|
386
403
|
);
|
|
387
404
|
}
|
|
388
405
|
|
|
389
|
-
async terminate() {
|
|
390
|
-
|
|
391
|
-
|
|
406
|
+
async terminate(options?: TerminateOptions) {
|
|
407
|
+
// Default is to clear the storage except when explicitly requested not to.
|
|
408
|
+
if (!options || options?.clearStorage) {
|
|
409
|
+
await this.clear();
|
|
410
|
+
}
|
|
392
411
|
await this.db.sync_rules.updateOne(
|
|
393
412
|
{
|
|
394
413
|
_id: this.group_id
|
|
@@ -30,7 +30,7 @@ export class MongoSyncRulesLock implements ReplicationLock {
|
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
if (doc == null) {
|
|
33
|
-
throw new Error(`
|
|
33
|
+
throw new Error(`Sync rules: ${sync_rules.id} have been locked by another process for replication.`);
|
|
34
34
|
}
|
|
35
35
|
return new MongoSyncRulesLock(db, sync_rules.id, lockId);
|
|
36
36
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import * as bson from 'bson';
|
|
2
1
|
import { ToastableSqliteRow } from '@powersync/service-sync-rules';
|
|
2
|
+
import * as bson from 'bson';
|
|
3
3
|
|
|
4
|
-
import * as util from '../../util/util-index.js';
|
|
5
4
|
import { SaveOptions } from '../BucketStorage.js';
|
|
5
|
+
import { isUUID } from './util.js';
|
|
6
|
+
import { ReplicaId } from './models.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Maximum number of operations in a batch.
|
|
@@ -63,18 +64,15 @@ export class OperationBatch {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
export class RecordOperation {
|
|
66
|
-
public readonly afterId:
|
|
67
|
-
public readonly beforeId:
|
|
67
|
+
public readonly afterId: ReplicaId | null;
|
|
68
|
+
public readonly beforeId: ReplicaId;
|
|
68
69
|
public readonly internalBeforeKey: string;
|
|
69
70
|
public readonly internalAfterKey: string | null;
|
|
70
71
|
public readonly estimatedSize: number;
|
|
71
72
|
|
|
72
73
|
constructor(public readonly record: SaveOptions) {
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const beforeId = record.before
|
|
76
|
-
? util.getUuidReplicaIdentityBson(record.before, record.sourceTable.replicaIdColumns!)
|
|
77
|
-
: afterId!;
|
|
74
|
+
const afterId = record.afterReplicaId ?? null;
|
|
75
|
+
const beforeId = record.beforeReplicaId ?? record.afterReplicaId;
|
|
78
76
|
this.afterId = afterId;
|
|
79
77
|
this.beforeId = beforeId;
|
|
80
78
|
this.internalBeforeKey = cacheKey(record.sourceTable.id, beforeId);
|
|
@@ -84,8 +82,17 @@ export class RecordOperation {
|
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
/**
|
|
86
|
+
* In-memory cache key - must not be persisted.
|
|
87
|
+
*/
|
|
88
|
+
export function cacheKey(table: bson.ObjectId, id: ReplicaId) {
|
|
89
|
+
if (isUUID(id)) {
|
|
90
|
+
return `${table.toHexString()}.${id.toHexString()}`;
|
|
91
|
+
} else if (typeof id == 'string') {
|
|
92
|
+
return `${table.toHexString()}.${id}`;
|
|
93
|
+
} else {
|
|
94
|
+
return `${table.toHexString()}.${(bson.serialize({ id: id }) as Buffer).toString('base64')}`;
|
|
95
|
+
}
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
/**
|
|
@@ -13,9 +13,10 @@ import {
|
|
|
13
13
|
BucketParameterDocument,
|
|
14
14
|
CurrentBucket,
|
|
15
15
|
CurrentDataDocument,
|
|
16
|
-
SourceKey
|
|
16
|
+
SourceKey,
|
|
17
|
+
ReplicaId
|
|
17
18
|
} from './models.js';
|
|
18
|
-
import { serializeLookup } from './util.js';
|
|
19
|
+
import { replicaIdToSubkey, serializeLookup } from './util.js';
|
|
19
20
|
import { logger } from '@powersync/lib-services-framework';
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -59,7 +60,7 @@ export class PersistedBatch {
|
|
|
59
60
|
|
|
60
61
|
saveBucketData(options: {
|
|
61
62
|
op_seq: MongoIdSequence;
|
|
62
|
-
sourceKey:
|
|
63
|
+
sourceKey: ReplicaId;
|
|
63
64
|
table: SourceTable;
|
|
64
65
|
evaluated: EvaluatedRow[];
|
|
65
66
|
before_buckets: CurrentBucket[];
|
|
@@ -70,7 +71,7 @@ export class PersistedBatch {
|
|
|
70
71
|
remaining_buckets.set(key, b);
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
const dchecksum = util.hashDelete(
|
|
74
|
+
const dchecksum = util.hashDelete(replicaIdToSubkey(options.table.id, options.sourceKey));
|
|
74
75
|
|
|
75
76
|
for (let k of options.evaluated) {
|
|
76
77
|
const key = currentBucketKey(k);
|
|
@@ -134,7 +135,7 @@ export class PersistedBatch {
|
|
|
134
135
|
|
|
135
136
|
saveParameterData(data: {
|
|
136
137
|
op_seq: MongoIdSequence;
|
|
137
|
-
sourceKey:
|
|
138
|
+
sourceKey: ReplicaId;
|
|
138
139
|
sourceTable: SourceTable;
|
|
139
140
|
evaluated: EvaluatedParameters[];
|
|
140
141
|
existing_lookups: bson.Binary[];
|