@powersync/service-module-mongodb-storage 0.15.4 → 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 +35 -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 +2 -2
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
- package/dist/storage/MongoBucketStorage.d.ts +2 -2
- package/dist/storage/MongoBucketStorage.js +47 -34
- package/dist/storage/MongoBucketStorage.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/MongoSyncBucketStorage.d.ts +47 -29
- package/dist/storage/implementation/MongoSyncBucketStorage.js +94 -387
- 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 +32 -35
- package/dist/storage/implementation/db.js +77 -99
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +62 -33
- package/dist/storage/implementation/models.js +20 -1
- 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 +6 -3
- package/dist/storage/storage-index.js +6 -3
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/utils/util.d.ts +10 -3
- package/dist/utils/util.js +24 -3
- 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 +6 -6
- package/src/storage/MongoBucketStorage.ts +92 -59
- 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 +52 -75
- 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 +17 -0
- package/src/storage/implementation/MongoSyncBucketStorage.ts +181 -455
- package/src/storage/implementation/MongoSyncRulesLock.ts +11 -13
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +3 -1
- 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 +105 -129
- package/src/storage/implementation/models.ts +82 -36
- 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 +6 -3
- package/src/utils/util.ts +34 -5
- 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,6 +1,14 @@
|
|
|
1
|
-
import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
1
|
+
import { deserializeParameterLookup, JwtPayload, storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
2
2
|
import { bucketRequest, register, test_utils } from '@powersync/service-core-tests';
|
|
3
|
+
import { RequestParameters } from '@powersync/service-sync-rules';
|
|
4
|
+
import * as bson from 'bson';
|
|
3
5
|
import { describe, expect, test } from 'vitest';
|
|
6
|
+
import { MongoBucketStorage } from '../../src/storage/MongoBucketStorage.js';
|
|
7
|
+
import { MongoSyncBucketStorage } from '../../src/storage/implementation/createMongoSyncBucketStorage.js';
|
|
8
|
+
import { SyncRuleDocument } from '../../src/storage/implementation/models.js';
|
|
9
|
+
import { SourceRecordStoreV3 } from '../../src/storage/implementation/v3/SourceRecordStoreV3.js';
|
|
10
|
+
import type { VersionedPowerSyncMongoV3 } from '../../src/storage/implementation/v3/VersionedPowerSyncMongoV3.js';
|
|
11
|
+
import { CurrentBucketV3 } from '../../src/storage/implementation/v3/models.js';
|
|
4
12
|
import { INITIALIZED_MONGO_STORAGE_FACTORY, TEST_STORAGE_VERSIONS } from './util.js';
|
|
5
13
|
|
|
6
14
|
function registerSyncStorageTests(storageConfig: storage.TestStorageConfig, storageVersion: number) {
|
|
@@ -126,12 +134,350 @@ function registerSyncStorageTests(storageConfig: storage.TestStorageConfig, stor
|
|
|
126
134
|
|
|
127
135
|
// Test that the checksum type is correct.
|
|
128
136
|
// Specifically, test that it never persisted as double.
|
|
129
|
-
const mongoFactory = factory as
|
|
130
|
-
const checksumTypes =
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
const mongoFactory = factory as MongoBucketStorage;
|
|
138
|
+
const checksumTypes =
|
|
139
|
+
storageVersion >= 3
|
|
140
|
+
? (
|
|
141
|
+
await Promise.all(
|
|
142
|
+
(
|
|
143
|
+
await mongoFactory.db.db
|
|
144
|
+
.listCollections({ name: new RegExp(`^bucket_data_${syncRules.id}_`) }, { nameOnly: true })
|
|
145
|
+
.toArray()
|
|
146
|
+
).map((collection: { name: string }) =>
|
|
147
|
+
mongoFactory.db.db
|
|
148
|
+
.collection(collection.name)
|
|
149
|
+
.aggregate([{ $group: { _id: { $type: '$checksum' }, count: { $sum: 1 } } }])
|
|
150
|
+
.toArray()
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
).flat()
|
|
154
|
+
: await mongoFactory.db.bucket_data
|
|
155
|
+
.aggregate([{ $group: { _id: { $type: '$checksum' }, count: { $sum: 1 } } }])
|
|
156
|
+
.toArray();
|
|
133
157
|
expect(checksumTypes).toEqual([{ _id: 'long', count: 4 }]);
|
|
134
158
|
});
|
|
159
|
+
|
|
160
|
+
test.runIf(storageVersion >= 3)('uses v3 mongodb model shapes', async () => {
|
|
161
|
+
await using factory = await storageConfig.factory();
|
|
162
|
+
const syncRules = await factory.updateSyncRules(
|
|
163
|
+
updateSyncRulesFromYaml(
|
|
164
|
+
`
|
|
165
|
+
bucket_definitions:
|
|
166
|
+
global:
|
|
167
|
+
parameters:
|
|
168
|
+
- SELECT owner_id FROM test WHERE id = token_parameters.test
|
|
169
|
+
data:
|
|
170
|
+
- SELECT id, description, owner_id FROM test WHERE id = bucket.owner_id
|
|
171
|
+
`,
|
|
172
|
+
{ storageVersion }
|
|
173
|
+
)
|
|
174
|
+
);
|
|
175
|
+
const bucketStorage = factory.getInstance(syncRules);
|
|
176
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncRules();
|
|
177
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
178
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
179
|
+
|
|
180
|
+
await writer.save({
|
|
181
|
+
sourceTable,
|
|
182
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
183
|
+
after: {
|
|
184
|
+
id: 'shape-check',
|
|
185
|
+
description: 'shape',
|
|
186
|
+
owner_id: 'user-1'
|
|
187
|
+
},
|
|
188
|
+
afterReplicaId: test_utils.rid('shape-check')
|
|
189
|
+
});
|
|
190
|
+
await writer.markAllSnapshotDone('1/1');
|
|
191
|
+
await writer.commit('1/1');
|
|
192
|
+
|
|
193
|
+
const checkpoint = await bucketStorage.getCheckpoint();
|
|
194
|
+
const parameters = new RequestParameters(new JwtPayload({ sub: 'u1', parameters: { test: 'shape-check' } }), {});
|
|
195
|
+
const querier = sync_rules.getBucketParameterQuerier(test_utils.querierOptions(parameters)).querier;
|
|
196
|
+
const buckets = await querier.queryDynamicBucketDescriptions({
|
|
197
|
+
async getParameterSets(lookups) {
|
|
198
|
+
expect(lookups.map((l) => l.indexKey)).toEqual([['shape-check']]);
|
|
199
|
+
expect(lookups[0].indexId).toEqual('1');
|
|
200
|
+
|
|
201
|
+
const parameter_sets = await checkpoint.getParameterSets(lookups, 1000);
|
|
202
|
+
expect(parameter_sets).toEqual([{ lookup: lookups[0], rows: [{ owner_id: 'user-1' }] }]);
|
|
203
|
+
return parameter_sets;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
expect(buckets.map((b) => b.bucket)).toEqual([bucketRequest(syncRules, 'global["user-1"]').bucket]);
|
|
207
|
+
|
|
208
|
+
const mongoFactory = factory as MongoBucketStorage;
|
|
209
|
+
const db = (bucketStorage as MongoSyncBucketStorage).db as VersionedPowerSyncMongoV3;
|
|
210
|
+
const currentDataCollections = await db.listSourceRecordCollectionsV3(syncRules.id);
|
|
211
|
+
const currentData = await currentDataCollections[0]?.findOne({});
|
|
212
|
+
const firstBucket: CurrentBucketV3 | undefined = currentData?.buckets[0] as CurrentBucketV3 | undefined;
|
|
213
|
+
expect(firstBucket?.def).toMatch(/^[0-9a-f]+$/);
|
|
214
|
+
|
|
215
|
+
const bucketCollections = await mongoFactory.db.db
|
|
216
|
+
.listCollections({ name: new RegExp(`^bucket_data_${syncRules.id}_`) }, { nameOnly: true })
|
|
217
|
+
.toArray();
|
|
218
|
+
expect(
|
|
219
|
+
bucketCollections.some((collection) => collection.name === `bucket_data_${syncRules.id}_${firstBucket?.def}`)
|
|
220
|
+
).toBe(true);
|
|
221
|
+
|
|
222
|
+
const syncRule = await mongoFactory.db.sync_rules.findOne({ _id: syncRules.id });
|
|
223
|
+
const ruleMapping: SyncRuleDocument['rule_mapping'] | undefined = syncRule?.rule_mapping;
|
|
224
|
+
expect(Object.keys(ruleMapping?.definitions ?? {})).not.toHaveLength(0);
|
|
225
|
+
|
|
226
|
+
const parameterIndexId = Object.values(ruleMapping?.parameter_indexes ?? {})[0] as string | undefined;
|
|
227
|
+
expect(parameterIndexId).toBeDefined();
|
|
228
|
+
const parameterEntry = await db.parameterIndexV3(syncRules.id, parameterIndexId!).findOne({});
|
|
229
|
+
expect(deserializeParameterLookup(parameterEntry!.lookup)).toEqual(['shape-check']);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test.runIf(storageVersion < 3)('uses a single current_data collection for v1 source records', async () => {
|
|
233
|
+
await using factory = await storageConfig.factory();
|
|
234
|
+
const syncRules = await factory.updateSyncRules(
|
|
235
|
+
updateSyncRulesFromYaml(
|
|
236
|
+
`
|
|
237
|
+
bucket_definitions:
|
|
238
|
+
global:
|
|
239
|
+
data:
|
|
240
|
+
- SELECT id, description FROM test
|
|
241
|
+
`,
|
|
242
|
+
{ storageVersion }
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
const bucketStorage = factory.getInstance(syncRules);
|
|
246
|
+
|
|
247
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
248
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
249
|
+
|
|
250
|
+
await writer.save({
|
|
251
|
+
sourceTable,
|
|
252
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
253
|
+
after: {
|
|
254
|
+
id: 'shape-check',
|
|
255
|
+
description: 'shape'
|
|
256
|
+
},
|
|
257
|
+
afterReplicaId: test_utils.rid('shape-check')
|
|
258
|
+
});
|
|
259
|
+
await writer.markAllSnapshotDone('1/1');
|
|
260
|
+
await writer.commit('1/1');
|
|
261
|
+
|
|
262
|
+
const mongoFactory = factory as MongoBucketStorage;
|
|
263
|
+
expect(await mongoFactory.db.current_data.countDocuments({ '_id.g': syncRules.id })).toBe(1);
|
|
264
|
+
|
|
265
|
+
const sourceRecordCollections = await mongoFactory.db.db
|
|
266
|
+
.listCollections({ name: new RegExp(`^source_records_${syncRules.id}_`) }, { nameOnly: true })
|
|
267
|
+
.toArray();
|
|
268
|
+
expect(sourceRecordCollections).toEqual([]);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test.runIf(storageVersion < 3)('clear removes v1 current_data rows', async () => {
|
|
272
|
+
await using factory = await storageConfig.factory();
|
|
273
|
+
const syncRules = await factory.updateSyncRules(
|
|
274
|
+
updateSyncRulesFromYaml(
|
|
275
|
+
`
|
|
276
|
+
bucket_definitions:
|
|
277
|
+
global:
|
|
278
|
+
data:
|
|
279
|
+
- SELECT id, description FROM test
|
|
280
|
+
`,
|
|
281
|
+
{ storageVersion }
|
|
282
|
+
)
|
|
283
|
+
);
|
|
284
|
+
const bucketStorage = factory.getInstance(syncRules);
|
|
285
|
+
|
|
286
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
287
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
288
|
+
|
|
289
|
+
await writer.save({
|
|
290
|
+
sourceTable,
|
|
291
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
292
|
+
after: {
|
|
293
|
+
id: 'clear-check',
|
|
294
|
+
description: 'shape'
|
|
295
|
+
},
|
|
296
|
+
afterReplicaId: test_utils.rid('clear-check')
|
|
297
|
+
});
|
|
298
|
+
await writer.markAllSnapshotDone('1/1');
|
|
299
|
+
await writer.commit('1/1');
|
|
300
|
+
|
|
301
|
+
const mongoFactory = factory as MongoBucketStorage;
|
|
302
|
+
expect(await mongoFactory.db.current_data.countDocuments({ '_id.g': syncRules.id })).toBe(1);
|
|
303
|
+
|
|
304
|
+
await bucketStorage.clear();
|
|
305
|
+
|
|
306
|
+
expect(await mongoFactory.db.current_data.countDocuments({ '_id.g': syncRules.id })).toBe(0);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test.runIf(storageVersion < 3)('storage metrics include v1 current_data', async () => {
|
|
310
|
+
await using factory = await storageConfig.factory();
|
|
311
|
+
const syncRules = await factory.updateSyncRules(
|
|
312
|
+
updateSyncRulesFromYaml(
|
|
313
|
+
`
|
|
314
|
+
bucket_definitions:
|
|
315
|
+
global:
|
|
316
|
+
data:
|
|
317
|
+
- SELECT id, description FROM test
|
|
318
|
+
`,
|
|
319
|
+
{ storageVersion }
|
|
320
|
+
)
|
|
321
|
+
);
|
|
322
|
+
const bucketStorage = factory.getInstance(syncRules);
|
|
323
|
+
const metricsBefore = await factory.getStorageMetrics();
|
|
324
|
+
|
|
325
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
326
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
327
|
+
|
|
328
|
+
await writer.save({
|
|
329
|
+
sourceTable,
|
|
330
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
331
|
+
after: {
|
|
332
|
+
id: 'metric-check',
|
|
333
|
+
description: 'shape'
|
|
334
|
+
},
|
|
335
|
+
afterReplicaId: test_utils.rid('metric-check')
|
|
336
|
+
});
|
|
337
|
+
await writer.markAllSnapshotDone('1/1');
|
|
338
|
+
await writer.commit('1/1');
|
|
339
|
+
|
|
340
|
+
const mongoFactory = factory as MongoBucketStorage;
|
|
341
|
+
expect(await mongoFactory.db.current_data.countDocuments({ '_id.g': syncRules.id })).toBe(1);
|
|
342
|
+
|
|
343
|
+
const metricsAfter = await factory.getStorageMetrics();
|
|
344
|
+
expect(metricsAfter.replication_size_bytes).toBeGreaterThan(metricsBefore.replication_size_bytes);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
test.runIf(storageVersion >= 3)(
|
|
348
|
+
'loads parameter checkpoint changes across all v3 parameter index collections',
|
|
349
|
+
async () => {
|
|
350
|
+
await using factory = await storageConfig.factory();
|
|
351
|
+
const syncRules = await factory.updateSyncRules(
|
|
352
|
+
updateSyncRulesFromYaml(
|
|
353
|
+
`
|
|
354
|
+
bucket_definitions:
|
|
355
|
+
by_owner:
|
|
356
|
+
parameters:
|
|
357
|
+
- SELECT owner_id FROM test WHERE id = token_parameters.owner_lookup
|
|
358
|
+
data:
|
|
359
|
+
- SELECT id, owner_id FROM test WHERE owner_id = bucket.owner_id
|
|
360
|
+
by_category:
|
|
361
|
+
parameters:
|
|
362
|
+
- SELECT category_id FROM test WHERE id = token_parameters.category_lookup
|
|
363
|
+
data:
|
|
364
|
+
- SELECT id, category_id FROM test WHERE category_id = bucket.category_id
|
|
365
|
+
`,
|
|
366
|
+
{ storageVersion }
|
|
367
|
+
)
|
|
368
|
+
);
|
|
369
|
+
const bucketStorage = factory.getInstance(syncRules) as MongoSyncBucketStorage;
|
|
370
|
+
const previousCheckpoint = await bucketStorage.getCheckpoint();
|
|
371
|
+
|
|
372
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
373
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id'], INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
374
|
+
|
|
375
|
+
await writer.save({
|
|
376
|
+
sourceTable,
|
|
377
|
+
tag: storage.SaveOperationTag.INSERT,
|
|
378
|
+
after: {
|
|
379
|
+
id: 'shape-check',
|
|
380
|
+
owner_id: 'user-1',
|
|
381
|
+
category_id: 'cat-1'
|
|
382
|
+
},
|
|
383
|
+
afterReplicaId: test_utils.rid('shape-check')
|
|
384
|
+
});
|
|
385
|
+
await writer.markAllSnapshotDone('1/1');
|
|
386
|
+
await writer.commit('1/1');
|
|
387
|
+
|
|
388
|
+
const nextCheckpoint = await bucketStorage.getCheckpoint();
|
|
389
|
+
const changes = await bucketStorage.getCheckpointChanges({
|
|
390
|
+
lastCheckpoint: previousCheckpoint,
|
|
391
|
+
nextCheckpoint
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
expect(changes.invalidateParameterBuckets).toBe(false);
|
|
395
|
+
expect(changes.updatedParameterLookups).toEqual(new Set(['["1","","shape-check"]', '["2","","shape-check"]']));
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
test.runIf(storageVersion >= 3)('cleans pending deletes only for tracked v3 source tables', async () => {
|
|
400
|
+
await using factory = await storageConfig.factory();
|
|
401
|
+
const syncRules = await factory.updateSyncRules(
|
|
402
|
+
updateSyncRulesFromYaml(
|
|
403
|
+
`
|
|
404
|
+
bucket_definitions:
|
|
405
|
+
global:
|
|
406
|
+
data:
|
|
407
|
+
- SELECT id, description FROM test
|
|
408
|
+
`,
|
|
409
|
+
{ storageVersion }
|
|
410
|
+
)
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
const mongoFactory = factory as MongoBucketStorage;
|
|
414
|
+
const bucketStorage = mongoFactory.getInstance(syncRules) as any;
|
|
415
|
+
const db = bucketStorage.db;
|
|
416
|
+
await db.initializeStreamStorage(syncRules.id);
|
|
417
|
+
|
|
418
|
+
const sourceTableA = new bson.ObjectId();
|
|
419
|
+
const sourceTableB = new bson.ObjectId();
|
|
420
|
+
await db.sourceTablesV3(syncRules.id).insertMany([
|
|
421
|
+
{
|
|
422
|
+
_id: sourceTableA,
|
|
423
|
+
connection_id: 1,
|
|
424
|
+
relation_id: 'a',
|
|
425
|
+
schema_name: 'public',
|
|
426
|
+
table_name: 'table_a',
|
|
427
|
+
replica_id_columns: null,
|
|
428
|
+
replica_id_columns2: [],
|
|
429
|
+
snapshot_done: true,
|
|
430
|
+
snapshot_status: undefined,
|
|
431
|
+
bucket_data_source_ids: [],
|
|
432
|
+
parameter_lookup_source_ids: [],
|
|
433
|
+
latest_pending_delete: 9n
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
_id: sourceTableB,
|
|
437
|
+
connection_id: 1,
|
|
438
|
+
relation_id: 'b',
|
|
439
|
+
schema_name: 'public',
|
|
440
|
+
table_name: 'table_b',
|
|
441
|
+
replica_id_columns: null,
|
|
442
|
+
replica_id_columns2: [],
|
|
443
|
+
snapshot_done: true,
|
|
444
|
+
snapshot_status: undefined,
|
|
445
|
+
bucket_data_source_ids: [],
|
|
446
|
+
parameter_lookup_source_ids: [],
|
|
447
|
+
latest_pending_delete: 12n
|
|
448
|
+
}
|
|
449
|
+
]);
|
|
450
|
+
|
|
451
|
+
await db.sourceRecordsV3(syncRules.id, sourceTableA).insertMany([
|
|
452
|
+
{ _id: 'deleted-1', data: null, buckets: [], lookups: [], pending_delete: 5n },
|
|
453
|
+
{ _id: 'deleted-2', data: null, buckets: [], lookups: [], pending_delete: 9n },
|
|
454
|
+
{ _id: 'active', data: null, buckets: [], lookups: [] }
|
|
455
|
+
]);
|
|
456
|
+
await db
|
|
457
|
+
.sourceRecordsV3(syncRules.id, sourceTableB)
|
|
458
|
+
.insertMany([{ _id: 'later-delete', data: null, buckets: [], lookups: [], pending_delete: 12n }]);
|
|
459
|
+
|
|
460
|
+
const store = new SourceRecordStoreV3(db, syncRules.id, bucketStorage.sync_rules.mapping);
|
|
461
|
+
const logger = { info() {} } as any;
|
|
462
|
+
|
|
463
|
+
await store.postCommitCleanup(6n, logger);
|
|
464
|
+
|
|
465
|
+
expect(await db.sourceRecordsV3(syncRules.id, sourceTableA).countDocuments({ pending_delete: 5n })).toBe(0);
|
|
466
|
+
expect(await db.sourceRecordsV3(syncRules.id, sourceTableA).countDocuments({ pending_delete: 9n })).toBe(1);
|
|
467
|
+
expect(await db.sourceRecordsV3(syncRules.id, sourceTableB).countDocuments({ pending_delete: 12n })).toBe(1);
|
|
468
|
+
expect((await db.sourceTablesV3(syncRules.id).findOne({ _id: sourceTableA }))?.latest_pending_delete).toBe(9n);
|
|
469
|
+
expect((await db.sourceTablesV3(syncRules.id).findOne({ _id: sourceTableB }))?.latest_pending_delete).toBe(12n);
|
|
470
|
+
|
|
471
|
+
await store.postCommitCleanup(10n, logger);
|
|
472
|
+
|
|
473
|
+
expect(
|
|
474
|
+
await db.sourceRecordsV3(syncRules.id, sourceTableA).countDocuments({ pending_delete: { $exists: true } })
|
|
475
|
+
).toBe(0);
|
|
476
|
+
expect(
|
|
477
|
+
(await db.sourceTablesV3(syncRules.id).findOne({ _id: sourceTableA }))?.latest_pending_delete
|
|
478
|
+
).toBeUndefined();
|
|
479
|
+
expect((await db.sourceTablesV3(syncRules.id).findOne({ _id: sourceTableB }))?.latest_pending_delete).toBe(12n);
|
|
480
|
+
});
|
|
135
481
|
}
|
|
136
482
|
|
|
137
483
|
describe('sync - mongodb', () => {
|