@powersync/service-module-postgres 0.0.0-dev-20241210162153 → 0.0.0-dev-20241219091224
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 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/module/PostgresModule.js +1 -1
- package/dist/module/PostgresModule.js.map +1 -1
- package/dist/replication/WalStream.js +12 -3
- package/dist/replication/WalStream.js.map +1 -1
- package/dist/types/types.d.ts +2 -0
- package/dist/types/types.js +3 -0
- package/dist/types/types.js.map +1 -1
- package/package.json +10 -8
- package/src/index.ts +2 -0
- package/src/module/PostgresModule.ts +1 -1
- package/src/replication/WalStream.ts +13 -4
- package/src/types/types.ts +6 -0
- package/test/src/env.ts +1 -0
- package/test/src/large_batch.test.ts +6 -6
- package/test/src/schema_changes.test.ts +8 -10
- package/test/src/slow_tests.test.ts +11 -12
- package/test/src/util.ts +20 -7
- package/test/src/validation.test.ts +4 -2
- package/test/src/wal_stream.test.ts +52 -3
- package/test/src/wal_stream_utils.ts +14 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { putOp, removeOp } from '@core-tests/stream_utils.js';
|
|
2
|
-
import { MONGO_STORAGE_FACTORY } from '@core-tests/util.js';
|
|
3
1
|
import { BucketStorageFactory, Metrics } from '@powersync/service-core';
|
|
2
|
+
import { putOp, removeOp } from '@powersync/service-core-tests';
|
|
4
3
|
import { pgwireRows } from '@powersync/service-jpgwire';
|
|
5
4
|
import * as crypto from 'crypto';
|
|
6
5
|
import { describe, expect, test } from 'vitest';
|
|
6
|
+
import { INITIALIZED_MONGO_STORAGE_FACTORY } from './util.js';
|
|
7
7
|
import { WalStreamTestContext } from './wal_stream_utils.js';
|
|
8
|
+
import { MissingReplicationSlotError } from '@module/replication/WalStream.js';
|
|
8
9
|
|
|
9
10
|
type StorageFactory = () => Promise<BucketStorageFactory>;
|
|
10
11
|
|
|
@@ -16,7 +17,7 @@ bucket_definitions:
|
|
|
16
17
|
`;
|
|
17
18
|
|
|
18
19
|
describe('wal stream - mongodb', { timeout: 20_000 }, function () {
|
|
19
|
-
defineWalStreamTests(
|
|
20
|
+
defineWalStreamTests(INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
function defineWalStreamTests(factory: StorageFactory) {
|
|
@@ -291,4 +292,52 @@ bucket_definitions:
|
|
|
291
292
|
expect(endRowCount - startRowCount).toEqual(0);
|
|
292
293
|
expect(endTxCount - startTxCount).toEqual(1);
|
|
293
294
|
});
|
|
295
|
+
|
|
296
|
+
test('reporting slot issues', async () => {
|
|
297
|
+
{
|
|
298
|
+
await using context = await WalStreamTestContext.open(factory);
|
|
299
|
+
const { pool } = context;
|
|
300
|
+
await context.updateSyncRules(`
|
|
301
|
+
bucket_definitions:
|
|
302
|
+
global:
|
|
303
|
+
data:
|
|
304
|
+
- SELECT id, description FROM "test_data"`);
|
|
305
|
+
|
|
306
|
+
await pool.query(
|
|
307
|
+
`CREATE TABLE test_data(id uuid primary key default uuid_generate_v4(), description text, num int8)`
|
|
308
|
+
);
|
|
309
|
+
await pool.query(
|
|
310
|
+
`INSERT INTO test_data(id, description) VALUES('8133cd37-903b-4937-a022-7c8294015a3a', 'test1') returning id as test_id`
|
|
311
|
+
);
|
|
312
|
+
await context.replicateSnapshot();
|
|
313
|
+
await context.startStreaming();
|
|
314
|
+
|
|
315
|
+
const data = await context.getBucketData('global[]');
|
|
316
|
+
|
|
317
|
+
expect(data).toMatchObject([
|
|
318
|
+
putOp('test_data', {
|
|
319
|
+
id: '8133cd37-903b-4937-a022-7c8294015a3a',
|
|
320
|
+
description: 'test1'
|
|
321
|
+
})
|
|
322
|
+
]);
|
|
323
|
+
|
|
324
|
+
expect(await context.storage!.getStatus()).toMatchObject({ active: true, snapshot_done: true });
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
{
|
|
328
|
+
await using context = await WalStreamTestContext.open(factory, { doNotClear: true });
|
|
329
|
+
const { pool } = context;
|
|
330
|
+
await pool.query('DROP PUBLICATION powersync');
|
|
331
|
+
await pool.query(`UPDATE test_data SET description = 'updated'`);
|
|
332
|
+
await pool.query('CREATE PUBLICATION powersync FOR ALL TABLES');
|
|
333
|
+
|
|
334
|
+
await context.loadActiveSyncRules();
|
|
335
|
+
await expect(async () => {
|
|
336
|
+
await context.replicateSnapshot();
|
|
337
|
+
}).rejects.toThrowError(MissingReplicationSlotError);
|
|
338
|
+
|
|
339
|
+
// The error is handled on a higher level, which triggers
|
|
340
|
+
// creating a new replication slot.
|
|
341
|
+
}
|
|
342
|
+
});
|
|
294
343
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { fromAsync } from '@core-tests/stream_utils.js';
|
|
2
1
|
import { PgManager } from '@module/replication/PgManager.js';
|
|
3
2
|
import { PUBLICATION_NAME, WalStream, WalStreamOptions } from '@module/replication/WalStream.js';
|
|
4
3
|
import { BucketStorageFactory, OplogEntry, SyncRulesBucketStorage } from '@powersync/service-core';
|
|
4
|
+
import { StorageOptions, test_utils } from '@powersync/service-core-tests';
|
|
5
5
|
import * as pgwire from '@powersync/service-jpgwire';
|
|
6
6
|
import { clearTestDb, getClientCheckpoint, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
7
|
-
import { StorageOptions } from '@core-tests/util.js';
|
|
8
7
|
|
|
9
8
|
export class WalStreamTestContext implements AsyncDisposable {
|
|
10
9
|
private _walStream?: WalStream;
|
|
@@ -77,6 +76,16 @@ export class WalStreamTestContext implements AsyncDisposable {
|
|
|
77
76
|
return this.storage!;
|
|
78
77
|
}
|
|
79
78
|
|
|
79
|
+
async loadActiveSyncRules() {
|
|
80
|
+
const syncRules = await this.factory.getActiveSyncRulesContent();
|
|
81
|
+
if (syncRules == null) {
|
|
82
|
+
throw new Error(`Active sync rules not available`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.storage = this.factory.getInstance(syncRules);
|
|
86
|
+
return this.storage!;
|
|
87
|
+
}
|
|
88
|
+
|
|
80
89
|
get walStream() {
|
|
81
90
|
if (this.storage == null) {
|
|
82
91
|
throw new Error('updateSyncRules() first');
|
|
@@ -122,7 +131,7 @@ export class WalStreamTestContext implements AsyncDisposable {
|
|
|
122
131
|
async getBucketsDataBatch(buckets: Record<string, string>, options?: { timeout?: number }) {
|
|
123
132
|
let checkpoint = await this.getCheckpoint(options);
|
|
124
133
|
const map = new Map<string, string>(Object.entries(buckets));
|
|
125
|
-
return fromAsync(this.storage!.getBucketDataBatch(checkpoint, map));
|
|
134
|
+
return test_utils.fromAsync(this.storage!.getBucketDataBatch(checkpoint, map));
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
/**
|
|
@@ -136,7 +145,7 @@ export class WalStreamTestContext implements AsyncDisposable {
|
|
|
136
145
|
while (true) {
|
|
137
146
|
const batch = this.storage!.getBucketDataBatch(checkpoint, map);
|
|
138
147
|
|
|
139
|
-
const batches = await fromAsync(batch);
|
|
148
|
+
const batches = await test_utils.fromAsync(batch);
|
|
140
149
|
data = data.concat(batches[0]?.batch.data ?? []);
|
|
141
150
|
if (batches.length == 0 || !batches[0]!.batch.has_more) {
|
|
142
151
|
break;
|
|
@@ -154,7 +163,7 @@ export class WalStreamTestContext implements AsyncDisposable {
|
|
|
154
163
|
const { checkpoint } = await this.storage!.getCheckpoint();
|
|
155
164
|
const map = new Map<string, string>([[bucket, start]]);
|
|
156
165
|
const batch = this.storage!.getBucketDataBatch(checkpoint, map);
|
|
157
|
-
const batches = await fromAsync(batch);
|
|
166
|
+
const batches = await test_utils.fromAsync(batch);
|
|
158
167
|
return batches[0]?.batch.data ?? [];
|
|
159
168
|
}
|
|
160
169
|
}
|