@powersync/service-module-postgres-storage 0.1.0

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 (157) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +67 -0
  3. package/README.md +67 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/@types/index.d.ts +7 -0
  6. package/dist/@types/migrations/PostgresMigrationAgent.d.ts +12 -0
  7. package/dist/@types/migrations/PostgresMigrationStore.d.ts +14 -0
  8. package/dist/@types/migrations/migration-utils.d.ts +3 -0
  9. package/dist/@types/migrations/scripts/1684951997326-init.d.ts +3 -0
  10. package/dist/@types/module/PostgresStorageModule.d.ts +6 -0
  11. package/dist/@types/storage/PostgresBucketStorageFactory.d.ts +42 -0
  12. package/dist/@types/storage/PostgresCompactor.d.ts +40 -0
  13. package/dist/@types/storage/PostgresStorageProvider.d.ts +5 -0
  14. package/dist/@types/storage/PostgresSyncRulesStorage.d.ts +46 -0
  15. package/dist/@types/storage/PostgresTestStorageFactoryGenerator.d.ts +13 -0
  16. package/dist/@types/storage/batch/OperationBatch.d.ts +47 -0
  17. package/dist/@types/storage/batch/PostgresBucketBatch.d.ts +90 -0
  18. package/dist/@types/storage/batch/PostgresPersistedBatch.d.ts +64 -0
  19. package/dist/@types/storage/checkpoints/PostgresWriteCheckpointAPI.d.ts +20 -0
  20. package/dist/@types/storage/storage-index.d.ts +5 -0
  21. package/dist/@types/storage/sync-rules/PostgresPersistedSyncRulesContent.d.ts +17 -0
  22. package/dist/@types/types/codecs.d.ts +61 -0
  23. package/dist/@types/types/models/ActiveCheckpoint.d.ts +12 -0
  24. package/dist/@types/types/models/ActiveCheckpointNotification.d.ts +19 -0
  25. package/dist/@types/types/models/BucketData.d.ts +22 -0
  26. package/dist/@types/types/models/BucketParameters.d.ts +11 -0
  27. package/dist/@types/types/models/CurrentData.d.ts +22 -0
  28. package/dist/@types/types/models/Instance.d.ts +6 -0
  29. package/dist/@types/types/models/Migration.d.ts +12 -0
  30. package/dist/@types/types/models/SourceTable.d.ts +31 -0
  31. package/dist/@types/types/models/SyncRules.d.ts +47 -0
  32. package/dist/@types/types/models/WriteCheckpoint.d.ts +15 -0
  33. package/dist/@types/types/models/models-index.d.ts +10 -0
  34. package/dist/@types/types/types.d.ts +94 -0
  35. package/dist/@types/utils/bson.d.ts +6 -0
  36. package/dist/@types/utils/bucket-data.d.ts +18 -0
  37. package/dist/@types/utils/db.d.ts +8 -0
  38. package/dist/@types/utils/ts-codec.d.ts +5 -0
  39. package/dist/@types/utils/utils-index.d.ts +4 -0
  40. package/dist/index.js +8 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/migrations/PostgresMigrationAgent.js +36 -0
  43. package/dist/migrations/PostgresMigrationAgent.js.map +1 -0
  44. package/dist/migrations/PostgresMigrationStore.js +60 -0
  45. package/dist/migrations/PostgresMigrationStore.js.map +1 -0
  46. package/dist/migrations/migration-utils.js +13 -0
  47. package/dist/migrations/migration-utils.js.map +1 -0
  48. package/dist/migrations/scripts/1684951997326-init.js +196 -0
  49. package/dist/migrations/scripts/1684951997326-init.js.map +1 -0
  50. package/dist/module/PostgresStorageModule.js +23 -0
  51. package/dist/module/PostgresStorageModule.js.map +1 -0
  52. package/dist/storage/PostgresBucketStorageFactory.js +433 -0
  53. package/dist/storage/PostgresBucketStorageFactory.js.map +1 -0
  54. package/dist/storage/PostgresCompactor.js +298 -0
  55. package/dist/storage/PostgresCompactor.js.map +1 -0
  56. package/dist/storage/PostgresStorageProvider.js +35 -0
  57. package/dist/storage/PostgresStorageProvider.js.map +1 -0
  58. package/dist/storage/PostgresSyncRulesStorage.js +619 -0
  59. package/dist/storage/PostgresSyncRulesStorage.js.map +1 -0
  60. package/dist/storage/PostgresTestStorageFactoryGenerator.js +110 -0
  61. package/dist/storage/PostgresTestStorageFactoryGenerator.js.map +1 -0
  62. package/dist/storage/batch/OperationBatch.js +93 -0
  63. package/dist/storage/batch/OperationBatch.js.map +1 -0
  64. package/dist/storage/batch/PostgresBucketBatch.js +732 -0
  65. package/dist/storage/batch/PostgresBucketBatch.js.map +1 -0
  66. package/dist/storage/batch/PostgresPersistedBatch.js +367 -0
  67. package/dist/storage/batch/PostgresPersistedBatch.js.map +1 -0
  68. package/dist/storage/checkpoints/PostgresWriteCheckpointAPI.js +148 -0
  69. package/dist/storage/checkpoints/PostgresWriteCheckpointAPI.js.map +1 -0
  70. package/dist/storage/storage-index.js +6 -0
  71. package/dist/storage/storage-index.js.map +1 -0
  72. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js +58 -0
  73. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js.map +1 -0
  74. package/dist/types/codecs.js +97 -0
  75. package/dist/types/codecs.js.map +1 -0
  76. package/dist/types/models/ActiveCheckpoint.js +12 -0
  77. package/dist/types/models/ActiveCheckpoint.js.map +1 -0
  78. package/dist/types/models/ActiveCheckpointNotification.js +8 -0
  79. package/dist/types/models/ActiveCheckpointNotification.js.map +1 -0
  80. package/dist/types/models/BucketData.js +23 -0
  81. package/dist/types/models/BucketData.js.map +1 -0
  82. package/dist/types/models/BucketParameters.js +11 -0
  83. package/dist/types/models/BucketParameters.js.map +1 -0
  84. package/dist/types/models/CurrentData.js +16 -0
  85. package/dist/types/models/CurrentData.js.map +1 -0
  86. package/dist/types/models/Instance.js +5 -0
  87. package/dist/types/models/Instance.js.map +1 -0
  88. package/dist/types/models/Migration.js +12 -0
  89. package/dist/types/models/Migration.js.map +1 -0
  90. package/dist/types/models/SourceTable.js +24 -0
  91. package/dist/types/models/SourceTable.js.map +1 -0
  92. package/dist/types/models/SyncRules.js +47 -0
  93. package/dist/types/models/SyncRules.js.map +1 -0
  94. package/dist/types/models/WriteCheckpoint.js +13 -0
  95. package/dist/types/models/WriteCheckpoint.js.map +1 -0
  96. package/dist/types/models/models-index.js +11 -0
  97. package/dist/types/models/models-index.js.map +1 -0
  98. package/dist/types/types.js +46 -0
  99. package/dist/types/types.js.map +1 -0
  100. package/dist/utils/bson.js +16 -0
  101. package/dist/utils/bson.js.map +1 -0
  102. package/dist/utils/bucket-data.js +25 -0
  103. package/dist/utils/bucket-data.js.map +1 -0
  104. package/dist/utils/db.js +24 -0
  105. package/dist/utils/db.js.map +1 -0
  106. package/dist/utils/ts-codec.js +11 -0
  107. package/dist/utils/ts-codec.js.map +1 -0
  108. package/dist/utils/utils-index.js +5 -0
  109. package/dist/utils/utils-index.js.map +1 -0
  110. package/package.json +50 -0
  111. package/src/index.ts +10 -0
  112. package/src/migrations/PostgresMigrationAgent.ts +46 -0
  113. package/src/migrations/PostgresMigrationStore.ts +70 -0
  114. package/src/migrations/migration-utils.ts +14 -0
  115. package/src/migrations/scripts/1684951997326-init.ts +141 -0
  116. package/src/module/PostgresStorageModule.ts +30 -0
  117. package/src/storage/PostgresBucketStorageFactory.ts +496 -0
  118. package/src/storage/PostgresCompactor.ts +366 -0
  119. package/src/storage/PostgresStorageProvider.ts +42 -0
  120. package/src/storage/PostgresSyncRulesStorage.ts +666 -0
  121. package/src/storage/PostgresTestStorageFactoryGenerator.ts +61 -0
  122. package/src/storage/batch/OperationBatch.ts +101 -0
  123. package/src/storage/batch/PostgresBucketBatch.ts +885 -0
  124. package/src/storage/batch/PostgresPersistedBatch.ts +441 -0
  125. package/src/storage/checkpoints/PostgresWriteCheckpointAPI.ts +176 -0
  126. package/src/storage/storage-index.ts +5 -0
  127. package/src/storage/sync-rules/PostgresPersistedSyncRulesContent.ts +67 -0
  128. package/src/types/codecs.ts +136 -0
  129. package/src/types/models/ActiveCheckpoint.ts +15 -0
  130. package/src/types/models/ActiveCheckpointNotification.ts +14 -0
  131. package/src/types/models/BucketData.ts +26 -0
  132. package/src/types/models/BucketParameters.ts +14 -0
  133. package/src/types/models/CurrentData.ts +23 -0
  134. package/src/types/models/Instance.ts +8 -0
  135. package/src/types/models/Migration.ts +19 -0
  136. package/src/types/models/SourceTable.ts +32 -0
  137. package/src/types/models/SyncRules.ts +50 -0
  138. package/src/types/models/WriteCheckpoint.ts +20 -0
  139. package/src/types/models/models-index.ts +10 -0
  140. package/src/types/types.ts +73 -0
  141. package/src/utils/bson.ts +17 -0
  142. package/src/utils/bucket-data.ts +25 -0
  143. package/src/utils/db.ts +27 -0
  144. package/src/utils/ts-codec.ts +14 -0
  145. package/src/utils/utils-index.ts +4 -0
  146. package/test/src/__snapshots__/storage.test.ts.snap +9 -0
  147. package/test/src/__snapshots__/storage_sync.test.ts.snap +332 -0
  148. package/test/src/env.ts +6 -0
  149. package/test/src/migrations.test.ts +34 -0
  150. package/test/src/setup.ts +16 -0
  151. package/test/src/storage.test.ts +131 -0
  152. package/test/src/storage_compacting.test.ts +5 -0
  153. package/test/src/storage_sync.test.ts +12 -0
  154. package/test/src/util.ts +34 -0
  155. package/test/tsconfig.json +20 -0
  156. package/tsconfig.json +36 -0
  157. package/vitest.config.ts +13 -0
@@ -0,0 +1,298 @@
1
+ import { logger } from '@powersync/lib-services-framework';
2
+ import { utils } from '@powersync/service-core';
3
+ import { BIGINT_MAX } from '../types/codecs.js';
4
+ import { models } from '../types/types.js';
5
+ import { sql } from '../utils/db.js';
6
+ import { pick } from '../utils/ts-codec.js';
7
+ import { encodedCacheKey } from './batch/OperationBatch.js';
8
+ const DEFAULT_CLEAR_BATCH_LIMIT = 5000;
9
+ const DEFAULT_MOVE_BATCH_LIMIT = 2000;
10
+ const DEFAULT_MOVE_BATCH_QUERY_LIMIT = 10_000;
11
+ /** This default is primarily for tests. */
12
+ const DEFAULT_MEMORY_LIMIT_MB = 64;
13
+ export class PostgresCompactor {
14
+ db;
15
+ group_id;
16
+ updates = [];
17
+ idLimitBytes;
18
+ moveBatchLimit;
19
+ moveBatchQueryLimit;
20
+ clearBatchLimit;
21
+ maxOpId;
22
+ buckets;
23
+ constructor(db, group_id, options) {
24
+ this.db = db;
25
+ this.group_id = group_id;
26
+ this.idLimitBytes = (options?.memoryLimitMB ?? DEFAULT_MEMORY_LIMIT_MB) * 1024 * 1024;
27
+ this.moveBatchLimit = options?.moveBatchLimit ?? DEFAULT_MOVE_BATCH_LIMIT;
28
+ this.moveBatchQueryLimit = options?.moveBatchQueryLimit ?? DEFAULT_MOVE_BATCH_QUERY_LIMIT;
29
+ this.clearBatchLimit = options?.clearBatchLimit ?? DEFAULT_CLEAR_BATCH_LIMIT;
30
+ this.maxOpId = options?.maxOpId;
31
+ this.buckets = options?.compactBuckets;
32
+ }
33
+ /**
34
+ * Compact buckets by converting operations into MOVE and/or CLEAR operations.
35
+ *
36
+ * See /docs/compacting-operations.md for details.
37
+ */
38
+ async compact() {
39
+ if (this.buckets) {
40
+ for (let bucket of this.buckets) {
41
+ // We can make this more efficient later on by iterating
42
+ // through the buckets in a single query.
43
+ // That makes batching more tricky, so we leave for later.
44
+ await this.compactInternal(bucket);
45
+ }
46
+ }
47
+ else {
48
+ await this.compactInternal(undefined);
49
+ }
50
+ }
51
+ async compactInternal(bucket) {
52
+ const idLimitBytes = this.idLimitBytes;
53
+ let currentState = null;
54
+ let bucketLower = null;
55
+ let bucketUpper = null;
56
+ if (bucket?.includes('[')) {
57
+ // Exact bucket name
58
+ bucketLower = bucket;
59
+ bucketUpper = bucket;
60
+ }
61
+ else if (bucket) {
62
+ // Bucket definition name
63
+ bucketLower = `${bucket}[`;
64
+ bucketUpper = `${bucket}[\uFFFF`;
65
+ }
66
+ let upperOpIdLimit = BIGINT_MAX;
67
+ while (true) {
68
+ const batch = await this.db.sql `
69
+ SELECT
70
+ op,
71
+ op_id,
72
+ source_table,
73
+ table_name,
74
+ row_id,
75
+ source_key,
76
+ bucket_name
77
+ FROM
78
+ bucket_data
79
+ WHERE
80
+ group_id = ${{ type: 'int4', value: this.group_id }}
81
+ AND bucket_name LIKE COALESCE(${{ type: 'varchar', value: bucketLower }}, '%')
82
+ AND op_id < ${{ type: 'int8', value: upperOpIdLimit }}
83
+ ORDER BY
84
+ bucket_name,
85
+ op_id DESC
86
+ LIMIT
87
+ ${{ type: 'int4', value: this.moveBatchQueryLimit }}
88
+ `
89
+ .decoded(pick(models.BucketData, ['op', 'source_table', 'table_name', 'source_key', 'row_id', 'op_id', 'bucket_name']))
90
+ .rows();
91
+ if (batch.length == 0) {
92
+ // We've reached the end
93
+ break;
94
+ }
95
+ // Set upperBound for the next batch
96
+ upperOpIdLimit = batch[batch.length - 1].op_id;
97
+ for (const doc of batch) {
98
+ if (currentState == null || doc.bucket_name != currentState.bucket) {
99
+ if (currentState != null && currentState.lastNotPut != null && currentState.opsSincePut >= 1) {
100
+ // Important to flush before clearBucket()
101
+ await this.flush();
102
+ logger.info(`Inserting CLEAR at ${this.group_id}:${currentState.bucket}:${currentState.lastNotPut} to remove ${currentState.opsSincePut} operations`);
103
+ const bucket = currentState.bucket;
104
+ const clearOp = currentState.lastNotPut;
105
+ // Free memory before clearing bucket
106
+ currentState = null;
107
+ await this.clearBucket(bucket, clearOp);
108
+ }
109
+ currentState = {
110
+ bucket: doc.bucket_name,
111
+ seen: new Map(),
112
+ trackingSize: 0,
113
+ lastNotPut: null,
114
+ opsSincePut: 0
115
+ };
116
+ }
117
+ if (this.maxOpId != null && doc.op_id > this.maxOpId) {
118
+ continue;
119
+ }
120
+ let isPersistentPut = doc.op == 'PUT';
121
+ if (doc.op == 'REMOVE' || doc.op == 'PUT') {
122
+ const key = `${doc.table_name}/${doc.row_id}/${encodedCacheKey(doc.source_table, doc.source_key)}`;
123
+ const targetOp = currentState.seen.get(utils.flatstr(key));
124
+ if (targetOp) {
125
+ // Will convert to MOVE, so don't count as PUT
126
+ isPersistentPut = false;
127
+ this.updates.push(sql `
128
+ UPDATE bucket_data
129
+ SET
130
+ op = 'MOVE',
131
+ target_op = ${{ type: 'int8', value: targetOp }},
132
+ table_name = NULL,
133
+ row_id = NULL,
134
+ data = NULL,
135
+ source_table = NULL,
136
+ source_key = NULL
137
+ WHERE
138
+ group_id = ${{ type: 'int4', value: this.group_id }}
139
+ AND bucket_name = ${{ type: 'varchar', value: doc.bucket_name }}
140
+ AND op_id = ${{ type: 'int8', value: doc.op_id }}
141
+ `);
142
+ }
143
+ else {
144
+ if (currentState.trackingSize >= idLimitBytes) {
145
+ // Reached memory limit.
146
+ // Keep the highest seen values in this case.
147
+ }
148
+ else {
149
+ // flatstr reduces the memory usage by flattening the string
150
+ currentState.seen.set(utils.flatstr(key), doc.op_id);
151
+ // length + 16 for the string
152
+ // 24 for the bigint
153
+ // 50 for map overhead
154
+ // 50 for additional overhead
155
+ currentState.trackingSize += key.length + 140;
156
+ }
157
+ }
158
+ }
159
+ if (isPersistentPut) {
160
+ currentState.lastNotPut = null;
161
+ currentState.opsSincePut = 0;
162
+ }
163
+ else if (doc.op != 'CLEAR') {
164
+ if (currentState.lastNotPut == null) {
165
+ currentState.lastNotPut = doc.op_id;
166
+ }
167
+ currentState.opsSincePut += 1;
168
+ }
169
+ if (this.updates.length >= this.moveBatchLimit) {
170
+ await this.flush();
171
+ }
172
+ }
173
+ }
174
+ await this.flush();
175
+ currentState?.seen.clear();
176
+ if (currentState?.lastNotPut != null && currentState?.opsSincePut > 1) {
177
+ logger.info(`Inserting CLEAR at ${this.group_id}:${currentState.bucket}:${currentState.lastNotPut} to remove ${currentState.opsSincePut} operations`);
178
+ const bucket = currentState.bucket;
179
+ const clearOp = currentState.lastNotPut;
180
+ // Free memory before clearing bucket
181
+ currentState = null;
182
+ await this.clearBucket(bucket, clearOp);
183
+ }
184
+ }
185
+ async flush() {
186
+ if (this.updates.length > 0) {
187
+ logger.info(`Compacting ${this.updates.length} ops`);
188
+ await this.db.query(...this.updates);
189
+ this.updates = [];
190
+ }
191
+ }
192
+ /**
193
+ * Perform a CLEAR compact for a bucket.
194
+ *
195
+ * @param bucket bucket name
196
+ * @param op op_id of the last non-PUT operation, which will be converted to CLEAR.
197
+ */
198
+ async clearBucket(bucket, op) {
199
+ /**
200
+ * This entire method could be implemented as a Postgres function, but this might make debugging
201
+ * a bit more challenging.
202
+ */
203
+ let done = false;
204
+ while (!done) {
205
+ await this.db.lockConnection(async (db) => {
206
+ /**
207
+ * Start a transaction where each read returns the state at the start of the transaction,.
208
+ * Similar to the MongoDB readConcern: { level: 'snapshot' } mode.
209
+ */
210
+ await db.sql `BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ`.execute();
211
+ try {
212
+ let checksum = 0;
213
+ let lastOpId = null;
214
+ let targetOp = null;
215
+ let gotAnOp = false;
216
+ const codec = pick(models.BucketData, ['op', 'source_table', 'source_key', 'op_id', 'checksum', 'target_op']);
217
+ for await (const operations of db.streamRows(sql `
218
+ SELECT
219
+ source_table,
220
+ source_key,
221
+ op,
222
+ op_id,
223
+ checksum,
224
+ target_op
225
+ FROM
226
+ bucket_data
227
+ WHERE
228
+ group_id = ${{ type: 'int4', value: this.group_id }}
229
+ AND bucket_name = ${{ type: 'varchar', value: bucket }}
230
+ AND op_id <= ${{ type: 'int8', value: op }}
231
+ ORDER BY
232
+ op_id
233
+ LIMIT
234
+ ${{ type: 'int4', value: this.clearBatchLimit }}
235
+ `)) {
236
+ const decodedOps = operations.map((o) => codec.decode(o));
237
+ for (const op of decodedOps) {
238
+ if ([models.OpType.MOVE, models.OpType.REMOVE, models.OpType.CLEAR].includes(op.op)) {
239
+ checksum = utils.addChecksums(checksum, Number(op.checksum));
240
+ lastOpId = op.op_id;
241
+ if (op.op != models.OpType.CLEAR) {
242
+ gotAnOp = true;
243
+ }
244
+ if (op.target_op != null) {
245
+ if (targetOp == null || op.target_op > targetOp) {
246
+ targetOp = op.target_op;
247
+ }
248
+ }
249
+ }
250
+ else {
251
+ throw new Error(`Unexpected ${op.op} operation at ${this.group_id}:${bucket}:${op.op_id}`);
252
+ }
253
+ }
254
+ }
255
+ if (!gotAnOp) {
256
+ await db.sql `COMMIT`.execute();
257
+ done = true;
258
+ return;
259
+ }
260
+ logger.info(`Flushing CLEAR at ${lastOpId}`);
261
+ await db.sql `
262
+ DELETE FROM bucket_data
263
+ WHERE
264
+ group_id = ${{ type: 'int4', value: this.group_id }}
265
+ AND bucket_name = ${{ type: 'varchar', value: bucket }}
266
+ AND op_id <= ${{ type: 'int8', value: lastOpId }}
267
+ `.execute();
268
+ await db.sql `
269
+ INSERT INTO
270
+ bucket_data (
271
+ group_id,
272
+ bucket_name,
273
+ op_id,
274
+ op,
275
+ checksum,
276
+ target_op
277
+ )
278
+ VALUES
279
+ (
280
+ ${{ type: 'int4', value: this.group_id }},
281
+ ${{ type: 'varchar', value: bucket }},
282
+ ${{ type: 'int8', value: lastOpId }},
283
+ ${{ type: 'varchar', value: models.OpType.CLEAR }},
284
+ ${{ type: 'int8', value: checksum }},
285
+ ${{ type: 'int8', value: targetOp }}
286
+ )
287
+ `.execute();
288
+ await db.sql `COMMIT`.execute();
289
+ }
290
+ catch (ex) {
291
+ await db.sql `ROLLBACK`.execute();
292
+ throw ex;
293
+ }
294
+ });
295
+ }
296
+ }
297
+ }
298
+ //# sourceMappingURL=PostgresCompactor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresCompactor.js","sourceRoot":"","sources":["../../src/storage/PostgresCompactor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import * as lib_postgres from '@powersync/lib-service-postgres';
2
+ import { logger } from '@powersync/lib-services-framework';
3
+ import { isPostgresStorageConfig, normalizePostgresStorageConfig, PostgresStorageConfig } from '../types/types.js';
4
+ import { dropTables } from '../utils/db.js';
5
+ import { PostgresBucketStorageFactory } from './PostgresBucketStorageFactory.js';
6
+ export class PostgresStorageProvider {
7
+ get type() {
8
+ return lib_postgres.POSTGRES_CONNECTION_TYPE;
9
+ }
10
+ async getStorage(options) {
11
+ const { resolvedConfig } = options;
12
+ const { storage } = resolvedConfig;
13
+ if (!isPostgresStorageConfig(storage)) {
14
+ // This should not be reached since the generation should be managed externally.
15
+ throw new Error(`Cannot create Postgres bucket storage with provided config ${storage.type} !== ${lib_postgres.POSTGRES_CONNECTION_TYPE}`);
16
+ }
17
+ const decodedConfig = PostgresStorageConfig.decode(storage);
18
+ const normalizedConfig = normalizePostgresStorageConfig(decodedConfig);
19
+ const storageFactory = new PostgresBucketStorageFactory({
20
+ config: normalizedConfig,
21
+ slot_name_prefix: options.resolvedConfig.slot_name_prefix
22
+ });
23
+ return {
24
+ storage: storageFactory,
25
+ shutDown: async () => storageFactory.db[Symbol.asyncDispose](),
26
+ tearDown: async () => {
27
+ logger.info(`Tearing down Postgres storage: ${normalizedConfig.database}...`);
28
+ await dropTables(storageFactory.db);
29
+ await storageFactory.db[Symbol.asyncDispose]();
30
+ return true;
31
+ }
32
+ };
33
+ }
34
+ }
35
+ //# sourceMappingURL=PostgresStorageProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresStorageProvider.js","sourceRoot":"","sources":["../../src/storage/PostgresStorageProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAG3D,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACnH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AAEjF,MAAM,OAAO,uBAAuB;IAClC,IAAI,IAAI;QACN,OAAO,YAAY,CAAC,wBAAwB,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAkC;QACjD,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;QAEnC,MAAM,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC;QACnC,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,gFAAgF;YAChF,MAAM,IAAI,KAAK,CACb,8DAA8D,OAAO,CAAC,IAAI,QAAQ,YAAY,CAAC,wBAAwB,EAAE,CAC1H,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5D,MAAM,gBAAgB,GAAG,8BAA8B,CAAC,aAAa,CAAC,CAAC;QACvE,MAAM,cAAc,GAAG,IAAI,4BAA4B,CAAC;YACtD,MAAM,EAAE,gBAAgB;YACxB,gBAAgB,EAAE,OAAO,CAAC,cAAc,CAAC,gBAAgB;SAC1D,CAAC,CAAC;QACH,OAAO;YACL,OAAO,EAAE,cAAc;YACvB,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE;YAC9D,QAAQ,EAAE,KAAK,IAAI,EAAE;gBACnB,MAAM,CAAC,IAAI,CAAC,kCAAkC,gBAAgB,CAAC,QAAQ,KAAK,CAAC,CAAC;gBAC9E,MAAM,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;gBACpC,MAAM,cAAc,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC/C,OAAO,IAAI,CAAC;YACd,CAAC;SAC8B,CAAC;IACpC,CAAC;CACF"}