@powersync/service-module-postgres 0.0.0-dev-20250117095455 → 0.0.0-dev-20250214100224

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +67 -11
  2. package/dist/api/PostgresRouteAPIAdapter.d.ts +2 -1
  3. package/dist/api/PostgresRouteAPIAdapter.js +22 -10
  4. package/dist/api/PostgresRouteAPIAdapter.js.map +1 -1
  5. package/dist/auth/SupabaseKeyCollector.js +6 -5
  6. package/dist/auth/SupabaseKeyCollector.js.map +1 -1
  7. package/dist/module/PostgresModule.d.ts +4 -2
  8. package/dist/module/PostgresModule.js +13 -5
  9. package/dist/module/PostgresModule.js.map +1 -1
  10. package/dist/replication/ConnectionManagerFactory.d.ts +1 -1
  11. package/dist/replication/ConnectionManagerFactory.js +2 -0
  12. package/dist/replication/ConnectionManagerFactory.js.map +1 -1
  13. package/dist/replication/PgManager.d.ts +5 -0
  14. package/dist/replication/PgManager.js +17 -2
  15. package/dist/replication/PgManager.js.map +1 -1
  16. package/dist/replication/PgRelation.js +2 -1
  17. package/dist/replication/PgRelation.js.map +1 -1
  18. package/dist/replication/PostgresErrorRateLimiter.js +5 -7
  19. package/dist/replication/PostgresErrorRateLimiter.js.map +1 -1
  20. package/dist/replication/WalStream.d.ts +18 -3
  21. package/dist/replication/WalStream.js +133 -22
  22. package/dist/replication/WalStream.js.map +1 -1
  23. package/dist/replication/WalStreamReplicationJob.js +7 -5
  24. package/dist/replication/WalStreamReplicationJob.js.map +1 -1
  25. package/dist/replication/WalStreamReplicator.d.ts +1 -0
  26. package/dist/replication/WalStreamReplicator.js +6 -1
  27. package/dist/replication/WalStreamReplicator.js.map +1 -1
  28. package/dist/replication/replication-utils.js +4 -4
  29. package/dist/replication/replication-utils.js.map +1 -1
  30. package/dist/utils/migration_lib.js +3 -4
  31. package/dist/utils/migration_lib.js.map +1 -1
  32. package/dist/utils/populate_test_data.js +1 -1
  33. package/dist/utils/populate_test_data.js.map +1 -1
  34. package/package.json +14 -12
  35. package/src/api/PostgresRouteAPIAdapter.ts +19 -9
  36. package/src/module/PostgresModule.ts +22 -5
  37. package/src/replication/ConnectionManagerFactory.ts +1 -1
  38. package/src/replication/PgManager.ts +10 -0
  39. package/src/replication/PgRelation.ts +2 -1
  40. package/src/replication/WalStream.ts +160 -26
  41. package/src/replication/WalStreamReplicationJob.ts +3 -3
  42. package/src/replication/WalStreamReplicator.ts +5 -0
  43. package/src/replication/replication-utils.ts +9 -4
  44. package/src/utils/migration_lib.ts +2 -1
  45. package/test/src/checkpoints.test.ts +70 -0
  46. package/test/src/storage_combination.test.ts +35 -0
  47. package/test/src/util.ts +1 -1
  48. package/test/src/wal_stream_utils.ts +1 -1
  49. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,70 @@
1
+ import { PostgresRouteAPIAdapter } from '@module/api/PostgresRouteAPIAdapter.js';
2
+ import { checkpointUserId, createWriteCheckpoint } from '@powersync/service-core';
3
+ import { describe, test } from 'vitest';
4
+ import { INITIALIZED_MONGO_STORAGE_FACTORY } from './util.js';
5
+ import { WalStreamTestContext } from './wal_stream_utils.js';
6
+
7
+ import timers from 'node:timers/promises';
8
+
9
+ const BASIC_SYNC_RULES = `bucket_definitions:
10
+ global:
11
+ data:
12
+ - SELECT id, description, other FROM "test_data"`;
13
+
14
+ describe('checkpoint tests', () => {
15
+ test('write checkpoints', { timeout: 30_000 }, async () => {
16
+ const factory = INITIALIZED_MONGO_STORAGE_FACTORY;
17
+ await using context = await WalStreamTestContext.open(factory);
18
+
19
+ await context.updateSyncRules(BASIC_SYNC_RULES);
20
+ const { pool } = context;
21
+ const api = new PostgresRouteAPIAdapter(pool);
22
+
23
+ await pool.query(`CREATE TABLE test_data(id text primary key, description text, other text)`);
24
+
25
+ await context.replicateSnapshot();
26
+
27
+ context.startStreaming();
28
+
29
+ const controller = new AbortController();
30
+ try {
31
+ const stream = context.factory.watchWriteCheckpoint(
32
+ checkpointUserId('test_user', 'test_client'),
33
+ controller.signal
34
+ );
35
+
36
+ let lastWriteCheckpoint: bigint | null = null;
37
+
38
+ (async () => {
39
+ try {
40
+ for await (const cp of stream) {
41
+ lastWriteCheckpoint = cp.writeCheckpoint;
42
+ }
43
+ } catch (e) {
44
+ if (e.name != 'AbortError') {
45
+ throw e;
46
+ }
47
+ }
48
+ })();
49
+
50
+ for (let i = 0; i < 10; i++) {
51
+ const cp = await createWriteCheckpoint({
52
+ userId: 'test_user',
53
+ clientId: 'test_client',
54
+ api,
55
+ storage: context.factory
56
+ });
57
+
58
+ const start = Date.now();
59
+ while (lastWriteCheckpoint == null || lastWriteCheckpoint < BigInt(cp.writeCheckpoint)) {
60
+ if (Date.now() - start > 2_000) {
61
+ throw new Error(`Timeout while waiting for checkpoint`);
62
+ }
63
+ await timers.setTimeout(0, undefined, { signal: controller.signal });
64
+ }
65
+ }
66
+ } finally {
67
+ controller.abort();
68
+ }
69
+ });
70
+ });
@@ -0,0 +1,35 @@
1
+ import * as postgres_storage from '@powersync/service-module-postgres-storage';
2
+ import { describe, expect, test } from 'vitest';
3
+ import { env } from './env.js';
4
+ import { WalStreamTestContext } from './wal_stream_utils.js';
5
+
6
+ describe.skipIf(!env.TEST_POSTGRES_STORAGE)('replication storage combination - postgres', function () {
7
+ test('should allow the same Postgres cluster to be used for data and storage', async () => {
8
+ // Use the same cluster for the storage as the data source
9
+ await using context = await WalStreamTestContext.open(
10
+ postgres_storage.PostgresTestStorageFactoryGenerator({
11
+ url: env.PG_TEST_URL
12
+ }),
13
+ { doNotClear: false }
14
+ );
15
+
16
+ await context.updateSyncRules(/* yaml */
17
+ ` bucket_definitions:
18
+ global:
19
+ data:
20
+ - SELECT * FROM "test_data" `);
21
+
22
+ const { pool, connectionManager } = context;
23
+
24
+ const sourceVersion = await connectionManager.getServerVersion();
25
+
26
+ await pool.query(`CREATE TABLE test_data(id text primary key, description text, other text)`);
27
+
28
+ if (sourceVersion!.compareMain('14.0.0') < 0) {
29
+ await expect(context.replicateSnapshot()).rejects.toThrow();
30
+ } else {
31
+ // Should resolve
32
+ await context.replicateSnapshot();
33
+ }
34
+ });
35
+ });
package/test/src/util.ts CHANGED
@@ -68,7 +68,7 @@ export async function getClientCheckpoint(
68
68
  const start = Date.now();
69
69
 
70
70
  const api = new PostgresRouteAPIAdapter(db);
71
- const lsn = await api.getReplicationHead();
71
+ const lsn = await api.createReplicationHead(async (lsn) => lsn);
72
72
 
73
73
  // This old API needs a persisted checkpoint id.
74
74
  // Since we don't use LSNs anymore, the only way to get that is to wait.
@@ -62,7 +62,7 @@ export class WalStreamTestContext implements AsyncDisposable {
62
62
  }
63
63
 
64
64
  async updateSyncRules(content: string) {
65
- const syncRules = await this.factory.updateSyncRules({ content: content });
65
+ const syncRules = await this.factory.updateSyncRules({ content: content, validate: true });
66
66
  this.storage = this.factory.getInstance(syncRules);
67
67
  return this.storage!;
68
68
  }