@powersync/service-module-postgres-storage 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 (35) hide show
  1. package/CHANGELOG.md +73 -11
  2. package/README.md +7 -1
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/@types/storage/PostgresBucketStorageFactory.d.ts +3 -4
  5. package/dist/@types/storage/batch/PostgresBucketBatch.d.ts +4 -4
  6. package/dist/@types/types/codecs.d.ts +2 -2
  7. package/dist/@types/types/models/BucketData.d.ts +1 -1
  8. package/dist/@types/types/models/BucketParameters.d.ts +2 -2
  9. package/dist/@types/types/models/CurrentData.d.ts +3 -3
  10. package/dist/migrations/migration-utils.js +2 -1
  11. package/dist/migrations/migration-utils.js.map +1 -1
  12. package/dist/storage/PostgresBucketStorageFactory.js +27 -16
  13. package/dist/storage/PostgresBucketStorageFactory.js.map +1 -1
  14. package/dist/storage/PostgresCompactor.js +2 -2
  15. package/dist/storage/PostgresCompactor.js.map +1 -1
  16. package/dist/storage/PostgresSyncRulesStorage.js +205 -205
  17. package/dist/storage/PostgresSyncRulesStorage.js.map +1 -1
  18. package/dist/storage/batch/PostgresBucketBatch.js +30 -21
  19. package/dist/storage/batch/PostgresBucketBatch.js.map +1 -1
  20. package/dist/storage/batch/PostgresPersistedBatch.js +39 -81
  21. package/dist/storage/batch/PostgresPersistedBatch.js.map +1 -1
  22. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js +2 -2
  23. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js.map +1 -1
  24. package/dist/types/codecs.js +3 -2
  25. package/dist/types/codecs.js.map +1 -1
  26. package/package.json +9 -9
  27. package/src/migrations/migration-utils.ts +2 -1
  28. package/src/storage/PostgresBucketStorageFactory.ts +31 -20
  29. package/src/storage/PostgresCompactor.ts +4 -2
  30. package/src/storage/PostgresSyncRulesStorage.ts +666 -666
  31. package/src/storage/batch/PostgresBucketBatch.ts +46 -24
  32. package/src/storage/batch/PostgresPersistedBatch.ts +39 -81
  33. package/src/storage/sync-rules/PostgresPersistedSyncRulesContent.ts +5 -2
  34. package/src/types/codecs.ts +3 -2
  35. package/tsconfig.json +0 -2
@@ -1,5 +1,5 @@
1
1
  import * as framework from '@powersync/lib-services-framework';
2
- import { storage, sync, utils } from '@powersync/service-core';
2
+ import { storage, sync, UpdateSyncRulesOptions, utils } from '@powersync/service-core';
3
3
  import * as pg_wire from '@powersync/service-jpgwire';
4
4
  import * as sync_rules from '@powersync/service-sync-rules';
5
5
  import crypto from 'crypto';
@@ -157,11 +157,19 @@ export class PostgresBucketStorageFactory
157
157
  return newInstanceRow!.id;
158
158
  }
159
159
 
160
+ async getSystemIdentifier(): Promise<storage.BucketStorageSystemIdentifier> {
161
+ const id = lib_postgres.utils.encodePostgresSystemIdentifier(
162
+ await lib_postgres.utils.queryPostgresSystemIdentifier(this.db.pool)
163
+ );
164
+
165
+ return {
166
+ id,
167
+ type: lib_postgres.POSTGRES_CONNECTION_TYPE
168
+ };
169
+ }
170
+
160
171
  // TODO possibly share implementation in abstract class
161
- async configureSyncRules(
162
- sync_rules: string,
163
- options?: { lock?: boolean }
164
- ): Promise<{
172
+ async configureSyncRules(options: UpdateSyncRulesOptions): Promise<{
165
173
  updated: boolean;
166
174
  persisted_sync_rules?: storage.PersistedSyncRulesContent;
167
175
  lock?: storage.ReplicationLock;
@@ -169,31 +177,32 @@ export class PostgresBucketStorageFactory
169
177
  const next = await this.getNextSyncRulesContent();
170
178
  const active = await this.getActiveSyncRulesContent();
171
179
 
172
- if (next?.sync_rules_content == sync_rules) {
180
+ if (next?.sync_rules_content == options.content) {
173
181
  framework.logger.info('Sync rules from configuration unchanged');
174
182
  return { updated: false };
175
- } else if (next == null && active?.sync_rules_content == sync_rules) {
183
+ } else if (next == null && active?.sync_rules_content == options.content) {
176
184
  framework.logger.info('Sync rules from configuration unchanged');
177
185
  return { updated: false };
178
186
  } else {
179
187
  framework.logger.info('Sync rules updated from configuration');
180
- const persisted_sync_rules = await this.updateSyncRules({
181
- content: sync_rules,
182
- lock: options?.lock
183
- });
188
+ const persisted_sync_rules = await this.updateSyncRules(options);
184
189
  return { updated: true, persisted_sync_rules, lock: persisted_sync_rules.current_lock ?? undefined };
185
190
  }
186
191
  }
187
192
 
188
193
  async updateSyncRules(options: storage.UpdateSyncRulesOptions): Promise<PostgresPersistedSyncRulesContent> {
189
194
  // TODO some shared implementation for this might be nice
190
- // Parse and validate before applying any changes
191
- sync_rules.SqlSyncRules.fromYaml(options.content, {
192
- // No schema-based validation at this point
193
- schema: undefined,
194
- defaultSchema: 'not_applicable', // Not needed for validation
195
- throwOnError: true
196
- });
195
+ if (options.validate) {
196
+ // Parse and validate before applying any changes
197
+ sync_rules.SqlSyncRules.fromYaml(options.content, {
198
+ // No schema-based validation at this point
199
+ schema: undefined,
200
+ defaultSchema: 'not_applicable', // Not needed for validation
201
+ throwOnError: true
202
+ });
203
+ } else {
204
+ // Apply unconditionally. Any errors will be reported via the diagnostics API.
205
+ }
197
206
 
198
207
  return this.db.transaction(async (db) => {
199
208
  await db.sql`
@@ -255,7 +264,8 @@ export class PostgresBucketStorageFactory
255
264
  if (next != null && next.slot_name == slot_name) {
256
265
  // We need to redo the "next" sync rules
257
266
  await this.updateSyncRules({
258
- content: next.sync_rules_content
267
+ content: next.sync_rules_content,
268
+ validate: false
259
269
  });
260
270
  // Pro-actively stop replicating
261
271
  await this.db.sql`
@@ -269,7 +279,8 @@ export class PostgresBucketStorageFactory
269
279
  } else if (next == null && active?.slot_name == slot_name) {
270
280
  // Slot removed for "active" sync rules, while there is no "next" one.
271
281
  await this.updateSyncRules({
272
- content: active.sync_rules_content
282
+ content: active.sync_rules_content,
283
+ validate: false
273
284
  });
274
285
 
275
286
  // Pro-actively stop replicating
@@ -1,5 +1,5 @@
1
1
  import * as lib_postgres from '@powersync/lib-service-postgres';
2
- import { logger } from '@powersync/lib-services-framework';
2
+ import { logger, ReplicationAssertionError } from '@powersync/lib-services-framework';
3
3
  import { storage, utils } from '@powersync/service-core';
4
4
  import * as pgwire from '@powersync/service-jpgwire';
5
5
  import * as t from 'ts-codec';
@@ -313,7 +313,9 @@ export class PostgresCompactor {
313
313
  }
314
314
  }
315
315
  } else {
316
- throw new Error(`Unexpected ${op.op} operation at ${this.group_id}:${bucket}:${op.op_id}`);
316
+ throw new ReplicationAssertionError(
317
+ `Unexpected ${op.op} operation at ${this.group_id}:${bucket}:${op.op_id}`
318
+ );
317
319
  }
318
320
  }
319
321
  }