@powersync/service-module-postgres 0.0.0-dev-20240918092408
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 +18 -0
- package/LICENSE +67 -0
- package/README.md +3 -0
- package/dist/api/PostgresRouteAPIAdapter.d.ts +22 -0
- package/dist/api/PostgresRouteAPIAdapter.js +273 -0
- package/dist/api/PostgresRouteAPIAdapter.js.map +1 -0
- package/dist/auth/SupabaseKeyCollector.d.ts +22 -0
- package/dist/auth/SupabaseKeyCollector.js +64 -0
- package/dist/auth/SupabaseKeyCollector.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/module/PostgresModule.d.ts +14 -0
- package/dist/module/PostgresModule.js +108 -0
- package/dist/module/PostgresModule.js.map +1 -0
- package/dist/replication/ConnectionManagerFactory.d.ts +10 -0
- package/dist/replication/ConnectionManagerFactory.js +21 -0
- package/dist/replication/ConnectionManagerFactory.js.map +1 -0
- package/dist/replication/PgManager.d.ts +25 -0
- package/dist/replication/PgManager.js +60 -0
- package/dist/replication/PgManager.js.map +1 -0
- package/dist/replication/PgRelation.d.ts +6 -0
- package/dist/replication/PgRelation.js +27 -0
- package/dist/replication/PgRelation.js.map +1 -0
- package/dist/replication/PostgresErrorRateLimiter.d.ts +11 -0
- package/dist/replication/PostgresErrorRateLimiter.js +43 -0
- package/dist/replication/PostgresErrorRateLimiter.js.map +1 -0
- package/dist/replication/WalStream.d.ts +53 -0
- package/dist/replication/WalStream.js +536 -0
- package/dist/replication/WalStream.js.map +1 -0
- package/dist/replication/WalStreamReplicationJob.d.ts +27 -0
- package/dist/replication/WalStreamReplicationJob.js +131 -0
- package/dist/replication/WalStreamReplicationJob.js.map +1 -0
- package/dist/replication/WalStreamReplicator.d.ts +13 -0
- package/dist/replication/WalStreamReplicator.js +36 -0
- package/dist/replication/WalStreamReplicator.js.map +1 -0
- package/dist/replication/replication-index.d.ts +5 -0
- package/dist/replication/replication-index.js +6 -0
- package/dist/replication/replication-index.js.map +1 -0
- package/dist/replication/replication-utils.d.ts +32 -0
- package/dist/replication/replication-utils.js +272 -0
- package/dist/replication/replication-utils.js.map +1 -0
- package/dist/types/types.d.ts +76 -0
- package/dist/types/types.js +110 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/migration_lib.d.ts +11 -0
- package/dist/utils/migration_lib.js +64 -0
- package/dist/utils/migration_lib.js.map +1 -0
- package/dist/utils/pgwire_utils.d.ts +16 -0
- package/dist/utils/pgwire_utils.js +70 -0
- package/dist/utils/pgwire_utils.js.map +1 -0
- package/dist/utils/populate_test_data.d.ts +8 -0
- package/dist/utils/populate_test_data.js +65 -0
- package/dist/utils/populate_test_data.js.map +1 -0
- package/package.json +49 -0
- package/src/api/PostgresRouteAPIAdapter.ts +307 -0
- package/src/auth/SupabaseKeyCollector.ts +70 -0
- package/src/index.ts +5 -0
- package/src/module/PostgresModule.ts +122 -0
- package/src/replication/ConnectionManagerFactory.ts +28 -0
- package/src/replication/PgManager.ts +70 -0
- package/src/replication/PgRelation.ts +31 -0
- package/src/replication/PostgresErrorRateLimiter.ts +44 -0
- package/src/replication/WalStream.ts +639 -0
- package/src/replication/WalStreamReplicationJob.ts +142 -0
- package/src/replication/WalStreamReplicator.ts +45 -0
- package/src/replication/replication-index.ts +5 -0
- package/src/replication/replication-utils.ts +329 -0
- package/src/types/types.ts +159 -0
- package/src/utils/migration_lib.ts +79 -0
- package/src/utils/pgwire_utils.ts +73 -0
- package/src/utils/populate_test_data.ts +77 -0
- package/test/src/__snapshots__/pg_test.test.ts.snap +256 -0
- package/test/src/env.ts +7 -0
- package/test/src/large_batch.test.ts +195 -0
- package/test/src/pg_test.test.ts +450 -0
- package/test/src/schema_changes.test.ts +543 -0
- package/test/src/setup.ts +7 -0
- package/test/src/slow_tests.test.ts +335 -0
- package/test/src/util.ts +105 -0
- package/test/src/validation.test.ts +64 -0
- package/test/src/wal_stream.test.ts +319 -0
- package/test/src/wal_stream_utils.ts +121 -0
- package/test/tsconfig.json +28 -0
- package/tsconfig.json +31 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PgManager } from './PgManager.js';
|
|
2
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
3
|
+
export class ConnectionManagerFactory {
|
|
4
|
+
constructor(dbConnectionConfig) {
|
|
5
|
+
this.dbConnectionConfig = dbConnectionConfig;
|
|
6
|
+
this.connectionManagers = [];
|
|
7
|
+
}
|
|
8
|
+
create(poolOptions) {
|
|
9
|
+
const manager = new PgManager(this.dbConnectionConfig, poolOptions);
|
|
10
|
+
this.connectionManagers.push(manager);
|
|
11
|
+
return manager;
|
|
12
|
+
}
|
|
13
|
+
async shutdown() {
|
|
14
|
+
logger.info('Shutting down Postgres connection Managers...');
|
|
15
|
+
for (const manager of this.connectionManagers) {
|
|
16
|
+
await manager.end();
|
|
17
|
+
}
|
|
18
|
+
logger.info('Postgres connection Managers shutdown completed.');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ConnectionManagerFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConnectionManagerFactory.js","sourceRoot":"","sources":["../../src/replication/ConnectionManagerFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAE3D,MAAM,OAAO,wBAAwB;IAInC,YAAY,kBAAsD;QAChE,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,WAA0B;QAC/B,MAAM,OAAO,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;QACpE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAC7D,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC7C,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC;SACrB;QACD,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAClE,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as pgwire from '@powersync/service-jpgwire';
|
|
2
|
+
import { NormalizedPostgresConnectionConfig } from '../types/types.js';
|
|
3
|
+
export declare class PgManager {
|
|
4
|
+
options: NormalizedPostgresConnectionConfig;
|
|
5
|
+
poolOptions: pgwire.PgPoolOptions;
|
|
6
|
+
/**
|
|
7
|
+
* Do not use this for any transactions.
|
|
8
|
+
*/
|
|
9
|
+
readonly pool: pgwire.PgClient;
|
|
10
|
+
private connectionPromises;
|
|
11
|
+
constructor(options: NormalizedPostgresConnectionConfig, poolOptions: pgwire.PgPoolOptions);
|
|
12
|
+
get connectionTag(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Create a new replication connection.
|
|
15
|
+
*/
|
|
16
|
+
replicationConnection(): Promise<pgwire.PgConnection>;
|
|
17
|
+
/**
|
|
18
|
+
* Create a new standard connection, used for initial snapshot.
|
|
19
|
+
*
|
|
20
|
+
* This connection must not be shared between multiple async contexts.
|
|
21
|
+
*/
|
|
22
|
+
snapshotConnection(): Promise<pgwire.PgConnection>;
|
|
23
|
+
end(): Promise<void>;
|
|
24
|
+
destroy(): Promise<void>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as pgwire from '@powersync/service-jpgwire';
|
|
2
|
+
export class PgManager {
|
|
3
|
+
constructor(options, poolOptions) {
|
|
4
|
+
this.options = options;
|
|
5
|
+
this.poolOptions = poolOptions;
|
|
6
|
+
this.connectionPromises = [];
|
|
7
|
+
// The pool is lazy - no connections are opened until a query is performed.
|
|
8
|
+
this.pool = pgwire.connectPgWirePool(this.options, poolOptions);
|
|
9
|
+
}
|
|
10
|
+
get connectionTag() {
|
|
11
|
+
return this.options.tag;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a new replication connection.
|
|
15
|
+
*/
|
|
16
|
+
async replicationConnection() {
|
|
17
|
+
const p = pgwire.connectPgWire(this.options, { type: 'replication' });
|
|
18
|
+
this.connectionPromises.push(p);
|
|
19
|
+
return await p;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create a new standard connection, used for initial snapshot.
|
|
23
|
+
*
|
|
24
|
+
* This connection must not be shared between multiple async contexts.
|
|
25
|
+
*/
|
|
26
|
+
async snapshotConnection() {
|
|
27
|
+
const p = pgwire.connectPgWire(this.options, { type: 'standard' });
|
|
28
|
+
this.connectionPromises.push(p);
|
|
29
|
+
return await p;
|
|
30
|
+
}
|
|
31
|
+
async end() {
|
|
32
|
+
for (let result of await Promise.allSettled([
|
|
33
|
+
this.pool.end(),
|
|
34
|
+
...this.connectionPromises.map(async (promise) => {
|
|
35
|
+
const connection = await promise;
|
|
36
|
+
return await connection.end();
|
|
37
|
+
})
|
|
38
|
+
])) {
|
|
39
|
+
// Throw the first error, if any
|
|
40
|
+
if (result.status == 'rejected') {
|
|
41
|
+
throw result.reason;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async destroy() {
|
|
46
|
+
this.pool.destroy();
|
|
47
|
+
for (let result of await Promise.allSettled([
|
|
48
|
+
...this.connectionPromises.map(async (promise) => {
|
|
49
|
+
const connection = await promise;
|
|
50
|
+
return connection.destroy();
|
|
51
|
+
})
|
|
52
|
+
])) {
|
|
53
|
+
// Throw the first error, if any
|
|
54
|
+
if (result.status == 'rejected') {
|
|
55
|
+
throw result.reason;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=PgManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PgManager.js","sourceRoot":"","sources":["../../src/replication/PgManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,4BAA4B,CAAC;AAGrD,MAAM,OAAO,SAAS;IAQpB,YAAmB,OAA2C,EAAS,WAAiC;QAArF,YAAO,GAAP,OAAO,CAAoC;QAAS,gBAAW,GAAX,WAAW,CAAsB;QAFhG,uBAAkB,GAAmC,EAAE,CAAC;QAG9D,2EAA2E;QAC3E,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAClE,CAAC;IAED,IAAW,aAAa;QACtB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,qBAAqB;QACzB,MAAM,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChC,OAAO,MAAM,CAAC,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,kBAAkB;QACtB,MAAM,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChC,OAAO,MAAM,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,GAAG;QACP,KAAK,IAAI,MAAM,IAAI,MAAM,OAAO,CAAC,UAAU,CAAC;YAC1C,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACf,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC/C,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC;gBACjC,OAAO,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;YAChC,CAAC,CAAC;SACH,CAAC,EAAE;YACF,gCAAgC;YAChC,IAAI,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE;gBAC/B,MAAM,MAAM,CAAC,MAAM,CAAC;aACrB;SACF;IACH,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,IAAI,MAAM,IAAI,MAAM,OAAO,CAAC,UAAU,CAAC;YAC1C,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC/C,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC;gBACjC,OAAO,UAAU,CAAC,OAAO,EAAE,CAAC;YAC9B,CAAC,CAAC;SACH,CAAC,EAAE;YACF,gCAAgC;YAChC,IAAI,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE;gBAC/B,MAAM,MAAM,CAAC,MAAM,CAAC;aACrB;SACF;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { storage } from '@powersync/service-core';
|
|
2
|
+
import { PgoutputRelation } from '@powersync/service-jpgwire';
|
|
3
|
+
export type ReplicationIdentity = 'default' | 'nothing' | 'full' | 'index';
|
|
4
|
+
export declare function getReplicaIdColumns(relation: PgoutputRelation): storage.ColumnDescriptor[];
|
|
5
|
+
export declare function getRelId(source: PgoutputRelation): number;
|
|
6
|
+
export declare function getPgOutputRelation(source: PgoutputRelation): storage.SourceEntityDescriptor;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function getReplicaIdColumns(relation) {
|
|
2
|
+
if (relation.replicaIdentity == 'nothing') {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
else {
|
|
6
|
+
return relation.columns
|
|
7
|
+
.filter((c) => (c.flags & 0b1) != 0)
|
|
8
|
+
.map((c) => ({ name: c.name, typeId: c.typeOid }));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function getRelId(source) {
|
|
12
|
+
// Source types are wrong here
|
|
13
|
+
const relId = source.relationOid;
|
|
14
|
+
if (!relId) {
|
|
15
|
+
throw new Error(`No relation id!`);
|
|
16
|
+
}
|
|
17
|
+
return relId;
|
|
18
|
+
}
|
|
19
|
+
export function getPgOutputRelation(source) {
|
|
20
|
+
return {
|
|
21
|
+
name: source.name,
|
|
22
|
+
schema: source.schema,
|
|
23
|
+
objectId: getRelId(source),
|
|
24
|
+
replicationColumns: getReplicaIdColumns(source)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=PgRelation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PgRelation.js","sourceRoot":"","sources":["../../src/replication/PgRelation.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,mBAAmB,CAAC,QAA0B;IAC5D,IAAI,QAAQ,CAAC,eAAe,IAAI,SAAS,EAAE;QACzC,OAAO,EAAE,CAAC;KACX;SAAM;QACL,OAAO,QAAQ,CAAC,OAAO;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;aACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAqC,CAAC,CAAC,CAAC;KACzF;AACH,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,MAAwB;IAC/C,8BAA8B;IAC9B,MAAM,KAAK,GAAI,MAAc,CAAC,WAAqB,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;KACpC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAwB;IAC1D,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC;QAC1B,kBAAkB,EAAE,mBAAmB,CAAC,MAAM,CAAC;KACP,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { ErrorRateLimiter } from '@powersync/service-core';
|
|
3
|
+
export declare class PostgresErrorRateLimiter implements ErrorRateLimiter {
|
|
4
|
+
nextAllowed: number;
|
|
5
|
+
waitUntilAllowed(options?: {
|
|
6
|
+
signal?: AbortSignal | undefined;
|
|
7
|
+
} | undefined): Promise<void>;
|
|
8
|
+
mayPing(): boolean;
|
|
9
|
+
reportError(e: any): void;
|
|
10
|
+
private setDelay;
|
|
11
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { setTimeout } from 'timers/promises';
|
|
2
|
+
export class PostgresErrorRateLimiter {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.nextAllowed = Date.now();
|
|
5
|
+
}
|
|
6
|
+
async waitUntilAllowed(options) {
|
|
7
|
+
const delay = Math.max(0, this.nextAllowed - Date.now());
|
|
8
|
+
// Minimum delay between connections, even without errors
|
|
9
|
+
this.setDelay(500);
|
|
10
|
+
await setTimeout(delay, undefined, { signal: options?.signal });
|
|
11
|
+
}
|
|
12
|
+
mayPing() {
|
|
13
|
+
return Date.now() >= this.nextAllowed;
|
|
14
|
+
}
|
|
15
|
+
reportError(e) {
|
|
16
|
+
const message = e.message ?? '';
|
|
17
|
+
if (message.includes('password authentication failed')) {
|
|
18
|
+
// Wait 15 minutes, to avoid triggering Supabase's fail2ban
|
|
19
|
+
this.setDelay(900000);
|
|
20
|
+
}
|
|
21
|
+
else if (message.includes('ENOTFOUND')) {
|
|
22
|
+
// DNS lookup issue - incorrect URI or deleted instance
|
|
23
|
+
this.setDelay(120000);
|
|
24
|
+
}
|
|
25
|
+
else if (message.includes('ECONNREFUSED')) {
|
|
26
|
+
// Could be fail2ban or similar
|
|
27
|
+
this.setDelay(120000);
|
|
28
|
+
}
|
|
29
|
+
else if (message.includes('Unable to do postgres query on ended pool') ||
|
|
30
|
+
message.includes('Postgres unexpectedly closed connection')) {
|
|
31
|
+
// Connection timed out - ignore / immediately retry
|
|
32
|
+
// We don't explicitly set the delay to 0, since there could have been another error that
|
|
33
|
+
// we need to respect.
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.setDelay(30000);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
setDelay(delay) {
|
|
40
|
+
this.nextAllowed = Math.max(this.nextAllowed, Date.now() + delay);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=PostgresErrorRateLimiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresErrorRateLimiter.js","sourceRoot":"","sources":["../../src/replication/PostgresErrorRateLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,MAAM,OAAO,wBAAwB;IAArC;QACE,gBAAW,GAAW,IAAI,CAAC,GAAG,EAAE,CAAC;IAuCnC,CAAC;IArCC,KAAK,CAAC,gBAAgB,CAAC,OAA0D;QAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACzD,yDAAyD;QACzD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnB,MAAM,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC;IACxC,CAAC;IAED,WAAW,CAAC,CAAM;QAChB,MAAM,OAAO,GAAI,CAAC,CAAC,OAAkB,IAAI,EAAE,CAAC;QAC5C,IAAI,OAAO,CAAC,QAAQ,CAAC,gCAAgC,CAAC,EAAE;YACtD,2DAA2D;YAC3D,IAAI,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC;SACxB;aAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;YACxC,uDAAuD;YACvD,IAAI,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC;SACxB;aAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;YAC3C,+BAA+B;YAC/B,IAAI,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC;SACxB;aAAM,IACL,OAAO,CAAC,QAAQ,CAAC,2CAA2C,CAAC;YAC7D,OAAO,CAAC,QAAQ,CAAC,yCAAyC,CAAC,EAC3D;YACA,oDAAoD;YACpD,yFAAyF;YACzF,sBAAsB;SACvB;aAAM;YACL,IAAI,CAAC,QAAQ,CAAC,KAAM,CAAC,CAAC;SACvB;IACH,CAAC;IAEO,QAAQ,CAAC,KAAa;QAC5B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;IACpE,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import * as pgwire from '@powersync/service-jpgwire';
|
|
3
|
+
import { DatabaseInputRow, SqliteRow, SqlSyncRules, TablePattern } from '@powersync/service-sync-rules';
|
|
4
|
+
import { SourceEntityDescriptor, storage } from '@powersync/service-core';
|
|
5
|
+
import { PgManager } from './PgManager.js';
|
|
6
|
+
export declare const ZERO_LSN = "00000000/00000000";
|
|
7
|
+
export declare const PUBLICATION_NAME = "powersync";
|
|
8
|
+
export declare const POSTGRES_DEFAULT_SCHEMA = "public";
|
|
9
|
+
export interface WalStreamOptions {
|
|
10
|
+
connections: PgManager;
|
|
11
|
+
storage: storage.SyncRulesBucketStorage;
|
|
12
|
+
abort_signal: AbortSignal;
|
|
13
|
+
}
|
|
14
|
+
interface InitResult {
|
|
15
|
+
needsInitialSync: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare class MissingReplicationSlotError extends Error {
|
|
18
|
+
constructor(message: string);
|
|
19
|
+
}
|
|
20
|
+
export declare class WalStream {
|
|
21
|
+
sync_rules: SqlSyncRules;
|
|
22
|
+
group_id: number;
|
|
23
|
+
connection_id: number;
|
|
24
|
+
private readonly storage;
|
|
25
|
+
private readonly slot_name;
|
|
26
|
+
private connections;
|
|
27
|
+
private abort_signal;
|
|
28
|
+
private relation_cache;
|
|
29
|
+
private startedStreaming;
|
|
30
|
+
constructor(options: WalStreamOptions);
|
|
31
|
+
get stopped(): boolean;
|
|
32
|
+
getQualifiedTableNames(batch: storage.BucketStorageBatch, db: pgwire.PgConnection, tablePattern: TablePattern): Promise<storage.SourceTable[]>;
|
|
33
|
+
initSlot(): Promise<InitResult>;
|
|
34
|
+
estimatedCount(db: pgwire.PgConnection, table: storage.SourceTable): Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Start initial replication.
|
|
37
|
+
*
|
|
38
|
+
* If (partial) replication was done before on this slot, this clears the state
|
|
39
|
+
* and starts again from scratch.
|
|
40
|
+
*/
|
|
41
|
+
startInitialReplication(replicationConnection: pgwire.PgConnection): Promise<void>;
|
|
42
|
+
initialReplication(db: pgwire.PgConnection, lsn: string): Promise<void>;
|
|
43
|
+
static getQueryData(results: Iterable<DatabaseInputRow>): Generator<SqliteRow>;
|
|
44
|
+
private snapshotTable;
|
|
45
|
+
handleRelation(batch: storage.BucketStorageBatch, descriptor: SourceEntityDescriptor, snapshot: boolean): Promise<storage.SourceTable>;
|
|
46
|
+
private getTable;
|
|
47
|
+
writeChange(batch: storage.BucketStorageBatch, msg: pgwire.PgoutputMessage): Promise<storage.FlushedResult | null>;
|
|
48
|
+
replicate(): Promise<void>;
|
|
49
|
+
initReplication(replicationConnection: pgwire.PgConnection): Promise<void>;
|
|
50
|
+
streamChanges(replicationConnection: pgwire.PgConnection): Promise<void>;
|
|
51
|
+
ack(lsn: string, replicationStream: pgwire.ReplicationStream): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
export {};
|