@powersync/service-module-mysql 0.1.6 → 0.1.8
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 +28 -0
- package/dist/common/mysql-to-sqlite.js +39 -9
- package/dist/common/mysql-to-sqlite.js.map +1 -1
- package/dist/replication/BinLogStream.js +63 -33
- package/dist/replication/BinLogStream.js.map +1 -1
- package/dist/replication/MySQLConnectionManager.js +9 -1
- package/dist/replication/MySQLConnectionManager.js.map +1 -1
- package/dist/utils/mysql-utils.d.ts +2 -0
- package/dist/utils/mysql-utils.js +3 -0
- package/dist/utils/mysql-utils.js.map +1 -1
- package/package.json +9 -7
- package/src/common/mysql-to-sqlite.ts +35 -9
- package/src/replication/BinLogStream.ts +74 -35
- package/src/replication/MySQLConnectionManager.ts +8 -1
- package/src/replication/zongji/zongji.d.ts +10 -0
- package/src/utils/mysql-utils.ts +5 -0
- package/test/src/BinLogStream.test.ts +257 -230
- package/test/src/BinlogStreamUtils.ts +48 -29
- package/test/src/env.ts +1 -0
- package/test/src/mysql-to-sqlite.test.ts +36 -19
- package/test/src/setup.ts +3 -1
- package/test/src/util.ts +6 -25
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { BucketStorageFactory, Metrics } from '@powersync/service-core';
|
|
4
|
-
import { describe, expect, test } from 'vitest';
|
|
5
|
-
import { binlogStreamTest } from './BinlogStreamUtils.js';
|
|
1
|
+
import { Metrics, storage } from '@powersync/service-core';
|
|
2
|
+
import { putOp, removeOp } from '@powersync/service-core-tests';
|
|
6
3
|
import { v4 as uuid } from 'uuid';
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import { describe, expect, test } from 'vitest';
|
|
5
|
+
import { BinlogStreamTestContext } from './BinlogStreamUtils.js';
|
|
6
|
+
import { INITIALIZED_MONGO_STORAGE_FACTORY } from './util.js';
|
|
9
7
|
|
|
10
8
|
const BASIC_SYNC_RULES = `
|
|
11
9
|
bucket_definitions:
|
|
@@ -17,89 +15,82 @@ bucket_definitions:
|
|
|
17
15
|
describe(
|
|
18
16
|
' Binlog stream - mongodb',
|
|
19
17
|
function () {
|
|
20
|
-
defineBinlogStreamTests(
|
|
18
|
+
defineBinlogStreamTests(INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
21
19
|
},
|
|
22
20
|
{ timeout: 20_000 }
|
|
23
21
|
);
|
|
24
22
|
|
|
25
|
-
function defineBinlogStreamTests(factory:
|
|
26
|
-
test(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
await context.updateSyncRules(`
|
|
23
|
+
function defineBinlogStreamTests(factory: storage.TestStorageFactory) {
|
|
24
|
+
test('Replicate basic values', async () => {
|
|
25
|
+
await using context = await BinlogStreamTestContext.open(factory);
|
|
26
|
+
const { connectionManager } = context;
|
|
27
|
+
await context.updateSyncRules(`
|
|
31
28
|
bucket_definitions:
|
|
32
29
|
global:
|
|
33
30
|
data:
|
|
34
31
|
- SELECT id, description, num FROM "test_data"`);
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
binlogStreamTest(factory, async (context) => {
|
|
64
|
-
const { connectionManager } = context;
|
|
65
|
-
await context.updateSyncRules(`
|
|
33
|
+
await connectionManager.query(`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description TEXT, num BIGINT)`);
|
|
34
|
+
|
|
35
|
+
await context.replicateSnapshot();
|
|
36
|
+
|
|
37
|
+
const startRowCount = (await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
38
|
+
const startTxCount =
|
|
39
|
+
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
40
|
+
|
|
41
|
+
context.startStreaming();
|
|
42
|
+
const testId = uuid();
|
|
43
|
+
await connectionManager.query(
|
|
44
|
+
`INSERT INTO test_data(id, description, num) VALUES('${testId}', 'test1', 1152921504606846976)`
|
|
45
|
+
);
|
|
46
|
+
const data = await context.getBucketData('global[]');
|
|
47
|
+
|
|
48
|
+
expect(data).toMatchObject([putOp('test_data', { id: testId, description: 'test1', num: 1152921504606846976n })]);
|
|
49
|
+
const endRowCount = (await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
50
|
+
const endTxCount =
|
|
51
|
+
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
52
|
+
expect(endRowCount - startRowCount).toEqual(1);
|
|
53
|
+
expect(endTxCount - startTxCount).toEqual(1);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('replicating case sensitive table', async () => {
|
|
57
|
+
await using context = await BinlogStreamTestContext.open(factory);
|
|
58
|
+
const { connectionManager } = context;
|
|
59
|
+
await context.updateSyncRules(`
|
|
66
60
|
bucket_definitions:
|
|
67
61
|
global:
|
|
68
62
|
data:
|
|
69
63
|
- SELECT id, description FROM "test_DATA"
|
|
70
64
|
`);
|
|
71
65
|
|
|
72
|
-
|
|
66
|
+
await connectionManager.query(`CREATE TABLE test_DATA (id CHAR(36) PRIMARY KEY, description text)`);
|
|
73
67
|
|
|
74
|
-
|
|
68
|
+
await context.replicateSnapshot();
|
|
75
69
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
70
|
+
const startRowCount = (await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
71
|
+
const startTxCount =
|
|
72
|
+
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
80
73
|
|
|
81
|
-
|
|
74
|
+
context.startStreaming();
|
|
82
75
|
|
|
83
|
-
|
|
84
|
-
|
|
76
|
+
const testId = uuid();
|
|
77
|
+
await connectionManager.query(`INSERT INTO test_DATA(id, description) VALUES('${testId}','test1')`);
|
|
85
78
|
|
|
86
|
-
|
|
79
|
+
const data = await context.getBucketData('global[]');
|
|
80
|
+
|
|
81
|
+
expect(data).toMatchObject([putOp('test_DATA', { id: testId, description: 'test1' })]);
|
|
82
|
+
const endRowCount = (await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
83
|
+
const endTxCount =
|
|
84
|
+
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
85
|
+
expect(endRowCount - startRowCount).toEqual(1);
|
|
86
|
+
expect(endTxCount - startTxCount).toEqual(1);
|
|
87
|
+
});
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
expect(endTxCount - startTxCount).toEqual(1);
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
// TODO: Not supported yet
|
|
98
|
-
// test(
|
|
99
|
-
// 'replicating TRUNCATE',
|
|
100
|
-
// binlogStreamTest(factory, async (context) => {
|
|
101
|
-
// const { connectionManager } = context;
|
|
102
|
-
// const syncRuleContent = `
|
|
89
|
+
// TODO: Not supported yet
|
|
90
|
+
// test('replicating TRUNCATE', async () => {
|
|
91
|
+
// await using context = await BinlogStreamTestContext.create(factory);
|
|
92
|
+
// const { connectionManager } = context;
|
|
93
|
+
// const syncRuleContent = `
|
|
103
94
|
// bucket_definitions:
|
|
104
95
|
// global:
|
|
105
96
|
// data:
|
|
@@ -108,199 +99,235 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
108
99
|
// parameters: SELECT id FROM test_data WHERE id = token_parameters.user_id
|
|
109
100
|
// data: []
|
|
110
101
|
// `;
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
// );
|
|
116
|
-
//
|
|
117
|
-
// await context.replicateSnapshot();
|
|
118
|
-
// context.startStreaming();
|
|
119
|
-
//
|
|
120
|
-
// const [{ test_id }] = pgwireRows(
|
|
121
|
-
// await connectionManager.query(`INSERT INTO test_data(description) VALUES('test1') returning id as test_id`)
|
|
122
|
-
// );
|
|
123
|
-
// await connectionManager.query(`TRUNCATE test_data`);
|
|
124
|
-
//
|
|
125
|
-
// const data = await context.getBucketData('global[]');
|
|
126
|
-
//
|
|
127
|
-
// expect(data).toMatchObject([
|
|
128
|
-
// putOp('test_data', { id: test_id, description: 'test1' }),
|
|
129
|
-
// removeOp('test_data', test_id)
|
|
130
|
-
// ]);
|
|
131
|
-
// })
|
|
102
|
+
// await context.updateSyncRules(syncRuleContent);
|
|
103
|
+
// await connectionManager.query(`DROP TABLE IF EXISTS test_data`);
|
|
104
|
+
// await connectionManager.query(
|
|
105
|
+
// `CREATE TABLE test_data(id uuid primary key default uuid_generate_v4(), description text)`
|
|
132
106
|
// );
|
|
133
107
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
binlogStreamTest(factory, async (context) => {
|
|
137
|
-
const { connectionManager } = context;
|
|
138
|
-
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
139
|
-
|
|
140
|
-
await connectionManager.query(`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description text)`);
|
|
141
|
-
|
|
142
|
-
await context.replicateSnapshot();
|
|
143
|
-
context.startStreaming();
|
|
144
|
-
|
|
145
|
-
const testId1 = uuid();
|
|
146
|
-
await connectionManager.query(`INSERT INTO test_data(id, description) VALUES('${testId1}','test1')`);
|
|
147
|
-
|
|
148
|
-
const testId2 = uuid();
|
|
149
|
-
await connectionManager.query(
|
|
150
|
-
`UPDATE test_data SET id = '${testId2}', description = 'test2a' WHERE id = '${testId1}'`
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
// This update may fail replicating with:
|
|
154
|
-
// Error: Update on missing record public.test_data:074a601e-fc78-4c33-a15d-f89fdd4af31d :: {"g":1,"t":"651e9fbe9fec6155895057ec","k":"1a0b34da-fb8c-5e6f-8421-d7a3c5d4df4f"}
|
|
155
|
-
await connectionManager.query(`UPDATE test_data SET description = 'test2b' WHERE id = '${testId2}'`);
|
|
108
|
+
// await context.replicateSnapshot();
|
|
109
|
+
// context.startStreaming();
|
|
156
110
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
111
|
+
// const [{ test_id }] = pgwireRows(
|
|
112
|
+
// await connectionManager.query(`INSERT INTO test_data(description) VALUES('test1') returning id as test_id`)
|
|
113
|
+
// );
|
|
114
|
+
// await connectionManager.query(`TRUNCATE test_data`);
|
|
115
|
+
|
|
116
|
+
// const data = await context.getBucketData('global[]');
|
|
117
|
+
|
|
118
|
+
// expect(data).toMatchObject([
|
|
119
|
+
// putOp('test_data', { id: test_id, description: 'test1' }),
|
|
120
|
+
// removeOp('test_data', test_id)
|
|
121
|
+
// ]);
|
|
122
|
+
// });
|
|
123
|
+
|
|
124
|
+
test('replicating changing primary key', async () => {
|
|
125
|
+
await using context = await BinlogStreamTestContext.open(factory);
|
|
126
|
+
const { connectionManager } = context;
|
|
127
|
+
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
128
|
+
|
|
129
|
+
await connectionManager.query(`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description text)`);
|
|
130
|
+
|
|
131
|
+
await context.replicateSnapshot();
|
|
132
|
+
context.startStreaming();
|
|
133
|
+
|
|
134
|
+
const testId1 = uuid();
|
|
135
|
+
await connectionManager.query(`INSERT INTO test_data(id, description) VALUES('${testId1}','test1')`);
|
|
136
|
+
|
|
137
|
+
const testId2 = uuid();
|
|
138
|
+
await connectionManager.query(
|
|
139
|
+
`UPDATE test_data SET id = '${testId2}', description = 'test2a' WHERE id = '${testId1}'`
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// This update may fail replicating with:
|
|
143
|
+
// Error: Update on missing record public.test_data:074a601e-fc78-4c33-a15d-f89fdd4af31d :: {"g":1,"t":"651e9fbe9fec6155895057ec","k":"1a0b34da-fb8c-5e6f-8421-d7a3c5d4df4f"}
|
|
144
|
+
await connectionManager.query(`UPDATE test_data SET description = 'test2b' WHERE id = '${testId2}'`);
|
|
145
|
+
|
|
146
|
+
// Re-use old id again
|
|
147
|
+
await connectionManager.query(`INSERT INTO test_data(id, description) VALUES('${testId1}', 'test1b')`);
|
|
148
|
+
await connectionManager.query(`UPDATE test_data SET description = 'test1c' WHERE id = '${testId1}'`);
|
|
149
|
+
|
|
150
|
+
const data = await context.getBucketData('global[]');
|
|
151
|
+
expect(data).toMatchObject([
|
|
152
|
+
// Initial insert
|
|
153
|
+
putOp('test_data', { id: testId1, description: 'test1' }),
|
|
154
|
+
// Update id, then description
|
|
155
|
+
removeOp('test_data', testId1),
|
|
156
|
+
putOp('test_data', { id: testId2, description: 'test2a' }),
|
|
157
|
+
putOp('test_data', { id: testId2, description: 'test2b' }),
|
|
158
|
+
// Re-use old id
|
|
159
|
+
putOp('test_data', { id: testId1, description: 'test1b' }),
|
|
160
|
+
putOp('test_data', { id: testId1, description: 'test1c' })
|
|
161
|
+
]);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test('initial sync', async () => {
|
|
165
|
+
await using context = await BinlogStreamTestContext.open(factory);
|
|
166
|
+
const { connectionManager } = context;
|
|
167
|
+
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
168
|
+
|
|
169
|
+
await connectionManager.query(`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description text)`);
|
|
170
|
+
|
|
171
|
+
const testId = uuid();
|
|
172
|
+
await connectionManager.query(`INSERT INTO test_data(id, description) VALUES('${testId}','test1')`);
|
|
173
|
+
|
|
174
|
+
await context.replicateSnapshot();
|
|
175
|
+
|
|
176
|
+
const data = await context.getBucketData('global[]');
|
|
177
|
+
expect(data).toMatchObject([putOp('test_data', { id: testId, description: 'test1' })]);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('snapshot with date values', async () => {
|
|
181
|
+
await using context = await BinlogStreamTestContext.open(factory);
|
|
182
|
+
const { connectionManager } = context;
|
|
183
|
+
await context.updateSyncRules(`
|
|
199
184
|
bucket_definitions:
|
|
200
185
|
global:
|
|
201
186
|
data:
|
|
202
187
|
- SELECT * FROM "test_data"
|
|
203
188
|
`);
|
|
204
189
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
190
|
+
await connectionManager.query(
|
|
191
|
+
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description TEXT, date DATE, datetime DATETIME, timestamp TIMESTAMP)`
|
|
192
|
+
);
|
|
208
193
|
|
|
209
|
-
|
|
210
|
-
|
|
194
|
+
const testId = uuid();
|
|
195
|
+
await connectionManager.query(`
|
|
211
196
|
INSERT INTO test_data(id, description, date, datetime, timestamp) VALUES('${testId}','testDates', '2023-03-06', '2023-03-06 15:47', '2023-03-06 15:47')
|
|
212
197
|
`);
|
|
213
198
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const { connectionManager } = context;
|
|
233
|
-
await context.updateSyncRules(`
|
|
199
|
+
await context.replicateSnapshot();
|
|
200
|
+
|
|
201
|
+
const data = await context.getBucketData('global[]');
|
|
202
|
+
expect(data).toMatchObject([
|
|
203
|
+
putOp('test_data', {
|
|
204
|
+
id: testId,
|
|
205
|
+
description: 'testDates',
|
|
206
|
+
date: `2023-03-06`,
|
|
207
|
+
datetime: '2023-03-06T15:47:00.000Z',
|
|
208
|
+
timestamp: '2023-03-06T15:47:00.000Z'
|
|
209
|
+
})
|
|
210
|
+
]);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test('replication with date values', async () => {
|
|
214
|
+
await using context = await BinlogStreamTestContext.open(factory);
|
|
215
|
+
const { connectionManager } = context;
|
|
216
|
+
await context.updateSyncRules(`
|
|
234
217
|
bucket_definitions:
|
|
235
218
|
global:
|
|
236
219
|
data:
|
|
237
220
|
- SELECT * FROM "test_data"
|
|
238
221
|
`);
|
|
239
222
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
223
|
+
await connectionManager.query(
|
|
224
|
+
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description TEXT, date DATE, datetime DATETIME NULL, timestamp TIMESTAMP NULL)`
|
|
225
|
+
);
|
|
243
226
|
|
|
244
|
-
|
|
227
|
+
await context.replicateSnapshot();
|
|
245
228
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
229
|
+
const startRowCount = (await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
230
|
+
const startTxCount =
|
|
231
|
+
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
250
232
|
|
|
251
|
-
|
|
233
|
+
context.startStreaming();
|
|
252
234
|
|
|
253
|
-
|
|
254
|
-
|
|
235
|
+
const testId = uuid();
|
|
236
|
+
await connectionManager.query(`
|
|
255
237
|
INSERT INTO test_data(id, description, date, datetime, timestamp) VALUES('${testId}','testDates', '2023-03-06', '2023-03-06 15:47', '2023-03-06 15:47')
|
|
256
238
|
`);
|
|
239
|
+
await connectionManager.query(`UPDATE test_data SET description = ? WHERE id = ?`, ['testUpdated', testId]);
|
|
240
|
+
|
|
241
|
+
const data = await context.getBucketData('global[]');
|
|
242
|
+
expect(data).toMatchObject([
|
|
243
|
+
putOp('test_data', {
|
|
244
|
+
id: testId,
|
|
245
|
+
description: 'testDates',
|
|
246
|
+
date: `2023-03-06`,
|
|
247
|
+
datetime: '2023-03-06T15:47:00.000Z',
|
|
248
|
+
timestamp: '2023-03-06T15:47:00.000Z'
|
|
249
|
+
}),
|
|
250
|
+
putOp('test_data', {
|
|
251
|
+
id: testId,
|
|
252
|
+
description: 'testUpdated',
|
|
253
|
+
date: `2023-03-06`,
|
|
254
|
+
datetime: '2023-03-06T15:47:00.000Z',
|
|
255
|
+
timestamp: '2023-03-06T15:47:00.000Z'
|
|
256
|
+
})
|
|
257
|
+
]);
|
|
258
|
+
const endRowCount = (await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
259
|
+
const endTxCount =
|
|
260
|
+
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
261
|
+
expect(endRowCount - startRowCount).toEqual(2);
|
|
262
|
+
expect(endTxCount - startTxCount).toEqual(2);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
test('table not in sync rules', async () => {
|
|
266
|
+
await using context = await BinlogStreamTestContext.open(factory);
|
|
267
|
+
const { connectionManager } = context;
|
|
268
|
+
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
269
|
+
|
|
270
|
+
await connectionManager.query(`CREATE TABLE test_donotsync (id CHAR(36) PRIMARY KEY, description text)`);
|
|
271
|
+
|
|
272
|
+
await context.replicateSnapshot();
|
|
273
|
+
|
|
274
|
+
const startRowCount = (await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
275
|
+
const startTxCount =
|
|
276
|
+
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
277
|
+
|
|
278
|
+
context.startStreaming();
|
|
279
|
+
|
|
280
|
+
await connectionManager.query(`INSERT INTO test_donotsync(id, description) VALUES('${uuid()}','test1')`);
|
|
281
|
+
const data = await context.getBucketData('global[]');
|
|
282
|
+
|
|
283
|
+
expect(data).toMatchObject([]);
|
|
284
|
+
const endRowCount = (await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
285
|
+
const endTxCount =
|
|
286
|
+
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
287
|
+
|
|
288
|
+
// There was a transaction, but we should not replicate any actual data
|
|
289
|
+
expect(endRowCount - startRowCount).toEqual(0);
|
|
290
|
+
expect(endTxCount - startTxCount).toEqual(1);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test('Resume replication', async () => {
|
|
294
|
+
const testId1 = uuid();
|
|
295
|
+
const testId2 = uuid();
|
|
296
|
+
{
|
|
297
|
+
await using context = await BinlogStreamTestContext.open(factory);
|
|
298
|
+
const { connectionManager } = context;
|
|
299
|
+
await context.updateSyncRules(`
|
|
300
|
+
bucket_definitions:
|
|
301
|
+
global:
|
|
302
|
+
data:
|
|
303
|
+
- SELECT id, description, num FROM "test_data"`);
|
|
304
|
+
|
|
305
|
+
await connectionManager.query(`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description TEXT, num BIGINT)`);
|
|
257
306
|
|
|
307
|
+
await context.replicateSnapshot();
|
|
308
|
+
context.startStreaming();
|
|
309
|
+
await connectionManager.query(
|
|
310
|
+
`INSERT INTO test_data(id, description, num) VALUES('${testId1}', 'test1', 1152921504606846976)`
|
|
311
|
+
);
|
|
258
312
|
const data = await context.getBucketData('global[]');
|
|
259
313
|
expect(data).toMatchObject([
|
|
260
|
-
putOp('test_data', {
|
|
261
|
-
id: testId,
|
|
262
|
-
description: 'testDates',
|
|
263
|
-
date: `2023-03-06`,
|
|
264
|
-
datetime: '2023-03-06T15:47:00.000Z',
|
|
265
|
-
timestamp: '2023-03-06T15:47:00.000Z'
|
|
266
|
-
})
|
|
314
|
+
putOp('test_data', { id: testId1, description: 'test1', num: 1152921504606846976n })
|
|
267
315
|
]);
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
expect(endRowCount - startRowCount).toEqual(1);
|
|
272
|
-
expect(endTxCount - startTxCount).toEqual(1);
|
|
273
|
-
})
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
test(
|
|
277
|
-
'table not in sync rules',
|
|
278
|
-
binlogStreamTest(factory, async (context) => {
|
|
316
|
+
}
|
|
317
|
+
{
|
|
318
|
+
await using context = await BinlogStreamTestContext.open(factory, { doNotClear: true });
|
|
279
319
|
const { connectionManager } = context;
|
|
280
|
-
await context.
|
|
281
|
-
|
|
282
|
-
await connectionManager.query(`CREATE TABLE test_donotsync (id CHAR(36) PRIMARY KEY, description text)`);
|
|
283
|
-
|
|
320
|
+
await context.loadActiveSyncRules();
|
|
321
|
+
// Does not actually do a snapshot again - just does the required intialization.
|
|
284
322
|
await context.replicateSnapshot();
|
|
285
|
-
|
|
286
|
-
const startRowCount =
|
|
287
|
-
(await Metrics.getInstance().getMetricValueForTests('powersync_rows_replicated_total')) ?? 0;
|
|
288
|
-
const startTxCount =
|
|
289
|
-
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
290
|
-
|
|
291
323
|
context.startStreaming();
|
|
292
|
-
|
|
293
|
-
await connectionManager.query(`INSERT INTO test_donotsync(id, description) VALUES('${uuid()}','test1')`);
|
|
324
|
+
await connectionManager.query(`INSERT INTO test_data(id, description, num) VALUES('${testId2}', 'test2', 0)`);
|
|
294
325
|
const data = await context.getBucketData('global[]');
|
|
295
326
|
|
|
296
|
-
expect(data).toMatchObject([
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
expect(endRowCount - startRowCount).toEqual(0);
|
|
303
|
-
expect(endTxCount - startTxCount).toEqual(1);
|
|
304
|
-
})
|
|
305
|
-
);
|
|
327
|
+
expect(data).toMatchObject([
|
|
328
|
+
putOp('test_data', { id: testId1, description: 'test1', num: 1152921504606846976n }),
|
|
329
|
+
putOp('test_data', { id: testId2, description: 'test2', num: 0n })
|
|
330
|
+
]);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
306
333
|
}
|