@powersync/service-module-postgres-storage 0.12.0 → 0.13.1
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 +45 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/migrations/scripts/1771424826685-current-data-pending-deletes.d.ts +3 -0
- package/dist/@types/storage/PostgresBucketStorageFactory.d.ts +4 -0
- package/dist/@types/storage/PostgresCompactor.d.ts +8 -2
- package/dist/@types/storage/PostgresSyncRulesStorage.d.ts +10 -4
- package/dist/@types/storage/batch/OperationBatch.d.ts +2 -2
- package/dist/@types/storage/batch/PostgresBucketBatch.d.ts +13 -9
- package/dist/@types/storage/batch/PostgresPersistedBatch.d.ts +17 -5
- package/dist/@types/storage/current-data-store.d.ts +85 -0
- package/dist/@types/storage/current-data-table.d.ts +9 -0
- package/dist/@types/storage/table-id.d.ts +2 -0
- package/dist/@types/types/models/CurrentData.d.ts +18 -3
- package/dist/@types/utils/bson.d.ts +1 -1
- package/dist/@types/utils/test-utils.d.ts +1 -1
- package/dist/migrations/scripts/1771424826685-current-data-pending-deletes.js +8 -0
- package/dist/migrations/scripts/1771424826685-current-data-pending-deletes.js.map +1 -0
- package/dist/storage/PostgresBucketStorageFactory.js +41 -4
- package/dist/storage/PostgresBucketStorageFactory.js.map +1 -1
- package/dist/storage/PostgresCompactor.js +14 -6
- package/dist/storage/PostgresCompactor.js.map +1 -1
- package/dist/storage/PostgresSyncRulesStorage.js +98 -24
- package/dist/storage/PostgresSyncRulesStorage.js.map +1 -1
- package/dist/storage/batch/OperationBatch.js +2 -1
- package/dist/storage/batch/OperationBatch.js.map +1 -1
- package/dist/storage/batch/PostgresBucketBatch.js +295 -213
- package/dist/storage/batch/PostgresBucketBatch.js.map +1 -1
- package/dist/storage/batch/PostgresPersistedBatch.js +86 -81
- package/dist/storage/batch/PostgresPersistedBatch.js.map +1 -1
- package/dist/storage/current-data-store.js +270 -0
- package/dist/storage/current-data-store.js.map +1 -0
- package/dist/storage/current-data-table.js +22 -0
- package/dist/storage/current-data-table.js.map +1 -0
- package/dist/storage/table-id.js +8 -0
- package/dist/storage/table-id.js.map +1 -0
- package/dist/types/models/CurrentData.js +11 -2
- package/dist/types/models/CurrentData.js.map +1 -1
- package/dist/utils/bson.js.map +1 -1
- package/dist/utils/db.js +9 -0
- package/dist/utils/db.js.map +1 -1
- package/dist/utils/test-utils.js +13 -6
- package/dist/utils/test-utils.js.map +1 -1
- package/package.json +8 -8
- package/src/migrations/scripts/1771424826685-current-data-pending-deletes.ts +10 -0
- package/src/storage/PostgresBucketStorageFactory.ts +53 -5
- package/src/storage/PostgresCompactor.ts +17 -8
- package/src/storage/PostgresSyncRulesStorage.ts +47 -31
- package/src/storage/batch/OperationBatch.ts +4 -3
- package/src/storage/batch/PostgresBucketBatch.ts +316 -238
- package/src/storage/batch/PostgresPersistedBatch.ts +92 -84
- package/src/storage/current-data-store.ts +326 -0
- package/src/storage/current-data-table.ts +26 -0
- package/src/storage/table-id.ts +9 -0
- package/src/types/models/CurrentData.ts +17 -4
- package/src/utils/bson.ts +1 -1
- package/src/utils/db.ts +10 -0
- package/src/utils/test-utils.ts +14 -7
- package/test/src/__snapshots__/storage.test.ts.snap +151 -0
- package/test/src/__snapshots__/storage_compacting.test.ts.snap +17 -0
- package/test/src/__snapshots__/storage_sync.test.ts.snap +1111 -16
- package/test/src/env.ts +1 -1
- package/test/src/migrations.test.ts +1 -1
- package/test/src/storage.test.ts +138 -131
- package/test/src/storage_compacting.test.ts +80 -11
- package/test/src/storage_sync.test.ts +57 -54
- package/test/src/util.ts +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as t from 'ts-codec';
|
|
2
|
-
import { hexBuffer, jsonb, pgwire_number } from '../codecs.js';
|
|
2
|
+
import { bigint, hexBuffer, jsonb, pgwire_number } from '../codecs.js';
|
|
3
3
|
|
|
4
4
|
export const CurrentBucket = t.object({
|
|
5
5
|
bucket: t.string,
|
|
@@ -10,7 +10,7 @@ export const CurrentBucket = t.object({
|
|
|
10
10
|
export type CurrentBucket = t.Encoded<typeof CurrentBucket>;
|
|
11
11
|
export type CurrentBucketDecoded = t.Decoded<typeof CurrentBucket>;
|
|
12
12
|
|
|
13
|
-
export const
|
|
13
|
+
export const V1CurrentData = t.object({
|
|
14
14
|
buckets: jsonb(t.array(CurrentBucket)),
|
|
15
15
|
data: hexBuffer,
|
|
16
16
|
group_id: pgwire_number,
|
|
@@ -19,5 +19,18 @@ export const CurrentData = t.object({
|
|
|
19
19
|
source_table: t.string
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
export
|
|
23
|
-
|
|
22
|
+
export const V3CurrentData = t.object({
|
|
23
|
+
buckets: jsonb(t.array(CurrentBucket)),
|
|
24
|
+
data: hexBuffer,
|
|
25
|
+
group_id: pgwire_number,
|
|
26
|
+
lookups: t.array(hexBuffer),
|
|
27
|
+
source_key: hexBuffer,
|
|
28
|
+
source_table: t.string,
|
|
29
|
+
pending_delete: t.Null.or(bigint)
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export type V1CurrentData = t.Encoded<typeof V1CurrentData>;
|
|
33
|
+
export type V1CurrentDataDecoded = t.Decoded<typeof V1CurrentData>;
|
|
34
|
+
|
|
35
|
+
export type V3CurrentData = t.Encoded<typeof V3CurrentData>;
|
|
36
|
+
export type V3CurrentDataDecoded = t.Decoded<typeof V3CurrentData>;
|
package/src/utils/bson.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as uuid from 'uuid';
|
|
|
6
6
|
* JSONB columns do not directly support storing binary data which could be required in future.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
export function replicaIdToSubkey(tableId:
|
|
9
|
+
export function replicaIdToSubkey(tableId: storage.SourceTableId, id: storage.ReplicaId): string {
|
|
10
10
|
// Hashed UUID from the table and id
|
|
11
11
|
if (storage.isUUID(id)) {
|
|
12
12
|
// Special case for UUID for backwards-compatiblity
|
package/src/utils/db.ts
CHANGED
|
@@ -21,6 +21,7 @@ export const dropTables = async (client: lib_postgres.DatabaseClient) => {
|
|
|
21
21
|
await db.sql`DROP TABLE IF EXISTS instance`.execute();
|
|
22
22
|
await db.sql`DROP TABLE IF EXISTS bucket_data`.execute();
|
|
23
23
|
await db.sql`DROP TABLE IF EXISTS current_data`.execute();
|
|
24
|
+
await db.sql`DROP TABLE IF EXISTS v3_current_data`.execute();
|
|
24
25
|
await db.sql`DROP TABLE IF EXISTS source_tables`.execute();
|
|
25
26
|
await db.sql`DROP TABLE IF EXISTS write_checkpoints`.execute();
|
|
26
27
|
await db.sql`DROP TABLE IF EXISTS custom_write_checkpoints`.execute();
|
|
@@ -50,6 +51,15 @@ export const truncateTables = async (db: lib_postgres.DatabaseClient) => {
|
|
|
50
51
|
connection_report_events RESTART IDENTITY CASCADE
|
|
51
52
|
`
|
|
52
53
|
},
|
|
54
|
+
{
|
|
55
|
+
// TRUNCATE if v3_current_data exists
|
|
56
|
+
statement: `DO $$
|
|
57
|
+
BEGIN
|
|
58
|
+
IF to_regclass('v3_current_data') IS NOT NULL THEN
|
|
59
|
+
EXECUTE 'TRUNCATE TABLE v3_current_data RESTART IDENTITY CASCADE';
|
|
60
|
+
END IF;
|
|
61
|
+
END $$;`
|
|
62
|
+
},
|
|
53
63
|
{
|
|
54
64
|
statement: `ALTER SEQUENCE IF EXISTS op_id_sequence RESTART
|
|
55
65
|
WITH
|
package/src/utils/test-utils.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { PostgresMigrationAgent } from '../migrations/PostgresMigrationAgent.js'
|
|
|
3
3
|
import { normalizePostgresStorageConfig, PostgresStorageConfigDecoded } from '../types/types.js';
|
|
4
4
|
import { PostgresReportStorage } from '../storage/PostgresReportStorage.js';
|
|
5
5
|
import { PostgresBucketStorageFactory } from '../storage/PostgresBucketStorageFactory.js';
|
|
6
|
+
import { logger as defaultLogger, createLogger, transports } from '@powersync/lib-services-framework';
|
|
6
7
|
import { truncateTables } from './db.js';
|
|
7
8
|
|
|
8
9
|
export type PostgresTestStorageOptions = {
|
|
@@ -32,12 +33,20 @@ export function postgresTestSetup(factoryOptions: PostgresTestStorageOptions) {
|
|
|
32
33
|
|
|
33
34
|
const mockServiceContext = { configuration: { storage: BASE_CONFIG } } as unknown as ServiceContext;
|
|
34
35
|
|
|
36
|
+
// Migration logs can get really verbose in tests, so only log warnings and up.
|
|
37
|
+
const logger = createLogger({
|
|
38
|
+
level: 'warn',
|
|
39
|
+
format: defaultLogger.format,
|
|
40
|
+
transports: [new transports.Console()]
|
|
41
|
+
});
|
|
42
|
+
|
|
35
43
|
if (options.down) {
|
|
36
44
|
await migrationManager.migrate({
|
|
37
45
|
direction: framework.migrations.Direction.Down,
|
|
38
46
|
migrationContext: {
|
|
39
47
|
service_context: mockServiceContext
|
|
40
|
-
}
|
|
48
|
+
},
|
|
49
|
+
logger
|
|
41
50
|
});
|
|
42
51
|
}
|
|
43
52
|
|
|
@@ -46,7 +55,8 @@ export function postgresTestSetup(factoryOptions: PostgresTestStorageOptions) {
|
|
|
46
55
|
direction: framework.migrations.Direction.Up,
|
|
47
56
|
migrationContext: {
|
|
48
57
|
service_context: mockServiceContext
|
|
49
|
-
}
|
|
58
|
+
},
|
|
59
|
+
logger
|
|
50
60
|
});
|
|
51
61
|
}
|
|
52
62
|
};
|
|
@@ -100,10 +110,7 @@ export function postgresTestSetup(factoryOptions: PostgresTestStorageOptions) {
|
|
|
100
110
|
throw ex;
|
|
101
111
|
}
|
|
102
112
|
},
|
|
103
|
-
migrate
|
|
113
|
+
migrate,
|
|
114
|
+
tableIdStrings: true
|
|
104
115
|
};
|
|
105
116
|
}
|
|
106
|
-
|
|
107
|
-
export function postgresTestStorageFactoryGenerator(factoryOptions: PostgresTestStorageOptions) {
|
|
108
|
-
return postgresTestSetup(factoryOptions).factory;
|
|
109
|
-
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`Postgres Sync Bucket Storage - Data > (insert, delete, insert), (delete) 1`] = `
|
|
4
|
+
[
|
|
5
|
+
{
|
|
6
|
+
"checksum": 2871785649,
|
|
7
|
+
"object_id": "test1",
|
|
8
|
+
"op": "PUT",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"checksum": 2872534815,
|
|
12
|
+
"object_id": "test1",
|
|
13
|
+
"op": "REMOVE",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"checksum": 2871785649,
|
|
17
|
+
"object_id": "test1",
|
|
18
|
+
"op": "PUT",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"checksum": 2872534815,
|
|
22
|
+
"object_id": "test1",
|
|
23
|
+
"op": "REMOVE",
|
|
24
|
+
},
|
|
25
|
+
]
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
exports[`Postgres Sync Bucket Storage - Data > (insert, delete, insert), (delete) 2`] = `
|
|
29
|
+
[
|
|
30
|
+
{
|
|
31
|
+
"checksum": 2871785649,
|
|
32
|
+
"object_id": "test1",
|
|
33
|
+
"op": "PUT",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"checksum": 2872534815,
|
|
37
|
+
"object_id": "test1",
|
|
38
|
+
"op": "REMOVE",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"checksum": 2871785649,
|
|
42
|
+
"object_id": "test1",
|
|
43
|
+
"op": "PUT",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"checksum": 2872534815,
|
|
47
|
+
"object_id": "test1",
|
|
48
|
+
"op": "REMOVE",
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
exports[`Postgres Sync Bucket Storage - Data > (insert, delete, insert), (delete) 3`] = `
|
|
54
|
+
[
|
|
55
|
+
{
|
|
56
|
+
"checksum": 2871785649,
|
|
57
|
+
"object_id": "test1",
|
|
58
|
+
"op": "PUT",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"checksum": 2872534815,
|
|
62
|
+
"object_id": "test1",
|
|
63
|
+
"op": "REMOVE",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"checksum": 2871785649,
|
|
67
|
+
"object_id": "test1",
|
|
68
|
+
"op": "PUT",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"checksum": 2872534815,
|
|
72
|
+
"object_id": "test1",
|
|
73
|
+
"op": "REMOVE",
|
|
74
|
+
},
|
|
75
|
+
]
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
exports[`Postgres Sync Bucket Storage - Data - v1 > (insert, delete, insert), (delete) 1`] = `
|
|
79
|
+
[
|
|
80
|
+
{
|
|
81
|
+
"checksum": 2871785649,
|
|
82
|
+
"object_id": "test1",
|
|
83
|
+
"op": "PUT",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"checksum": 2872534815,
|
|
87
|
+
"object_id": "test1",
|
|
88
|
+
"op": "REMOVE",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"checksum": 2871785649,
|
|
92
|
+
"object_id": "test1",
|
|
93
|
+
"op": "PUT",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"checksum": 2872534815,
|
|
97
|
+
"object_id": "test1",
|
|
98
|
+
"op": "REMOVE",
|
|
99
|
+
},
|
|
100
|
+
]
|
|
101
|
+
`;
|
|
102
|
+
|
|
103
|
+
exports[`Postgres Sync Bucket Storage - Data - v2 > (insert, delete, insert), (delete) 1`] = `
|
|
104
|
+
[
|
|
105
|
+
{
|
|
106
|
+
"checksum": 2871785649,
|
|
107
|
+
"object_id": "test1",
|
|
108
|
+
"op": "PUT",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"checksum": 2872534815,
|
|
112
|
+
"object_id": "test1",
|
|
113
|
+
"op": "REMOVE",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"checksum": 2871785649,
|
|
117
|
+
"object_id": "test1",
|
|
118
|
+
"op": "PUT",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"checksum": 2872534815,
|
|
122
|
+
"object_id": "test1",
|
|
123
|
+
"op": "REMOVE",
|
|
124
|
+
},
|
|
125
|
+
]
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
exports[`Postgres Sync Bucket Storage - Data - v3 > (insert, delete, insert), (delete) 1`] = `
|
|
129
|
+
[
|
|
130
|
+
{
|
|
131
|
+
"checksum": 2871785649,
|
|
132
|
+
"object_id": "test1",
|
|
133
|
+
"op": "PUT",
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"checksum": 2872534815,
|
|
137
|
+
"object_id": "test1",
|
|
138
|
+
"op": "REMOVE",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"checksum": 2871785649,
|
|
142
|
+
"object_id": "test1",
|
|
143
|
+
"op": "PUT",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"checksum": 2872534815,
|
|
147
|
+
"object_id": "test1",
|
|
148
|
+
"op": "REMOVE",
|
|
149
|
+
},
|
|
150
|
+
]
|
|
151
|
+
`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`Postgres Sync Bucket Storage Compact > partial checksums after compacting (2) 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"bucket": "1#global[]",
|
|
6
|
+
"checksum": 1196713877,
|
|
7
|
+
"count": 1,
|
|
8
|
+
}
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
exports[`Postgres Sync Bucket Storage Compact > partial checksums after compacting 1`] = `
|
|
12
|
+
{
|
|
13
|
+
"bucket": "1#global[]",
|
|
14
|
+
"checksum": -134691003,
|
|
15
|
+
"count": 4,
|
|
16
|
+
}
|
|
17
|
+
`;
|