@powersync/service-core-tests 0.0.0-dev-20260803144812 → 0.0.0-dev-20260929095716
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 +60 -5
- package/dist/test-utils/AbstractStreamTestContext.js +4 -3
- package/dist/test-utils/AbstractStreamTestContext.js.map +1 -1
- package/dist/test-utils/leased-storage.d.ts +9 -0
- package/dist/test-utils/leased-storage.js +53 -0
- package/dist/test-utils/leased-storage.js.map +1 -0
- package/dist/test-utils/storage-combinations.d.ts +13 -0
- package/dist/test-utils/storage-combinations.js +26 -0
- package/dist/test-utils/storage-combinations.js.map +1 -0
- package/dist/test-utils/test-utils-index.d.ts +2 -0
- package/dist/test-utils/test-utils-index.js +2 -0
- package/dist/test-utils/test-utils-index.js.map +1 -1
- package/dist/tests/register-compacting-tests.js +16 -15
- package/dist/tests/register-compacting-tests.js.map +1 -1
- package/dist/tests/register-data-storage-checkpoint-tests.js +47 -21
- package/dist/tests/register-data-storage-checkpoint-tests.js.map +1 -1
- package/dist/tests/register-data-storage-data-tests.js +37 -24
- package/dist/tests/register-data-storage-data-tests.js.map +1 -1
- package/dist/tests/register-data-storage-parameter-tests.js +16 -15
- package/dist/tests/register-data-storage-parameter-tests.js.map +1 -1
- package/dist/tests/register-parameter-compacting-tests.js +6 -4
- package/dist/tests/register-parameter-compacting-tests.js.map +1 -1
- package/dist/tests/register-sync-tests.js +28 -26
- package/dist/tests/register-sync-tests.js.map +1 -1
- package/dist/tests/util.d.ts +6 -0
- package/dist/tests/util.js +12 -0
- package/dist/tests/util.js.map +1 -1
- package/package.json +4 -4
- package/src/test-utils/AbstractStreamTestContext.ts +4 -3
- package/src/test-utils/leased-storage.ts +58 -0
- package/src/test-utils/storage-combinations.ts +51 -0
- package/src/test-utils/test-utils-index.ts +2 -0
- package/src/tests/register-compacting-tests.ts +16 -15
- package/src/tests/register-data-storage-checkpoint-tests.ts +85 -56
- package/src/tests/register-data-storage-data-tests.ts +41 -24
- package/src/tests/register-data-storage-parameter-tests.ts +16 -15
- package/src/tests/register-parameter-compacting-tests.ts +6 -4
- package/src/tests/register-sync-tests.ts +28 -26
- package/src/tests/util.ts +13 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { storage } from '@powersync/service-core';
|
|
2
|
+
|
|
3
|
+
const leases = new WeakMap<storage.BucketStorageFactory, Map<number, Promise<storage.ReplicationLock>>>();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Acquire a real replication lease before constructing writable test storage.
|
|
7
|
+
* Writers in the same test job share a lease per factory/stream. The factory owns
|
|
8
|
+
* these leases and releases them at teardown; takeover tests manage their own leases.
|
|
9
|
+
*/
|
|
10
|
+
export async function getTestStorage<T extends storage.BucketStorageFactory>(
|
|
11
|
+
factory: T,
|
|
12
|
+
stream: storage.PersistedReplicationStream,
|
|
13
|
+
options?: Parameters<T['getInstance']>[1]
|
|
14
|
+
): Promise<ReturnType<T['getInstance']>> {
|
|
15
|
+
let owned = leases.get(factory);
|
|
16
|
+
if (owned == null) {
|
|
17
|
+
owned = new Map();
|
|
18
|
+
leases.set(factory, owned);
|
|
19
|
+
const factoryLeases = owned;
|
|
20
|
+
// `await using` captures the disposer before this helper runs. Register a
|
|
21
|
+
// lifecycle callback instead of replacing that already-captured method.
|
|
22
|
+
const unregister = factory.registerListener({
|
|
23
|
+
beforeDispose: async () => {
|
|
24
|
+
unregister();
|
|
25
|
+
try {
|
|
26
|
+
for (const lock of factoryLeases.values()) {
|
|
27
|
+
await (await lock).release();
|
|
28
|
+
}
|
|
29
|
+
} finally {
|
|
30
|
+
factoryLeases.clear();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
let pending = owned.get(stream.replicationStreamId);
|
|
36
|
+
if (pending == null) {
|
|
37
|
+
pending = stream.lock();
|
|
38
|
+
owned.set(stream.replicationStreamId, pending);
|
|
39
|
+
}
|
|
40
|
+
let lock: storage.ReplicationLock;
|
|
41
|
+
try {
|
|
42
|
+
lock = await pending;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
owned.delete(stream.replicationStreamId);
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
return factory.getInstance(stream, { ...options, replicationLock: lock }) as ReturnType<T['getInstance']>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** End a test job before starting a replacement through another factory. */
|
|
51
|
+
export async function releaseTestStorageLease(factory: storage.BucketStorageFactory, streamId: number) {
|
|
52
|
+
const owned = leases.get(factory);
|
|
53
|
+
const pending = owned?.get(streamId);
|
|
54
|
+
if (pending != null) {
|
|
55
|
+
await (await pending).release();
|
|
56
|
+
owned!.delete(streamId);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
STORAGE_VERSION_1,
|
|
3
|
+
STORAGE_VERSION_2,
|
|
4
|
+
STORAGE_VERSION_4,
|
|
5
|
+
TestStorageConfig,
|
|
6
|
+
TestStorageFactory
|
|
7
|
+
} from '@powersync/service-core';
|
|
8
|
+
import { describe, TestOptions } from 'vitest';
|
|
9
|
+
|
|
10
|
+
const MONGO_STORAGE_VERSIONS = [STORAGE_VERSION_1, STORAGE_VERSION_2, STORAGE_VERSION_4];
|
|
11
|
+
const POSTGRES_STORAGE_VERSIONS = [STORAGE_VERSION_1, STORAGE_VERSION_2];
|
|
12
|
+
|
|
13
|
+
export interface StorageVersionTestContext {
|
|
14
|
+
factory: TestStorageFactory;
|
|
15
|
+
storageVersion: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface StorageCombinationTestConfig {
|
|
19
|
+
mongodb?: TestStorageConfig;
|
|
20
|
+
postgres?: TestStorageConfig;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function describeStorageCombinations(
|
|
24
|
+
config: StorageCombinationTestConfig,
|
|
25
|
+
options: TestOptions & { storageVersions?: number[] },
|
|
26
|
+
fn: (context: StorageVersionTestContext) => void
|
|
27
|
+
) {
|
|
28
|
+
const describeFactory = (storageName: string, storage: TestStorageConfig, supportedStorageVersions: number[]) => {
|
|
29
|
+
const storageVersions = (options.storageVersions ?? supportedStorageVersions).filter((version) =>
|
|
30
|
+
supportedStorageVersions.includes(version)
|
|
31
|
+
);
|
|
32
|
+
describe(`${storageName} storage`, options, function () {
|
|
33
|
+
for (const storageVersion of storageVersions) {
|
|
34
|
+
describe(`storage v${storageVersion}`, function () {
|
|
35
|
+
fn({
|
|
36
|
+
factory: storage.factory,
|
|
37
|
+
storageVersion
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (config.mongodb) {
|
|
45
|
+
describeFactory('mongodb', config.mongodb, MONGO_STORAGE_VERSIONS);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (config.postgres) {
|
|
49
|
+
describeFactory('postgres', config.postgres, POSTGRES_STORAGE_VERSIONS);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './AbstractStreamTestContext.js';
|
|
2
2
|
export * from './bucket-validation.js';
|
|
3
3
|
export * from './general-utils.js';
|
|
4
|
+
export * from './leased-storage.js';
|
|
4
5
|
export * from './MetricsHelper.js';
|
|
6
|
+
export * from './storage-combinations.js';
|
|
5
7
|
export * from './StorageDataHelpers.js';
|
|
6
8
|
export * from './stream_utils.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { addChecksums, storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
2
2
|
import { expect, test } from 'vitest';
|
|
3
|
+
import { getTestStorage } from '../test-utils/leased-storage.js';
|
|
3
4
|
import * as test_utils from '../test-utils/test-utils-index.js';
|
|
4
5
|
import { bucketRequest } from '../test-utils/test-utils-index.js';
|
|
5
|
-
import { bucketRequestMap, bucketRequests } from './util.js';
|
|
6
|
+
import { bucketRequestMap, bucketRequests, compactActive } from './util.js';
|
|
6
7
|
|
|
7
8
|
export function registerCompactTests(config: storage.TestStorageConfig) {
|
|
8
9
|
const generateStorageFactory = config.factory;
|
|
@@ -16,7 +17,7 @@ bucket_definitions:
|
|
|
16
17
|
data: [select * from test]
|
|
17
18
|
`)
|
|
18
19
|
);
|
|
19
|
-
const bucketStorage = factory
|
|
20
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
20
21
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
21
22
|
|
|
22
23
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -81,7 +82,7 @@ bucket_definitions:
|
|
|
81
82
|
]);
|
|
82
83
|
expect(batchBefore.targetOp).toEqual(null);
|
|
83
84
|
|
|
84
|
-
await
|
|
85
|
+
await compactActive(factory, {
|
|
85
86
|
clearBatchLimit: 2,
|
|
86
87
|
moveBatchLimit: 1,
|
|
87
88
|
moveBatchQueryLimit: 1,
|
|
@@ -128,7 +129,7 @@ bucket_definitions:
|
|
|
128
129
|
data: [select * from test]
|
|
129
130
|
`)
|
|
130
131
|
);
|
|
131
|
-
const bucketStorage = factory
|
|
132
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
132
133
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
133
134
|
|
|
134
135
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -202,7 +203,7 @@ bucket_definitions:
|
|
|
202
203
|
}
|
|
203
204
|
]);
|
|
204
205
|
|
|
205
|
-
await
|
|
206
|
+
await compactActive(factory, {
|
|
206
207
|
clearBatchLimit: 2,
|
|
207
208
|
moveBatchLimit: 1,
|
|
208
209
|
moveBatchQueryLimit: 1,
|
|
@@ -249,7 +250,7 @@ bucket_definitions:
|
|
|
249
250
|
data: [select * from test]
|
|
250
251
|
`)
|
|
251
252
|
);
|
|
252
|
-
const bucketStorage = factory
|
|
253
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
253
254
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
254
255
|
|
|
255
256
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -301,7 +302,7 @@ bucket_definitions:
|
|
|
301
302
|
await writer2.flush();
|
|
302
303
|
const checkpoint2 = writer2.last_flushed_op!;
|
|
303
304
|
|
|
304
|
-
await
|
|
305
|
+
await compactActive(factory, {
|
|
305
306
|
clearBatchLimit: 2,
|
|
306
307
|
moveBatchLimit: 1,
|
|
307
308
|
moveBatchQueryLimit: 1,
|
|
@@ -340,7 +341,7 @@ bucket_definitions:
|
|
|
340
341
|
data:
|
|
341
342
|
- select * from test where b = bucket.b`)
|
|
342
343
|
);
|
|
343
|
-
const bucketStorage = factory
|
|
344
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
344
345
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
345
346
|
|
|
346
347
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -416,7 +417,7 @@ bucket_definitions:
|
|
|
416
417
|
|
|
417
418
|
const checkpoint = writer.last_flushed_op!;
|
|
418
419
|
|
|
419
|
-
await
|
|
420
|
+
await compactActive(factory, {
|
|
420
421
|
clearBatchLimit: 100,
|
|
421
422
|
moveBatchLimit: 100,
|
|
422
423
|
moveBatchQueryLimit: 100, // Larger limit for a larger window of operations
|
|
@@ -471,7 +472,7 @@ bucket_definitions:
|
|
|
471
472
|
data: [select * from test]
|
|
472
473
|
`)
|
|
473
474
|
);
|
|
474
|
-
const bucketStorage = factory
|
|
475
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
475
476
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
476
477
|
|
|
477
478
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -507,7 +508,7 @@ bucket_definitions:
|
|
|
507
508
|
await writer.commit('1/1');
|
|
508
509
|
await writer.flush();
|
|
509
510
|
|
|
510
|
-
await
|
|
511
|
+
await compactActive(factory, {
|
|
511
512
|
clearBatchLimit: 2,
|
|
512
513
|
moveBatchLimit: 1,
|
|
513
514
|
moveBatchQueryLimit: 1,
|
|
@@ -550,7 +551,7 @@ bucket_definitions:
|
|
|
550
551
|
data: [select * from test]
|
|
551
552
|
`)
|
|
552
553
|
);
|
|
553
|
-
const bucketStorage = factory
|
|
554
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
554
555
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
555
556
|
|
|
556
557
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -595,7 +596,7 @@ bucket_definitions:
|
|
|
595
596
|
await writer2.commit('2/1');
|
|
596
597
|
await writer2.flush();
|
|
597
598
|
|
|
598
|
-
await
|
|
599
|
+
await compactActive(factory, {
|
|
599
600
|
clearBatchLimit: 20,
|
|
600
601
|
moveBatchLimit: 10,
|
|
601
602
|
moveBatchQueryLimit: 10,
|
|
@@ -625,7 +626,7 @@ bucket_definitions:
|
|
|
625
626
|
data: [select * from test]
|
|
626
627
|
`)
|
|
627
628
|
);
|
|
628
|
-
const bucketStorage = factory
|
|
629
|
+
const bucketStorage = await getTestStorage(factory, syncRules);
|
|
629
630
|
const syncRulesContent = syncRules.syncConfigContent[0];
|
|
630
631
|
|
|
631
632
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -658,7 +659,7 @@ bucket_definitions:
|
|
|
658
659
|
expect(checkpointBeforeCompact.checkpoint).toEqual(checkpoint1);
|
|
659
660
|
|
|
660
661
|
// With default options, Postgres compaction should use the active checkpoint.
|
|
661
|
-
await
|
|
662
|
+
await compactActive(factory, {
|
|
662
663
|
moveBatchLimit: 1,
|
|
663
664
|
moveBatchQueryLimit: 1,
|
|
664
665
|
minBucketChanges: 1,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
|
|
2
2
|
import { expect, test } from 'vitest';
|
|
3
|
+
import { getTestStorage } from '../test-utils/leased-storage.js';
|
|
3
4
|
import * as test_utils from '../test-utils/test-utils-index.js';
|
|
5
|
+
import { compactActive } from './util.js';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* @example
|
|
@@ -31,12 +33,15 @@ bucket_definitions:
|
|
|
31
33
|
}
|
|
32
34
|
)
|
|
33
35
|
);
|
|
34
|
-
const bucketStorage = factory
|
|
36
|
+
const bucketStorage = await getTestStorage(factory, r.persisted_sync_rules!);
|
|
35
37
|
|
|
36
38
|
const abortController = new AbortController();
|
|
37
39
|
context.onTestFinished(() => abortController.abort());
|
|
38
40
|
const iter = bucketStorage
|
|
39
|
-
.watchCheckpointChanges({
|
|
41
|
+
.watchCheckpointChanges({
|
|
42
|
+
user_id: 'user1',
|
|
43
|
+
signal: abortController.signal
|
|
44
|
+
})
|
|
40
45
|
[Symbol.asyncIterator]();
|
|
41
46
|
|
|
42
47
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -77,7 +82,7 @@ bucket_definitions:
|
|
|
77
82
|
}
|
|
78
83
|
)
|
|
79
84
|
);
|
|
80
|
-
const bucketStorage = factory
|
|
85
|
+
const bucketStorage = await getTestStorage(factory, r.persisted_sync_rules!);
|
|
81
86
|
|
|
82
87
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
83
88
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -85,7 +90,10 @@ bucket_definitions:
|
|
|
85
90
|
const abortController = new AbortController();
|
|
86
91
|
context.onTestFinished(() => abortController.abort());
|
|
87
92
|
const iter = bucketStorage
|
|
88
|
-
.watchCheckpointChanges({
|
|
93
|
+
.watchCheckpointChanges({
|
|
94
|
+
user_id: 'user1',
|
|
95
|
+
signal: abortController.signal
|
|
96
|
+
})
|
|
89
97
|
[Symbol.asyncIterator]();
|
|
90
98
|
|
|
91
99
|
await writer.keepalive('5/0');
|
|
@@ -143,7 +151,7 @@ bucket_definitions:
|
|
|
143
151
|
}
|
|
144
152
|
)
|
|
145
153
|
);
|
|
146
|
-
const bucketStorage = factory
|
|
154
|
+
const bucketStorage = await getTestStorage(factory, r.persisted_sync_rules!);
|
|
147
155
|
|
|
148
156
|
const first = await createManagedWriteCheckpointResult(bucketStorage, {
|
|
149
157
|
user_id: 'user1',
|
|
@@ -194,7 +202,7 @@ bucket_definitions:
|
|
|
194
202
|
expect(generated.shouldAdvance).toBe(true);
|
|
195
203
|
});
|
|
196
204
|
|
|
197
|
-
test('custom write checkpoints - checkpoint after write', async (context) => {
|
|
205
|
+
test.runIf((storageVersion ?? 1) < 3)('custom write checkpoints - checkpoint after write', async (context) => {
|
|
198
206
|
await using factory = await generateStorageFactory();
|
|
199
207
|
const r = await factory.configureSyncRules(
|
|
200
208
|
updateSyncRulesFromYaml(
|
|
@@ -209,8 +217,10 @@ bucket_definitions:
|
|
|
209
217
|
}
|
|
210
218
|
)
|
|
211
219
|
);
|
|
212
|
-
const bucketStorage = factory
|
|
213
|
-
bucketStorage.setWriteCheckpointMode(
|
|
220
|
+
const bucketStorage = await getTestStorage(factory, r.persisted_sync_rules!);
|
|
221
|
+
bucketStorage.setWriteCheckpointMode({
|
|
222
|
+
mode: storage.WriteCheckpointMode.CUSTOM
|
|
223
|
+
});
|
|
214
224
|
|
|
215
225
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
216
226
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -218,7 +228,10 @@ bucket_definitions:
|
|
|
218
228
|
const abortController = new AbortController();
|
|
219
229
|
context.onTestFinished(() => abortController.abort());
|
|
220
230
|
const iter = bucketStorage
|
|
221
|
-
.watchCheckpointChanges({
|
|
231
|
+
.watchCheckpointChanges({
|
|
232
|
+
user_id: 'user1',
|
|
233
|
+
signal: abortController.signal
|
|
234
|
+
})
|
|
222
235
|
[Symbol.asyncIterator]();
|
|
223
236
|
|
|
224
237
|
writer.addCustomWriteCheckpoint({
|
|
@@ -240,7 +253,7 @@ bucket_definitions:
|
|
|
240
253
|
});
|
|
241
254
|
});
|
|
242
255
|
|
|
243
|
-
test('custom write checkpoints - standalone checkpoint', async (context) => {
|
|
256
|
+
test.runIf((storageVersion ?? 1) < 3)('custom write checkpoints - standalone checkpoint', async (context) => {
|
|
244
257
|
await using factory = await generateStorageFactory();
|
|
245
258
|
const r = await factory.configureSyncRules(
|
|
246
259
|
updateSyncRulesFromYaml(
|
|
@@ -255,8 +268,10 @@ bucket_definitions:
|
|
|
255
268
|
}
|
|
256
269
|
)
|
|
257
270
|
);
|
|
258
|
-
const bucketStorage = factory
|
|
259
|
-
bucketStorage.setWriteCheckpointMode(
|
|
271
|
+
const bucketStorage = await getTestStorage(factory, r.persisted_sync_rules!);
|
|
272
|
+
bucketStorage.setWriteCheckpointMode({
|
|
273
|
+
mode: storage.WriteCheckpointMode.CUSTOM
|
|
274
|
+
});
|
|
260
275
|
|
|
261
276
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
262
277
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -264,7 +279,10 @@ bucket_definitions:
|
|
|
264
279
|
const abortController = new AbortController();
|
|
265
280
|
context.onTestFinished(() => abortController.abort());
|
|
266
281
|
const iter = bucketStorage
|
|
267
|
-
.watchCheckpointChanges({
|
|
282
|
+
.watchCheckpointChanges({
|
|
283
|
+
user_id: 'user1',
|
|
284
|
+
signal: abortController.signal
|
|
285
|
+
})
|
|
268
286
|
[Symbol.asyncIterator]();
|
|
269
287
|
|
|
270
288
|
// Flush to clear state
|
|
@@ -289,7 +307,7 @@ bucket_definitions:
|
|
|
289
307
|
});
|
|
290
308
|
});
|
|
291
309
|
|
|
292
|
-
test('custom write checkpoints - write after checkpoint', async (context) => {
|
|
310
|
+
test.runIf((storageVersion ?? 1) < 3)('custom write checkpoints - write after checkpoint', async (context) => {
|
|
293
311
|
await using factory = await generateStorageFactory();
|
|
294
312
|
const r = await factory.configureSyncRules(
|
|
295
313
|
updateSyncRulesFromYaml(
|
|
@@ -304,8 +322,10 @@ bucket_definitions:
|
|
|
304
322
|
}
|
|
305
323
|
)
|
|
306
324
|
);
|
|
307
|
-
const bucketStorage = factory
|
|
308
|
-
bucketStorage.setWriteCheckpointMode(
|
|
325
|
+
const bucketStorage = await getTestStorage(factory, r.persisted_sync_rules!);
|
|
326
|
+
bucketStorage.setWriteCheckpointMode({
|
|
327
|
+
mode: storage.WriteCheckpointMode.CUSTOM
|
|
328
|
+
});
|
|
309
329
|
|
|
310
330
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
311
331
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -313,7 +333,10 @@ bucket_definitions:
|
|
|
313
333
|
const abortController = new AbortController();
|
|
314
334
|
context.onTestFinished(() => abortController.abort());
|
|
315
335
|
const iter = bucketStorage
|
|
316
|
-
.watchCheckpointChanges({
|
|
336
|
+
.watchCheckpointChanges({
|
|
337
|
+
user_id: 'user1',
|
|
338
|
+
signal: abortController.signal
|
|
339
|
+
})
|
|
317
340
|
[Symbol.asyncIterator]();
|
|
318
341
|
|
|
319
342
|
await writer.keepalive('5/0');
|
|
@@ -368,49 +391,55 @@ bucket_definitions:
|
|
|
368
391
|
});
|
|
369
392
|
});
|
|
370
393
|
|
|
371
|
-
test(
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
394
|
+
test.runIf((storageVersion ?? 1) < 3)(
|
|
395
|
+
'custom write checkpoints - checkpoint request markers are temporary',
|
|
396
|
+
async () => {
|
|
397
|
+
await using factory = await generateStorageFactory();
|
|
398
|
+
const r = await factory.configureSyncRules(
|
|
399
|
+
updateSyncRulesFromYaml(
|
|
400
|
+
`
|
|
376
401
|
bucket_definitions:
|
|
377
402
|
mybucket:
|
|
378
403
|
data: []
|
|
379
404
|
`,
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
405
|
+
{
|
|
406
|
+
validate: false,
|
|
407
|
+
storageVersion
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
);
|
|
411
|
+
const bucketStorage = await getTestStorage(factory, r.persisted_sync_rules!);
|
|
412
|
+
bucketStorage.setWriteCheckpointMode({
|
|
413
|
+
mode: storage.WriteCheckpointMode.CUSTOM
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
417
|
+
await writer.markAllSnapshotDone('1/1');
|
|
418
|
+
|
|
419
|
+
writer.addCustomWriteCheckpoint({
|
|
420
|
+
checkpoint: 5n,
|
|
421
|
+
user_id: 'persistent'
|
|
422
|
+
});
|
|
423
|
+
writer.addCustomWriteCheckpoint({
|
|
424
|
+
checkpoint: 6n,
|
|
425
|
+
user_id: 'temporary',
|
|
426
|
+
checkpoint_requested_at: new Date('2024-01-01T00:00:00.000Z')
|
|
427
|
+
});
|
|
428
|
+
await writer.flush();
|
|
429
|
+
await writer.keepalive('1/1');
|
|
430
|
+
|
|
431
|
+
await expect(bucketStorage.lastWriteCheckpoint({ user_id: 'persistent' })).resolves.toEqual(5n);
|
|
432
|
+
await expect(bucketStorage.lastWriteCheckpoint({ user_id: 'temporary' })).resolves.toEqual(6n);
|
|
433
|
+
|
|
434
|
+
await compactActive(factory, {
|
|
435
|
+
compactBuckets: [],
|
|
436
|
+
deleteCheckpointRequestsBefore: new Date(Date.now() + 1_000)
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
await expect(bucketStorage.lastWriteCheckpoint({ user_id: 'persistent' })).resolves.toEqual(5n);
|
|
440
|
+
await expect(bucketStorage.lastWriteCheckpoint({ user_id: 'temporary' })).resolves.toBeNull();
|
|
441
|
+
}
|
|
442
|
+
);
|
|
414
443
|
}
|
|
415
444
|
|
|
416
445
|
async function createManagedWriteCheckpoint(
|