@powersync/service-module-mongodb-storage 0.15.3 → 0.16.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 +54 -0
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js +1 -1
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js.map +1 -1
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +3 -3
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
- package/dist/migrations/db/migrations/1770213298299-storage-version.js.map +1 -1
- package/dist/storage/MongoBucketStorage.d.ts +5 -3
- package/dist/storage/MongoBucketStorage.js +50 -36
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/MongoReportStorage.js.map +1 -1
- package/dist/storage/implementation/BucketDefinitionMapping.d.ts +17 -0
- package/dist/storage/implementation/BucketDefinitionMapping.js +58 -0
- package/dist/storage/implementation/BucketDefinitionMapping.js.map +1 -0
- package/dist/storage/implementation/MongoBucketBatch.d.ts +16 -14
- package/dist/storage/implementation/MongoBucketBatch.js +80 -115
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatchShared.d.ts +5 -0
- package/dist/storage/implementation/MongoBucketBatchShared.js +8 -0
- package/dist/storage/implementation/MongoBucketBatchShared.js.map +1 -0
- package/dist/storage/implementation/MongoChecksums.d.ts +28 -17
- package/dist/storage/implementation/MongoChecksums.js +13 -72
- package/dist/storage/implementation/MongoChecksums.js.map +1 -1
- package/dist/storage/implementation/MongoCompactor.d.ts +98 -58
- package/dist/storage/implementation/MongoCompactor.js +229 -296
- package/dist/storage/implementation/MongoCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoParameterCompactor.d.ts +11 -6
- package/dist/storage/implementation/MongoParameterCompactor.js +11 -8
- package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoPersistedSyncRules.d.ts +14 -0
- package/dist/storage/implementation/MongoPersistedSyncRules.js +64 -0
- package/dist/storage/implementation/MongoPersistedSyncRules.js.map +1 -0
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +3 -0
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +9 -0
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/implementation/MongoStorageProvider.js +1 -1
- package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +49 -30
- package/dist/storage/implementation/MongoSyncBucketStorage.js +96 -388
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +5 -3
- package/dist/storage/implementation/MongoSyncRulesLock.js +12 -10
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/implementation/OperationBatch.js +1 -1
- package/dist/storage/implementation/common/BucketDataDoc.d.ts +35 -0
- package/dist/storage/implementation/common/BucketDataDoc.js +2 -0
- package/dist/storage/implementation/common/BucketDataDoc.js.map +1 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.d.ts +13 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js +2 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js.map +1 -0
- package/dist/storage/implementation/common/PersistedBatch.d.ts +108 -0
- package/dist/storage/implementation/common/PersistedBatch.js +237 -0
- package/dist/storage/implementation/common/PersistedBatch.js.map +1 -0
- package/dist/storage/implementation/common/SingleBucketStore.d.ts +54 -0
- package/dist/storage/implementation/common/SingleBucketStore.js +3 -0
- package/dist/storage/implementation/common/SingleBucketStore.js.map +1 -0
- package/dist/storage/implementation/common/SourceRecordStore.d.ts +36 -0
- package/dist/storage/implementation/common/SourceRecordStore.js +2 -0
- package/dist/storage/implementation/common/SourceRecordStore.js.map +1 -0
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.d.ts +27 -0
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js +57 -0
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js.map +1 -0
- package/dist/storage/implementation/createMongoSyncBucketStorage.d.ts +7 -0
- package/dist/storage/implementation/createMongoSyncBucketStorage.js +9 -0
- package/dist/storage/implementation/createMongoSyncBucketStorage.js.map +1 -0
- package/dist/storage/implementation/db.d.ts +34 -34
- package/dist/storage/implementation/db.js +78 -98
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +63 -34
- package/dist/storage/implementation/models.js +21 -2
- package/dist/storage/implementation/models.js.map +1 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +13 -0
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +22 -0
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -0
- package/dist/storage/implementation/v1/MongoChecksumsV1.d.ts +12 -0
- package/dist/storage/implementation/v1/MongoChecksumsV1.js +56 -0
- package/dist/storage/implementation/v1/MongoChecksumsV1.js.map +1 -0
- package/dist/storage/implementation/v1/MongoCompactorV1.d.ts +23 -0
- package/dist/storage/implementation/v1/MongoCompactorV1.js +52 -0
- package/dist/storage/implementation/v1/MongoCompactorV1.js.map +1 -0
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.d.ts +9 -0
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.js +20 -0
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.js.map +1 -0
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.d.ts +41 -0
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +283 -0
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -0
- package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +26 -0
- package/dist/storage/implementation/v1/PersistedBatchV1.js +183 -0
- package/dist/storage/implementation/v1/PersistedBatchV1.js.map +1 -0
- package/dist/storage/implementation/v1/SingleBucketStoreV1.d.ts +18 -0
- package/dist/storage/implementation/v1/SingleBucketStoreV1.js +57 -0
- package/dist/storage/implementation/v1/SingleBucketStoreV1.js.map +1 -0
- package/dist/storage/implementation/v1/SourceRecordStoreV1.d.ts +19 -0
- package/dist/storage/implementation/v1/SourceRecordStoreV1.js +105 -0
- package/dist/storage/implementation/v1/SourceRecordStoreV1.js.map +1 -0
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.d.ts +12 -0
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js +20 -0
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js.map +1 -0
- package/dist/storage/implementation/v1/models.d.ts +34 -0
- package/dist/storage/implementation/v1/models.js +37 -0
- package/dist/storage/implementation/v1/models.js.map +1 -0
- package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +13 -0
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +34 -0
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoChecksumsV3.d.ts +15 -0
- package/dist/storage/implementation/v3/MongoChecksumsV3.js +84 -0
- package/dist/storage/implementation/v3/MongoChecksumsV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +23 -0
- package/dist/storage/implementation/v3/MongoCompactorV3.js +68 -0
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.d.ts +9 -0
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js +18 -0
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoParameterLookupV3.d.ts +5 -0
- package/dist/storage/implementation/v3/MongoParameterLookupV3.js +9 -0
- package/dist/storage/implementation/v3/MongoParameterLookupV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +41 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +407 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -0
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +29 -0
- package/dist/storage/implementation/v3/PersistedBatchV3.js +259 -0
- package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -0
- package/dist/storage/implementation/v3/SingleBucketStoreV3.d.ts +18 -0
- package/dist/storage/implementation/v3/SingleBucketStoreV3.js +48 -0
- package/dist/storage/implementation/v3/SingleBucketStoreV3.js.map +1 -0
- package/dist/storage/implementation/v3/SourceRecordStoreV3.d.ts +22 -0
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js +164 -0
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js.map +1 -0
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.d.ts +21 -0
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +71 -0
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -0
- package/dist/storage/implementation/v3/models.d.ts +43 -0
- package/dist/storage/implementation/v3/models.js +34 -0
- package/dist/storage/implementation/v3/models.js.map +1 -0
- package/dist/storage/storage-index.d.ts +8 -5
- package/dist/storage/storage-index.js +8 -5
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/utils/util.d.ts +11 -4
- package/dist/utils/util.js +25 -4
- package/dist/utils/util.js.map +1 -1
- package/package.json +9 -9
- package/src/migrations/db/migrations/1688556755264-initial-sync-rules.ts +1 -1
- package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -7
- package/src/migrations/db/migrations/1770213298299-storage-version.ts +1 -1
- package/src/storage/MongoBucketStorage.ts +97 -62
- package/src/storage/MongoReportStorage.ts +2 -2
- package/src/storage/implementation/BucketDefinitionMapping.ts +72 -0
- package/src/storage/implementation/MongoBucketBatch.ts +110 -144
- package/src/storage/implementation/MongoBucketBatchShared.ts +11 -0
- package/src/storage/implementation/MongoChecksums.ts +53 -76
- package/src/storage/implementation/MongoCompactor.ts +374 -404
- package/src/storage/implementation/MongoParameterCompactor.ts +37 -24
- package/src/storage/implementation/MongoPersistedSyncRules.ts +76 -0
- package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +18 -1
- package/src/storage/implementation/MongoStorageProvider.ts +1 -1
- package/src/storage/implementation/MongoSyncBucketStorage.ts +190 -457
- package/src/storage/implementation/MongoSyncRulesLock.ts +12 -14
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +4 -2
- package/src/storage/implementation/OperationBatch.ts +1 -1
- package/src/storage/implementation/common/BucketDataDoc.ts +37 -0
- package/src/storage/implementation/common/MongoSyncBucketStorageContext.ts +15 -0
- package/src/storage/implementation/common/PersistedBatch.ts +364 -0
- package/src/storage/implementation/common/SingleBucketStore.ts +63 -0
- package/src/storage/implementation/common/SourceRecordStore.ts +49 -0
- package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +80 -0
- package/src/storage/implementation/createMongoSyncBucketStorage.ts +25 -0
- package/src/storage/implementation/db.ts +107 -128
- package/src/storage/implementation/models.ts +84 -38
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +32 -0
- package/src/storage/implementation/v1/MongoChecksumsV1.ts +75 -0
- package/src/storage/implementation/v1/MongoCompactorV1.ts +93 -0
- package/src/storage/implementation/v1/MongoParameterCompactorV1.ts +26 -0
- package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +448 -0
- package/src/storage/implementation/v1/PersistedBatchV1.ts +230 -0
- package/src/storage/implementation/v1/SingleBucketStoreV1.ts +74 -0
- package/src/storage/implementation/v1/SourceRecordStoreV1.ts +156 -0
- package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +28 -0
- package/src/storage/implementation/v1/models.ts +84 -0
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +44 -0
- package/src/storage/implementation/v3/MongoChecksumsV3.ts +120 -0
- package/src/storage/implementation/v3/MongoCompactorV3.ts +107 -0
- package/src/storage/implementation/v3/MongoParameterCompactorV3.ts +24 -0
- package/src/storage/implementation/v3/MongoParameterLookupV3.ts +12 -0
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +550 -0
- package/src/storage/implementation/v3/PersistedBatchV3.ts +318 -0
- package/src/storage/implementation/v3/SingleBucketStoreV3.ts +68 -0
- package/src/storage/implementation/v3/SourceRecordStoreV3.ts +226 -0
- package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +112 -0
- package/src/storage/implementation/v3/models.ts +96 -0
- package/src/storage/storage-index.ts +8 -5
- package/src/utils/util.ts +36 -7
- package/test/src/__snapshots__/storage_sync.test.ts.snap +282 -0
- package/test/src/connection-report-storage.test.ts +3 -3
- package/test/src/setup.ts +1 -1
- package/test/src/storage.test.ts +2 -2
- package/test/src/storage_compacting.test.ts +57 -29
- package/test/src/storage_sync.test.ts +351 -5
- package/test/tsconfig.json +0 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/storage/implementation/PersistedBatch.d.ts +0 -71
- package/dist/storage/implementation/PersistedBatch.js +0 -354
- package/dist/storage/implementation/PersistedBatch.js.map +0 -1
- package/src/storage/implementation/PersistedBatch.ts +0 -432
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
2
|
|
|
3
|
-
import { ErrorCode,
|
|
3
|
+
import { ErrorCode, Logger, ServiceError } from '@powersync/lib-services-framework';
|
|
4
4
|
import { storage } from '@powersync/service-core';
|
|
5
|
-
import {
|
|
5
|
+
import { VersionedPowerSyncMongo } from './db.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Manages a lock on a
|
|
9
|
-
*
|
|
8
|
+
* Manages a lock on a replication stream document, so that only one process
|
|
9
|
+
* processes that replication stream at a time.
|
|
10
10
|
*/
|
|
11
11
|
export class MongoSyncRulesLock implements storage.ReplicationLock {
|
|
12
12
|
private readonly refreshInterval: NodeJS.Timeout;
|
|
@@ -38,29 +38,27 @@ export class MongoSyncRulesLock implements storage.ReplicationLock {
|
|
|
38
38
|
if (heldLock?.lock?.expires_at) {
|
|
39
39
|
throw new ServiceError(
|
|
40
40
|
ErrorCode.PSYNC_S1003,
|
|
41
|
-
`
|
|
41
|
+
`Replication stream is locked by another process, standing by. Lock expiring at ${heldLock.lock.expires_at.toISOString()}.`
|
|
42
42
|
);
|
|
43
43
|
} else {
|
|
44
|
-
throw new ServiceError(
|
|
45
|
-
ErrorCode.PSYNC_S1003,
|
|
46
|
-
`Sync rules ${sync_rules.id} have been locked by another process for replication.`
|
|
47
|
-
);
|
|
44
|
+
throw new ServiceError(ErrorCode.PSYNC_S1003, `Replication stream is locked by another process, standing by.`);
|
|
48
45
|
}
|
|
49
46
|
}
|
|
50
|
-
logger.info(`
|
|
51
|
-
return new MongoSyncRulesLock(db, sync_rules.id, lockId);
|
|
47
|
+
sync_rules.logger.info(`Locked replication stream for processing`);
|
|
48
|
+
return new MongoSyncRulesLock(db, sync_rules.id, lockId, sync_rules.logger);
|
|
52
49
|
}
|
|
53
50
|
|
|
54
51
|
constructor(
|
|
55
52
|
private db: VersionedPowerSyncMongo,
|
|
56
53
|
public sync_rules_id: number,
|
|
57
|
-
private lock_id: string
|
|
54
|
+
private lock_id: string,
|
|
55
|
+
private logger: Logger
|
|
58
56
|
) {
|
|
59
57
|
this.refreshInterval = setInterval(async () => {
|
|
60
58
|
try {
|
|
61
59
|
await this.refresh();
|
|
62
60
|
} catch (e) {
|
|
63
|
-
logger.error('Failed to refresh lock', e);
|
|
61
|
+
this.logger.error('Failed to refresh lock', e);
|
|
64
62
|
clearInterval(this.refreshInterval);
|
|
65
63
|
}
|
|
66
64
|
}, 30_130);
|
|
@@ -79,7 +77,7 @@ export class MongoSyncRulesLock implements storage.ReplicationLock {
|
|
|
79
77
|
);
|
|
80
78
|
if (result.modifiedCount == 0) {
|
|
81
79
|
// Log and ignore
|
|
82
|
-
logger.warn(`Lock already released: ${this.sync_rules_id}/${this.lock_id}`);
|
|
80
|
+
this.logger.warn(`Lock already released: ${this.sync_rules_id}/${this.lock_id}`);
|
|
83
81
|
}
|
|
84
82
|
}
|
|
85
83
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
2
|
import * as framework from '@powersync/lib-services-framework';
|
|
3
3
|
import { GetCheckpointChangesOptions, InternalOpId, storage } from '@powersync/service-core';
|
|
4
|
-
import {
|
|
4
|
+
import { VersionedPowerSyncMongo } from './db.js';
|
|
5
5
|
|
|
6
6
|
export type MongoCheckpointAPIOptions = {
|
|
7
7
|
db: VersionedPowerSyncMongo;
|
|
@@ -56,7 +56,9 @@ export class MongoWriteCheckpointAPI implements storage.WriteCheckpointAPI {
|
|
|
56
56
|
switch (this.writeCheckpointMode) {
|
|
57
57
|
case storage.WriteCheckpointMode.CUSTOM:
|
|
58
58
|
if (false == 'sync_rules_id' in filters) {
|
|
59
|
-
throw new framework.ServiceAssertionError(
|
|
59
|
+
throw new framework.ServiceAssertionError(
|
|
60
|
+
`Replication stream ID is required for custom Write Checkpoint filtering`
|
|
61
|
+
);
|
|
60
62
|
}
|
|
61
63
|
return this.lastCustomWriteCheckpoint(filters);
|
|
62
64
|
case storage.WriteCheckpointMode.MANAGED:
|
|
@@ -2,7 +2,7 @@ import { ToastableSqliteRow } from '@powersync/service-sync-rules';
|
|
|
2
2
|
import * as bson from 'bson';
|
|
3
3
|
|
|
4
4
|
import { storage } from '@powersync/service-core';
|
|
5
|
-
import { mongoTableId } from '
|
|
5
|
+
import { mongoTableId } from '../../utils/util.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Maximum number of operations in a batch.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { InternalOpId } from '@powersync/service-core';
|
|
2
|
+
import { BucketDefinitionId } from '../BucketDefinitionMapping.js';
|
|
3
|
+
import { BucketDataProperties } from '../models.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Full context identifying a bucket.
|
|
7
|
+
*/
|
|
8
|
+
export interface BucketKey {
|
|
9
|
+
/**
|
|
10
|
+
* Also referred to as g / group_id.
|
|
11
|
+
*/
|
|
12
|
+
replicationStreamId: number;
|
|
13
|
+
/**
|
|
14
|
+
* Bucket definition id, '0' for storage V1.
|
|
15
|
+
*/
|
|
16
|
+
definitionId: BucketDefinitionId;
|
|
17
|
+
/**
|
|
18
|
+
* Bucket name.
|
|
19
|
+
*/
|
|
20
|
+
bucket: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* In-memory bucket data document.
|
|
25
|
+
*
|
|
26
|
+
* This is converted to/from BucketDataDocumentV1 / BucketDataDocumentV3 for storage.
|
|
27
|
+
*/
|
|
28
|
+
export interface BucketDataDoc extends BucketDataProperties {
|
|
29
|
+
/**
|
|
30
|
+
* Identifies the bucket for this document.
|
|
31
|
+
*/
|
|
32
|
+
bucketKey: BucketKey;
|
|
33
|
+
/**
|
|
34
|
+
* op_id
|
|
35
|
+
*/
|
|
36
|
+
o: InternalOpId;
|
|
37
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { InternalOpId } from '@powersync/service-core';
|
|
2
|
+
import * as bson from 'bson';
|
|
3
|
+
import { BucketDefinitionMapping } from '../BucketDefinitionMapping.js';
|
|
4
|
+
import type { VersionedPowerSyncMongo } from '../db.js';
|
|
5
|
+
|
|
6
|
+
export interface MongoSyncBucketStorageContext<TDb extends VersionedPowerSyncMongo = VersionedPowerSyncMongo> {
|
|
7
|
+
db: TDb;
|
|
8
|
+
group_id: number;
|
|
9
|
+
mapping: BucketDefinitionMapping;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface MongoSyncBucketStorageCheckpoint {
|
|
13
|
+
checkpoint: InternalOpId;
|
|
14
|
+
snapshotTime: bson.Timestamp;
|
|
15
|
+
}
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
|
+
import { BucketDataSource, EvaluatedParameters, EvaluatedRow } from '@powersync/service-sync-rules';
|
|
3
|
+
import * as bson from 'bson';
|
|
4
|
+
|
|
5
|
+
import { logger as defaultLogger, Logger } from '@powersync/lib-services-framework';
|
|
6
|
+
import { InternalOpId, storage, utils } from '@powersync/service-core';
|
|
7
|
+
import { JSONBig } from '@powersync/service-jsonbig';
|
|
8
|
+
import { mongoTableId, replicaIdToSubkey } from '../../../utils/util.js';
|
|
9
|
+
import { BucketDefinitionId, BucketDefinitionMapping } from '../BucketDefinitionMapping.js';
|
|
10
|
+
import { currentBucketKey, MAX_ROW_SIZE } from '../MongoBucketBatchShared.js';
|
|
11
|
+
import { MongoIdSequence } from '../MongoIdSequence.js';
|
|
12
|
+
import type { VersionedPowerSyncMongo } from '../db.js';
|
|
13
|
+
import { TaggedBucketParameterDocument } from '../models.js';
|
|
14
|
+
import { BucketDataDoc, BucketKey } from './BucketDataDoc.js';
|
|
15
|
+
import { SourceRecordBucketState, SourceRecordLookupState } from './SourceRecordStore.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Maximum size of operations we write in a single transaction.
|
|
19
|
+
*
|
|
20
|
+
* It's tricky to find the exact limit, but from experience, over 100MB
|
|
21
|
+
* can cause an error:
|
|
22
|
+
* > transaction is too large and will not fit in the storage engine cache
|
|
23
|
+
*
|
|
24
|
+
* Additionally, unbounded size here can balloon our memory usage in some edge
|
|
25
|
+
* cases.
|
|
26
|
+
*
|
|
27
|
+
* When we reach this threshold, we commit the transaction and start a new one.
|
|
28
|
+
*/
|
|
29
|
+
const MAX_TRANSACTION_BATCH_SIZE = 30_000_000;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Limit number of documents to write in a single transaction.
|
|
33
|
+
*
|
|
34
|
+
* This has an effect on error message size in some cases.
|
|
35
|
+
*/
|
|
36
|
+
const MAX_TRANSACTION_DOC_COUNT = 2_000;
|
|
37
|
+
|
|
38
|
+
export interface SaveBucketDataOptions {
|
|
39
|
+
op_seq: MongoIdSequence;
|
|
40
|
+
sourceKey: storage.ReplicaId;
|
|
41
|
+
table: storage.SourceTable;
|
|
42
|
+
evaluated: EvaluatedRow[];
|
|
43
|
+
before_buckets: SourceRecordBucketState[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface SaveParameterDataOptions {
|
|
47
|
+
op_seq: MongoIdSequence;
|
|
48
|
+
sourceKey: storage.ReplicaId;
|
|
49
|
+
sourceTable: storage.SourceTable;
|
|
50
|
+
evaluated: EvaluatedParameters[];
|
|
51
|
+
existing_lookups: SourceRecordLookupState[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface UpsertCurrentDataOptions {
|
|
55
|
+
sourceTableId: bson.ObjectId;
|
|
56
|
+
replicaId: storage.ReplicaId;
|
|
57
|
+
data: bson.Binary | null;
|
|
58
|
+
buckets: SourceRecordBucketState[];
|
|
59
|
+
lookups: SourceRecordLookupState[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface PersistedBatchOptions {
|
|
63
|
+
logger?: Logger;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Keeps track of bulkwrite operations within a transaction.
|
|
68
|
+
*
|
|
69
|
+
* There may be multiple of these batches per transaction, but it may not span
|
|
70
|
+
* multiple transactions.
|
|
71
|
+
*/
|
|
72
|
+
export abstract class PersistedBatch {
|
|
73
|
+
logger: Logger;
|
|
74
|
+
bucketData: BucketDataDoc[] = [];
|
|
75
|
+
bucketParameters: TaggedBucketParameterDocument[] = [];
|
|
76
|
+
bucketStates: Map<string, BucketStateUpdate> = new Map();
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* For debug logging only.
|
|
80
|
+
*/
|
|
81
|
+
debugLastOpId: InternalOpId | null = null;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Very rough estimate of transaction size.
|
|
85
|
+
*/
|
|
86
|
+
currentSize = 0;
|
|
87
|
+
|
|
88
|
+
constructor(
|
|
89
|
+
protected readonly db: VersionedPowerSyncMongo,
|
|
90
|
+
protected readonly group_id: number,
|
|
91
|
+
protected readonly mapping: BucketDefinitionMapping,
|
|
92
|
+
writtenSize: number,
|
|
93
|
+
options?: PersistedBatchOptions
|
|
94
|
+
) {
|
|
95
|
+
this.currentSize = writtenSize;
|
|
96
|
+
this.logger = options?.logger ?? defaultLogger;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
saveBucketData(options: SaveBucketDataOptions) {
|
|
100
|
+
const remaining_buckets = new Map<string, SaveBucketDataOptions['before_buckets'][number]>();
|
|
101
|
+
for (let bucket of options.before_buckets) {
|
|
102
|
+
const mapped: SourceRecordBucketState = {
|
|
103
|
+
bucket: bucket.bucket,
|
|
104
|
+
definitionId: this.checkDefinitionId(bucket.definitionId),
|
|
105
|
+
id: bucket.id,
|
|
106
|
+
table: bucket.table
|
|
107
|
+
};
|
|
108
|
+
remaining_buckets.set(currentBucketKey(mapped), mapped);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const dchecksum = BigInt(utils.hashDelete(replicaIdToSubkey(options.table.id, options.sourceKey)));
|
|
112
|
+
|
|
113
|
+
for (const evaluated of options.evaluated) {
|
|
114
|
+
const definitionId = this.getBucketDefinitionId(evaluated.source);
|
|
115
|
+
const key = currentBucketKey({
|
|
116
|
+
definitionId: definitionId,
|
|
117
|
+
bucket: evaluated.bucket,
|
|
118
|
+
table: evaluated.table,
|
|
119
|
+
id: evaluated.id
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const recordData = JSONBig.stringify(evaluated.data);
|
|
123
|
+
const checksum = utils.hashData(evaluated.table, evaluated.id, recordData);
|
|
124
|
+
if (recordData.length > MAX_ROW_SIZE) {
|
|
125
|
+
this.logger.error(`Row ${key} too large: ${recordData.length} bytes. Removing.`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
remaining_buckets.delete(key);
|
|
130
|
+
const byteEstimate = recordData.length + 200;
|
|
131
|
+
this.currentSize += byteEstimate;
|
|
132
|
+
|
|
133
|
+
const op_id = options.op_seq.next();
|
|
134
|
+
this.debugLastOpId = op_id;
|
|
135
|
+
|
|
136
|
+
this.addBucketDataPut({
|
|
137
|
+
bucketKey: {
|
|
138
|
+
bucket: evaluated.bucket,
|
|
139
|
+
definitionId: definitionId,
|
|
140
|
+
replicationStreamId: this.group_id
|
|
141
|
+
},
|
|
142
|
+
op_id,
|
|
143
|
+
bucket: evaluated.bucket,
|
|
144
|
+
sourceTableId: options.table.id,
|
|
145
|
+
sourceKey: options.sourceKey,
|
|
146
|
+
table: evaluated.table,
|
|
147
|
+
rowId: evaluated.id,
|
|
148
|
+
checksum: BigInt(checksum),
|
|
149
|
+
data: recordData
|
|
150
|
+
});
|
|
151
|
+
this.incrementBucket(definitionId, evaluated.bucket, op_id, byteEstimate);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
for (let bucket of remaining_buckets.values()) {
|
|
155
|
+
const definitionId = bucket.definitionId!;
|
|
156
|
+
const op_id = options.op_seq.next();
|
|
157
|
+
this.debugLastOpId = op_id;
|
|
158
|
+
|
|
159
|
+
this.addBucketDataRemove({
|
|
160
|
+
bucketKey: {
|
|
161
|
+
replicationStreamId: this.group_id,
|
|
162
|
+
definitionId,
|
|
163
|
+
bucket: bucket.bucket
|
|
164
|
+
},
|
|
165
|
+
op_id,
|
|
166
|
+
sourceTableId: options.table.id,
|
|
167
|
+
sourceKey: options.sourceKey,
|
|
168
|
+
table: bucket.table,
|
|
169
|
+
rowId: bucket.id,
|
|
170
|
+
checksum: dchecksum
|
|
171
|
+
});
|
|
172
|
+
this.currentSize += 200;
|
|
173
|
+
this.incrementBucket(definitionId, bucket.bucket, op_id, 200);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
abstract saveParameterData(data: SaveParameterDataOptions): void;
|
|
178
|
+
|
|
179
|
+
abstract hardDeleteCurrentData(sourceTableId: bson.ObjectId, replicaId: storage.ReplicaId): void;
|
|
180
|
+
|
|
181
|
+
abstract softDeleteCurrentData(
|
|
182
|
+
sourceTableId: bson.ObjectId,
|
|
183
|
+
replicaId: storage.ReplicaId,
|
|
184
|
+
checkpointGreaterThan: bigint
|
|
185
|
+
): void;
|
|
186
|
+
|
|
187
|
+
abstract upsertCurrentData(values: UpsertCurrentDataOptions): void;
|
|
188
|
+
|
|
189
|
+
protected abstract get currentDataCount(): number;
|
|
190
|
+
|
|
191
|
+
protected abstract flushBucketData(session: mongo.ClientSession): Promise<void>;
|
|
192
|
+
|
|
193
|
+
protected abstract flushBucketParameters(session: mongo.ClientSession): Promise<void>;
|
|
194
|
+
|
|
195
|
+
protected abstract flushCurrentData(session: mongo.ClientSession): Promise<void>;
|
|
196
|
+
|
|
197
|
+
protected abstract flushBucketStates(session: mongo.ClientSession): Promise<void>;
|
|
198
|
+
|
|
199
|
+
protected abstract resetCurrentData(): void;
|
|
200
|
+
|
|
201
|
+
protected abstract checkDefinitionId(definitionId: BucketDefinitionId | null): BucketDefinitionId;
|
|
202
|
+
protected abstract getBucketDefinitionId(bucketSource: BucketDataSource): BucketDefinitionId;
|
|
203
|
+
|
|
204
|
+
protected get bucketDataCount(): number {
|
|
205
|
+
return this.bucketData.length;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
protected incrementBucket(definitionId: BucketDefinitionId, bucket: string, op_id: InternalOpId, bytes: number) {
|
|
209
|
+
const key = `${definitionId ?? ''}:${bucket}`;
|
|
210
|
+
let existingState = this.bucketStates.get(key);
|
|
211
|
+
if (existingState) {
|
|
212
|
+
existingState.lastOp = op_id;
|
|
213
|
+
existingState.incrementCount += 1;
|
|
214
|
+
existingState.incrementBytes += bytes;
|
|
215
|
+
} else {
|
|
216
|
+
this.bucketStates.set(key, {
|
|
217
|
+
definitionId,
|
|
218
|
+
bucket,
|
|
219
|
+
lastOp: op_id,
|
|
220
|
+
incrementCount: 1,
|
|
221
|
+
incrementBytes: bytes
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
protected addBucketDataPut(options: {
|
|
227
|
+
op_id: InternalOpId;
|
|
228
|
+
bucketKey: BucketKey;
|
|
229
|
+
bucket: string;
|
|
230
|
+
sourceTableId: storage.SourceTable['id'];
|
|
231
|
+
sourceKey: storage.ReplicaId;
|
|
232
|
+
table: string;
|
|
233
|
+
rowId: string;
|
|
234
|
+
checksum: bigint;
|
|
235
|
+
data: string;
|
|
236
|
+
}) {
|
|
237
|
+
this.bucketData.push({
|
|
238
|
+
bucketKey: options.bucketKey,
|
|
239
|
+
o: options.op_id,
|
|
240
|
+
op: 'PUT',
|
|
241
|
+
source_table: mongoTableId(options.sourceTableId),
|
|
242
|
+
source_key: options.sourceKey,
|
|
243
|
+
table: options.table,
|
|
244
|
+
row_id: options.rowId,
|
|
245
|
+
checksum: options.checksum,
|
|
246
|
+
data: options.data
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
protected addBucketDataRemove(options: {
|
|
251
|
+
op_id: InternalOpId;
|
|
252
|
+
bucketKey: BucketKey;
|
|
253
|
+
sourceTableId: storage.SourceTable['id'];
|
|
254
|
+
sourceKey: storage.ReplicaId;
|
|
255
|
+
table: string;
|
|
256
|
+
rowId: string;
|
|
257
|
+
checksum: bigint;
|
|
258
|
+
}) {
|
|
259
|
+
this.bucketData.push({
|
|
260
|
+
bucketKey: options.bucketKey,
|
|
261
|
+
o: options.op_id,
|
|
262
|
+
op: 'REMOVE',
|
|
263
|
+
source_table: mongoTableId(options.sourceTableId),
|
|
264
|
+
source_key: options.sourceKey,
|
|
265
|
+
table: options.table,
|
|
266
|
+
row_id: options.rowId,
|
|
267
|
+
checksum: options.checksum,
|
|
268
|
+
data: null
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
shouldFlushTransaction() {
|
|
273
|
+
return (
|
|
274
|
+
this.currentSize >= MAX_TRANSACTION_BATCH_SIZE ||
|
|
275
|
+
this.bucketDataCount >= MAX_TRANSACTION_DOC_COUNT ||
|
|
276
|
+
this.currentDataCount >= MAX_TRANSACTION_DOC_COUNT ||
|
|
277
|
+
this.bucketParameters.length >= MAX_TRANSACTION_DOC_COUNT
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
async flush(session: mongo.ClientSession, options?: storage.BucketBatchCommitOptions) {
|
|
282
|
+
const startAt = performance.now();
|
|
283
|
+
let flushedSomething = false;
|
|
284
|
+
if (this.bucketDataCount > 0) {
|
|
285
|
+
flushedSomething = true;
|
|
286
|
+
await this.flushBucketData(session);
|
|
287
|
+
}
|
|
288
|
+
if (this.bucketParameters.length > 0) {
|
|
289
|
+
flushedSomething = true;
|
|
290
|
+
await this.flushBucketParameters(session);
|
|
291
|
+
}
|
|
292
|
+
if (this.currentDataCount > 0) {
|
|
293
|
+
flushedSomething = true;
|
|
294
|
+
await this.flushCurrentData(session);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (this.bucketStates.size > 0) {
|
|
298
|
+
flushedSomething = true;
|
|
299
|
+
await this.flushBucketStates(session);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (flushedSomething) {
|
|
303
|
+
const duration = Math.round(performance.now() - startAt);
|
|
304
|
+
if (options?.oldestUncommittedChange != null) {
|
|
305
|
+
const replicationLag = Math.round((Date.now() - options.oldestUncommittedChange.getTime()) / 1000);
|
|
306
|
+
|
|
307
|
+
this.logger.info(
|
|
308
|
+
`Flushed ${this.bucketDataCount} + ${this.bucketParameters.length} + ${
|
|
309
|
+
this.currentDataCount
|
|
310
|
+
} updates, ${Math.round(this.currentSize / 1024)}kb in ${duration}ms. Last op_id: ${this.debugLastOpId}. Replication lag: ${replicationLag}s`,
|
|
311
|
+
{
|
|
312
|
+
flushed: {
|
|
313
|
+
duration: duration,
|
|
314
|
+
size: this.currentSize,
|
|
315
|
+
bucket_data_count: this.bucketDataCount,
|
|
316
|
+
parameter_data_count: this.bucketParameters.length,
|
|
317
|
+
current_data_count: this.currentDataCount,
|
|
318
|
+
replication_lag_seconds: replicationLag
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
} else {
|
|
323
|
+
this.logger.info(
|
|
324
|
+
`Flushed ${this.bucketDataCount} + ${this.bucketParameters.length} + ${
|
|
325
|
+
this.currentDataCount
|
|
326
|
+
} updates, ${Math.round(this.currentSize / 1024)}kb in ${duration}ms. Last op_id: ${this.debugLastOpId}`,
|
|
327
|
+
{
|
|
328
|
+
flushed: {
|
|
329
|
+
duration: duration,
|
|
330
|
+
size: this.currentSize,
|
|
331
|
+
bucket_data_count: this.bucketDataCount,
|
|
332
|
+
parameter_data_count: this.bucketParameters.length,
|
|
333
|
+
current_data_count: this.currentDataCount
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const stats = {
|
|
341
|
+
bucketDataCount: this.bucketDataCount,
|
|
342
|
+
parameterDataCount: this.bucketParameters.length,
|
|
343
|
+
currentDataCount: this.currentDataCount,
|
|
344
|
+
flushedAny: flushedSomething
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
this.bucketData = [];
|
|
348
|
+
this.bucketParameters = [];
|
|
349
|
+
this.resetCurrentData();
|
|
350
|
+
this.bucketStates.clear();
|
|
351
|
+
this.currentSize = 0;
|
|
352
|
+
this.debugLastOpId = null;
|
|
353
|
+
|
|
354
|
+
return stats;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export interface BucketStateUpdate {
|
|
359
|
+
definitionId: BucketDefinitionId | null;
|
|
360
|
+
bucket: string;
|
|
361
|
+
lastOp: InternalOpId;
|
|
362
|
+
incrementCount: number;
|
|
363
|
+
incrementBytes: number;
|
|
364
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
|
+
import { InternalOpId } from '@powersync/service-core';
|
|
3
|
+
import { BucketDataProperties } from '../models.js';
|
|
4
|
+
import { BucketDataDoc, BucketKey } from './BucketDataDoc.js';
|
|
5
|
+
|
|
6
|
+
const GENERIC_ID = Symbol('BucketDataDocumentGenericId');
|
|
7
|
+
export type BucketDataDocumentGenericId = {
|
|
8
|
+
b: string;
|
|
9
|
+
o: InternalOpId;
|
|
10
|
+
// Hack to ensure this can't be constructed directly
|
|
11
|
+
[GENERIC_ID]: true;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* This document is never actually constructed - we use it as a "virtual" type.
|
|
16
|
+
*
|
|
17
|
+
* The actual implementations are BucketDataDocumentV1 or BucketDataDocumentV3.
|
|
18
|
+
* They don't fully satisfy this interface, but this works to share common implementations.
|
|
19
|
+
*
|
|
20
|
+
* The idea is that we can have a common implementation between V1 & V3, using this type,
|
|
21
|
+
* and operate on MongoDB collections.
|
|
22
|
+
*
|
|
23
|
+
* This interface serves two primary purposes:
|
|
24
|
+
* 1. Captures properties that exist on both V1 and V3 storage models.
|
|
25
|
+
* 2. Gives a common reference when querying or modifying collections.
|
|
26
|
+
*
|
|
27
|
+
* Generics would've been ideal, but they don't play well with MongoDB collections.
|
|
28
|
+
*/
|
|
29
|
+
export interface BucketDataDocumentGeneric extends BucketDataProperties {
|
|
30
|
+
_id: BucketDataDocumentGenericId;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Represent read/write access for a single bucket.
|
|
35
|
+
*
|
|
36
|
+
* This does not implement the actual collection operations, but supports the required conversions
|
|
37
|
+
* between in-memory BucketDataDoc and the specific storage formats.
|
|
38
|
+
*/
|
|
39
|
+
export interface SingleBucketStore {
|
|
40
|
+
readonly key: BucketKey;
|
|
41
|
+
|
|
42
|
+
readonly collection: mongo.Collection<BucketDataDocumentGeneric>;
|
|
43
|
+
docId(o: InternalOpId): BucketDataDocumentGenericId;
|
|
44
|
+
readonly minId: BucketDataDocumentGenericId;
|
|
45
|
+
readonly maxId: BucketDataDocumentGenericId;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Convert in-memory document -> persisted document.
|
|
49
|
+
*/
|
|
50
|
+
toPersistedDocument(source: Omit<BucketDataDoc, 'bucketKey'>): BucketDataDocumentGeneric;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Convert persisted document -> in-memory document.
|
|
54
|
+
*/
|
|
55
|
+
fromPersistedDocument(doc: BucketDataDocumentGeneric): BucketDataDoc;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Convert partial persisted document -> partial in-memory document.
|
|
59
|
+
*/
|
|
60
|
+
fromPartialPersistedDocument<T extends keyof BucketDataProperties>(
|
|
61
|
+
doc: Pick<BucketDataDocumentGeneric, '_id' | T>
|
|
62
|
+
): Pick<BucketDataDoc, 'bucketKey' | 'o' | T>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
|
+
import { Logger } from '@powersync/lib-services-framework';
|
|
3
|
+
import { storage } from '@powersync/service-core';
|
|
4
|
+
import { EvaluatedParameters, EvaluatedRow } from '@powersync/service-sync-rules';
|
|
5
|
+
import * as bson from 'bson';
|
|
6
|
+
import { BucketDefinitionId, ParameterIndexId } from '../BucketDefinitionMapping.js';
|
|
7
|
+
|
|
8
|
+
export interface SourceRecordLookupEntry {
|
|
9
|
+
sourceTableId: bson.ObjectId;
|
|
10
|
+
replicaId: storage.ReplicaId;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface SourceRecordBucketState {
|
|
14
|
+
definitionId: BucketDefinitionId | null;
|
|
15
|
+
bucket: string;
|
|
16
|
+
table: string;
|
|
17
|
+
id: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SourceRecordLookupState {
|
|
21
|
+
indexId: ParameterIndexId | null;
|
|
22
|
+
lookup: bson.Binary;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface LoadedSourceRecord {
|
|
26
|
+
sourceTableId: bson.ObjectId;
|
|
27
|
+
replicaId: storage.ReplicaId;
|
|
28
|
+
data: bson.Binary | null;
|
|
29
|
+
buckets: SourceRecordBucketState[];
|
|
30
|
+
lookups: SourceRecordLookupState[];
|
|
31
|
+
cacheKey: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface SourceRecordStore {
|
|
35
|
+
mapEvaluatedBuckets(evaluated: EvaluatedRow[]): SourceRecordBucketState[];
|
|
36
|
+
mapParameterLookups(paramEvaluated: EvaluatedParameters[]): SourceRecordLookupState[];
|
|
37
|
+
loadSizes(session: mongo.ClientSession, entries: SourceRecordLookupEntry[]): Promise<Map<string, number>>;
|
|
38
|
+
loadDocuments(
|
|
39
|
+
session: mongo.ClientSession,
|
|
40
|
+
entries: SourceRecordLookupEntry[],
|
|
41
|
+
idsOnly: boolean
|
|
42
|
+
): Promise<Map<string, LoadedSourceRecord>>;
|
|
43
|
+
loadTruncateBatch(
|
|
44
|
+
session: mongo.ClientSession,
|
|
45
|
+
sourceTableId: bson.ObjectId,
|
|
46
|
+
limit: number
|
|
47
|
+
): Promise<LoadedSourceRecord[]>;
|
|
48
|
+
postCommitCleanup(lastCheckpoint: bigint, logger: Logger): Promise<void>;
|
|
49
|
+
}
|