@powersync/service-core-tests 0.0.0-dev-20250804094552 → 0.0.0-dev-20250811145516

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.
@@ -0,0 +1,172 @@
1
+ import { storage } from '@powersync/service-core';
2
+ import { ParameterLookup } from '@powersync/service-sync-rules';
3
+ import { expect, test } from 'vitest';
4
+ import * as test_utils from '../test-utils/test-utils-index.js';
5
+
6
+ const TEST_TABLE = test_utils.makeTestTable('test', ['id']);
7
+
8
+ export function registerParameterCompactTests(generateStorageFactory: storage.TestStorageFactory) {
9
+ test('compacting parameters', async () => {
10
+ await using factory = await generateStorageFactory();
11
+ const syncRules = await factory.updateSyncRules({
12
+ content: `
13
+ bucket_definitions:
14
+ test:
15
+ parameters: select id from test where id = request.user_id()
16
+ data: []
17
+ `
18
+ });
19
+ const bucketStorage = factory.getInstance(syncRules);
20
+
21
+ await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
22
+ await batch.save({
23
+ sourceTable: TEST_TABLE,
24
+ tag: storage.SaveOperationTag.INSERT,
25
+ after: {
26
+ id: 't1'
27
+ },
28
+ afterReplicaId: 't1'
29
+ });
30
+
31
+ await batch.save({
32
+ sourceTable: TEST_TABLE,
33
+ tag: storage.SaveOperationTag.INSERT,
34
+ after: {
35
+ id: 't2'
36
+ },
37
+ afterReplicaId: 't2'
38
+ });
39
+
40
+ await batch.commit('1/1');
41
+ });
42
+
43
+ const lookup = ParameterLookup.normalized('test', '1', ['t1']);
44
+
45
+ const checkpoint1 = await bucketStorage.getCheckpoint();
46
+ const parameters1 = await checkpoint1.getParameterSets([lookup]);
47
+ expect(parameters1).toEqual([{ id: 't1' }]);
48
+
49
+ await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
50
+ await batch.save({
51
+ sourceTable: TEST_TABLE,
52
+ tag: storage.SaveOperationTag.UPDATE,
53
+ before: {
54
+ id: 't1'
55
+ },
56
+ beforeReplicaId: 't1',
57
+ after: {
58
+ id: 't1'
59
+ },
60
+ afterReplicaId: 't1'
61
+ });
62
+
63
+ await batch.save({
64
+ sourceTable: TEST_TABLE,
65
+ tag: storage.SaveOperationTag.DELETE,
66
+ before: {
67
+ id: 't1'
68
+ },
69
+ beforeReplicaId: 't1'
70
+ });
71
+ await batch.commit('1/2');
72
+ });
73
+ const checkpoint2 = await bucketStorage.getCheckpoint();
74
+ const parameters2 = await checkpoint2.getParameterSets([lookup]);
75
+ expect(parameters2).toEqual([]);
76
+
77
+ const statsBefore = await bucketStorage.factory.getStorageMetrics();
78
+ await bucketStorage.compact({ compactParameterData: true });
79
+
80
+ // Check consistency
81
+ const parameters1b = await checkpoint1.getParameterSets([lookup]);
82
+ const parameters2b = await checkpoint2.getParameterSets([lookup]);
83
+ expect(parameters1b).toEqual([{ id: 't1' }]);
84
+ expect(parameters2b).toEqual([]);
85
+
86
+ // Check storage size
87
+ const statsAfter = await bucketStorage.factory.getStorageMetrics();
88
+ expect(statsAfter.parameters_size_bytes).toBeLessThan(statsBefore.parameters_size_bytes);
89
+ });
90
+
91
+ for (let cacheLimit of [1, 10]) {
92
+ test(`compacting deleted parameters with cache size ${cacheLimit}`, async () => {
93
+ await using factory = await generateStorageFactory();
94
+ const syncRules = await factory.updateSyncRules({
95
+ content: `
96
+ bucket_definitions:
97
+ test:
98
+ parameters: select id from test where uid = request.user_id()
99
+ data: []
100
+ `
101
+ });
102
+ const bucketStorage = factory.getInstance(syncRules);
103
+
104
+ await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
105
+ await batch.save({
106
+ sourceTable: TEST_TABLE,
107
+ tag: storage.SaveOperationTag.INSERT,
108
+ after: {
109
+ id: 't1',
110
+ uid: 'u1'
111
+ },
112
+ afterReplicaId: 't1'
113
+ });
114
+ // Interleave with another operation, to evict the other cache entry when compacting.
115
+ await batch.save({
116
+ sourceTable: TEST_TABLE,
117
+ tag: storage.SaveOperationTag.INSERT,
118
+ after: {
119
+ id: 't2',
120
+ uid: 'u1'
121
+ },
122
+ afterReplicaId: 't2'
123
+ });
124
+
125
+ await batch.commit('1/1');
126
+ });
127
+
128
+ await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
129
+ await batch.save({
130
+ sourceTable: TEST_TABLE,
131
+ tag: storage.SaveOperationTag.DELETE,
132
+ before: {
133
+ id: 't1',
134
+ uid: 'u1'
135
+ },
136
+ beforeReplicaId: 't1'
137
+ });
138
+ await batch.commit('2/1');
139
+ });
140
+
141
+ await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
142
+ await batch.save({
143
+ sourceTable: TEST_TABLE,
144
+ tag: storage.SaveOperationTag.UPDATE,
145
+ after: {
146
+ id: 't2',
147
+ uid: 'u2'
148
+ },
149
+ afterReplicaId: 't2'
150
+ });
151
+ await batch.commit('3/1');
152
+ });
153
+
154
+ const lookup = ParameterLookup.normalized('test', '1', ['u1']);
155
+
156
+ const checkpoint1 = await bucketStorage.getCheckpoint();
157
+ const parameters1 = await checkpoint1.getParameterSets([lookup]);
158
+ expect(parameters1).toEqual([]);
159
+
160
+ const statsBefore = await bucketStorage.factory.getStorageMetrics();
161
+ await bucketStorage.compact({ compactParameterData: true, compactParameterCacheLimit: cacheLimit });
162
+
163
+ // Check consistency
164
+ const parameters1b = await checkpoint1.getParameterSets([lookup]);
165
+ expect(parameters1b).toEqual([]);
166
+
167
+ // Check storage size
168
+ const statsAfter = await bucketStorage.factory.getStorageMetrics();
169
+ expect(statsAfter.parameters_size_bytes).toBeLessThan(statsBefore.parameters_size_bytes);
170
+ });
171
+ }
172
+ }
@@ -1,5 +1,6 @@
1
1
  export * from './register-bucket-validation-tests.js';
2
2
  export * from './register-compacting-tests.js';
3
+ export * from './register-parameter-compacting-tests.js';
3
4
  export * from './register-data-storage-tests.js';
4
5
  export * from './register-migration-tests.js';
5
6
  export * from './register-sync-tests.js';