@powersync/service-module-postgres-storage 0.11.2 → 0.13.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 (87) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/@types/migrations/scripts/1771232439485-storage-version.d.ts +3 -0
  4. package/dist/@types/migrations/scripts/1771424826685-current-data-pending-deletes.d.ts +3 -0
  5. package/dist/@types/migrations/scripts/1771491856000-sync-plan.d.ts +3 -0
  6. package/dist/@types/storage/PostgresBucketStorageFactory.d.ts +6 -10
  7. package/dist/@types/storage/PostgresCompactor.d.ts +10 -3
  8. package/dist/@types/storage/PostgresSyncRulesStorage.d.ts +5 -3
  9. package/dist/@types/storage/batch/OperationBatch.d.ts +2 -2
  10. package/dist/@types/storage/batch/PostgresBucketBatch.d.ts +12 -9
  11. package/dist/@types/storage/batch/PostgresPersistedBatch.d.ts +17 -5
  12. package/dist/@types/storage/current-data-store.d.ts +85 -0
  13. package/dist/@types/storage/current-data-table.d.ts +9 -0
  14. package/dist/@types/storage/sync-rules/PostgresPersistedSyncRulesContent.d.ts +1 -10
  15. package/dist/@types/storage/table-id.d.ts +2 -0
  16. package/dist/@types/types/models/CurrentData.d.ts +18 -3
  17. package/dist/@types/types/models/SyncRules.d.ts +12 -2
  18. package/dist/@types/types/models/json.d.ts +11 -0
  19. package/dist/@types/types/types.d.ts +2 -0
  20. package/dist/@types/utils/bson.d.ts +1 -1
  21. package/dist/@types/utils/db.d.ts +9 -0
  22. package/dist/@types/utils/test-utils.d.ts +1 -1
  23. package/dist/migrations/scripts/1771232439485-storage-version.js +111 -0
  24. package/dist/migrations/scripts/1771232439485-storage-version.js.map +1 -0
  25. package/dist/migrations/scripts/1771424826685-current-data-pending-deletes.js +8 -0
  26. package/dist/migrations/scripts/1771424826685-current-data-pending-deletes.js.map +1 -0
  27. package/dist/migrations/scripts/1771491856000-sync-plan.js +91 -0
  28. package/dist/migrations/scripts/1771491856000-sync-plan.js.map +1 -0
  29. package/dist/storage/PostgresBucketStorageFactory.js +56 -58
  30. package/dist/storage/PostgresBucketStorageFactory.js.map +1 -1
  31. package/dist/storage/PostgresCompactor.js +55 -66
  32. package/dist/storage/PostgresCompactor.js.map +1 -1
  33. package/dist/storage/PostgresSyncRulesStorage.js +23 -15
  34. package/dist/storage/PostgresSyncRulesStorage.js.map +1 -1
  35. package/dist/storage/batch/OperationBatch.js +2 -1
  36. package/dist/storage/batch/OperationBatch.js.map +1 -1
  37. package/dist/storage/batch/PostgresBucketBatch.js +286 -213
  38. package/dist/storage/batch/PostgresBucketBatch.js.map +1 -1
  39. package/dist/storage/batch/PostgresPersistedBatch.js +86 -81
  40. package/dist/storage/batch/PostgresPersistedBatch.js.map +1 -1
  41. package/dist/storage/current-data-store.js +270 -0
  42. package/dist/storage/current-data-store.js.map +1 -0
  43. package/dist/storage/current-data-table.js +22 -0
  44. package/dist/storage/current-data-table.js.map +1 -0
  45. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js +14 -30
  46. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js.map +1 -1
  47. package/dist/storage/table-id.js +8 -0
  48. package/dist/storage/table-id.js.map +1 -0
  49. package/dist/types/models/CurrentData.js +11 -2
  50. package/dist/types/models/CurrentData.js.map +1 -1
  51. package/dist/types/models/SyncRules.js +12 -1
  52. package/dist/types/models/SyncRules.js.map +1 -1
  53. package/dist/types/models/json.js +21 -0
  54. package/dist/types/models/json.js.map +1 -0
  55. package/dist/utils/bson.js.map +1 -1
  56. package/dist/utils/db.js +41 -0
  57. package/dist/utils/db.js.map +1 -1
  58. package/dist/utils/test-utils.js +50 -14
  59. package/dist/utils/test-utils.js.map +1 -1
  60. package/package.json +9 -9
  61. package/src/migrations/scripts/1771232439485-storage-version.ts +44 -0
  62. package/src/migrations/scripts/1771424826685-current-data-pending-deletes.ts +10 -0
  63. package/src/migrations/scripts/1771491856000-sync-plan.ts +21 -0
  64. package/src/storage/PostgresBucketStorageFactory.ts +69 -68
  65. package/src/storage/PostgresCompactor.ts +63 -72
  66. package/src/storage/PostgresSyncRulesStorage.ts +30 -17
  67. package/src/storage/batch/OperationBatch.ts +4 -3
  68. package/src/storage/batch/PostgresBucketBatch.ts +306 -238
  69. package/src/storage/batch/PostgresPersistedBatch.ts +92 -84
  70. package/src/storage/current-data-store.ts +326 -0
  71. package/src/storage/current-data-table.ts +26 -0
  72. package/src/storage/sync-rules/PostgresPersistedSyncRulesContent.ts +13 -33
  73. package/src/storage/table-id.ts +9 -0
  74. package/src/types/models/CurrentData.ts +17 -4
  75. package/src/types/models/SyncRules.ts +16 -1
  76. package/src/types/models/json.ts +26 -0
  77. package/src/utils/bson.ts +1 -1
  78. package/src/utils/db.ts +47 -0
  79. package/src/utils/test-utils.ts +42 -15
  80. package/test/src/__snapshots__/storage.test.ts.snap +148 -6
  81. package/test/src/__snapshots__/storage_compacting.test.ts.snap +17 -0
  82. package/test/src/__snapshots__/storage_sync.test.ts.snap +2211 -21
  83. package/test/src/migrations.test.ts +9 -2
  84. package/test/src/storage.test.ts +137 -131
  85. package/test/src/storage_compacting.test.ts +113 -2
  86. package/test/src/storage_sync.test.ts +148 -4
  87. package/test/src/util.ts +5 -2
@@ -1,47 +1,27 @@
1
1
  import * as lib_postgres from '@powersync/lib-service-postgres';
2
2
  import { ErrorCode, logger, ServiceError } from '@powersync/lib-services-framework';
3
3
  import { storage } from '@powersync/service-core';
4
- import { SqlSyncRules, versionedHydrationState } from '@powersync/service-sync-rules';
5
-
6
4
  import { models } from '../../types/types.js';
7
5
 
8
- export class PostgresPersistedSyncRulesContent implements storage.PersistedSyncRulesContent {
9
- public readonly slot_name: string;
10
-
11
- public readonly id: number;
12
- public readonly sync_rules_content: string;
13
- public readonly last_checkpoint_lsn: string | null;
14
- public readonly last_fatal_error: string | null;
15
- public readonly last_keepalive_ts: Date | null;
16
- public readonly last_checkpoint_ts: Date | null;
17
- public readonly active: boolean;
6
+ export class PostgresPersistedSyncRulesContent extends storage.PersistedSyncRulesContent {
18
7
  current_lock: storage.ReplicationLock | null = null;
19
8
 
20
9
  constructor(
21
10
  private db: lib_postgres.DatabaseClient,
22
11
  row: models.SyncRulesDecoded
23
12
  ) {
24
- this.id = Number(row.id);
25
- this.sync_rules_content = row.content;
26
- this.last_checkpoint_lsn = row.last_checkpoint_lsn;
27
- this.slot_name = row.slot_name;
28
- this.last_fatal_error = row.last_fatal_error;
29
- this.last_checkpoint_ts = row.last_checkpoint_ts ? new Date(row.last_checkpoint_ts) : null;
30
- this.last_keepalive_ts = row.last_keepalive_ts ? new Date(row.last_keepalive_ts) : null;
31
- this.active = row.state == 'ACTIVE';
32
- }
33
-
34
- parsed(options: storage.ParseSyncRulesOptions): storage.PersistedSyncRules {
35
- return {
36
- id: this.id,
37
- slot_name: this.slot_name,
38
- sync_rules: SqlSyncRules.fromYaml(this.sync_rules_content, options),
39
- hydratedSyncRules() {
40
- return this.sync_rules.config.hydrate({
41
- hydrationState: versionedHydrationState(this.id)
42
- });
43
- }
44
- };
13
+ super({
14
+ id: Number(row.id),
15
+ sync_rules_content: row.content,
16
+ compiled_plan: row.sync_plan,
17
+ last_checkpoint_lsn: row.last_checkpoint_lsn,
18
+ slot_name: row.slot_name,
19
+ last_fatal_error: row.last_fatal_error,
20
+ last_checkpoint_ts: row.last_checkpoint_ts ? new Date(row.last_checkpoint_ts) : null,
21
+ last_keepalive_ts: row.last_keepalive_ts ? new Date(row.last_keepalive_ts) : null,
22
+ active: row.state == 'ACTIVE',
23
+ storageVersion: row.storage_version ?? storage.LEGACY_STORAGE_VERSION
24
+ });
45
25
  }
46
26
 
47
27
  async lock(): Promise<storage.ReplicationLock> {
@@ -0,0 +1,9 @@
1
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
2
+ import { storage } from '@powersync/service-core';
3
+
4
+ export function postgresTableId(id: storage.SourceTableId) {
5
+ if (typeof id == 'string') {
6
+ return id;
7
+ }
8
+ throw new ServiceAssertionError(`Expected string table id, got ObjectId`);
9
+ }
@@ -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 CurrentData = t.object({
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 type CurrentData = t.Encoded<typeof CurrentData>;
23
- export type CurrentDataDecoded = t.Decoded<typeof CurrentData>;
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>;
@@ -1,6 +1,7 @@
1
1
  import { framework, storage } from '@powersync/service-core';
2
2
  import * as t from 'ts-codec';
3
3
  import { bigint, pgwire_number } from '../codecs.js';
4
+ import { jsonContainerObject } from './json.js';
4
5
 
5
6
  export const SyncRules = t.object({
6
7
  id: pgwire_number,
@@ -47,7 +48,21 @@ export const SyncRules = t.object({
47
48
  */
48
49
  last_fatal_error: t.Null.or(t.string),
49
50
  keepalive_op: t.Null.or(bigint),
50
- content: t.string
51
+ storage_version: t.Null.or(pgwire_number).optional(),
52
+ content: t.string,
53
+ sync_plan: t.Null.or(
54
+ jsonContainerObject(
55
+ t.object({
56
+ plan: t.any,
57
+ compatibility: t.object({
58
+ edition: t.number,
59
+ overrides: t.record(t.boolean),
60
+ maxTimeValuePrecision: t.number.optional()
61
+ }),
62
+ eventDescriptors: t.record(t.array(t.string))
63
+ })
64
+ )
65
+ )
51
66
  });
52
67
 
53
68
  export type SyncRules = t.Encoded<typeof SyncRules>;
@@ -0,0 +1,26 @@
1
+ import { JsonContainer } from '@powersync/service-jsonbig';
2
+ import { Codec, codec } from 'ts-codec';
3
+
4
+ /**
5
+ * Wraps a codec to support {@link JsonContainer} values.
6
+ *
7
+ * Because our postgres client implementation wraps JSON objects in a {@link JsonContainer}, this intermediate layer is
8
+ * required to use JSON columns from Postgres in `ts-codec` models.
9
+ *
10
+ * Note that this serializes and deserializes values using {@link JSON}, so bigints are not supported.
11
+ */
12
+ export function jsonContainerObject<I, O>(inner: Codec<I, O>): Codec<I, JsonContainer> {
13
+ return codec(
14
+ inner._tag,
15
+ (input) => {
16
+ return new JsonContainer(JSON.stringify(inner.encode(input)));
17
+ },
18
+ (json) => {
19
+ if (!(json instanceof JsonContainer)) {
20
+ throw new Error('Expected JsonContainer');
21
+ }
22
+
23
+ return inner.decode(JSON.parse(json.data));
24
+ }
25
+ );
26
+ }
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: string, id: storage.ReplicaId): string {
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
@@ -9,6 +9,9 @@ export const NOTIFICATION_CHANNEL = 'powersynccheckpoints';
9
9
  */
10
10
  export const sql = lib_postgres.sql;
11
11
 
12
+ /**
13
+ * Drop all Postgres storage tables used by the service, including migrations.
14
+ */
12
15
  export const dropTables = async (client: lib_postgres.DatabaseClient) => {
13
16
  // Lock a connection for automatic schema search paths
14
17
  await client.lockConnection(async (db) => {
@@ -18,10 +21,54 @@ export const dropTables = async (client: lib_postgres.DatabaseClient) => {
18
21
  await db.sql`DROP TABLE IF EXISTS instance`.execute();
19
22
  await db.sql`DROP TABLE IF EXISTS bucket_data`.execute();
20
23
  await db.sql`DROP TABLE IF EXISTS current_data`.execute();
24
+ await db.sql`DROP TABLE IF EXISTS v3_current_data`.execute();
21
25
  await db.sql`DROP TABLE IF EXISTS source_tables`.execute();
22
26
  await db.sql`DROP TABLE IF EXISTS write_checkpoints`.execute();
23
27
  await db.sql`DROP TABLE IF EXISTS custom_write_checkpoints`.execute();
24
28
  await db.sql`DROP SEQUENCE IF EXISTS op_id_sequence`.execute();
25
29
  await db.sql`DROP SEQUENCE IF EXISTS sync_rules_id_sequence`.execute();
30
+ await db.sql`DROP TABLE IF EXISTS migrations`.execute();
26
31
  });
27
32
  };
33
+
34
+ /**
35
+ * Clear all Postgres storage tables and reset sequences.
36
+ *
37
+ * Does not clear migration state.
38
+ */
39
+ export const truncateTables = async (db: lib_postgres.DatabaseClient) => {
40
+ // Lock a connection for automatic schema search paths
41
+ await db.query(
42
+ {
43
+ statement: `TRUNCATE TABLE bucket_data,
44
+ bucket_parameters,
45
+ sync_rules,
46
+ instance,
47
+ current_data,
48
+ source_tables,
49
+ write_checkpoints,
50
+ custom_write_checkpoints,
51
+ connection_report_events RESTART IDENTITY CASCADE
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
+ },
63
+ {
64
+ statement: `ALTER SEQUENCE IF EXISTS op_id_sequence RESTART
65
+ WITH
66
+ 1`
67
+ },
68
+ {
69
+ statement: `ALTER SEQUENCE IF EXISTS sync_rules_id_sequence RESTART
70
+ WITH
71
+ 1`
72
+ }
73
+ );
74
+ };
@@ -3,6 +3,8 @@ 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';
7
+ import { truncateTables } from './db.js';
6
8
 
7
9
  export type PostgresTestStorageOptions = {
8
10
  url: string;
@@ -22,7 +24,7 @@ export function postgresTestSetup(factoryOptions: PostgresTestStorageOptions) {
22
24
 
23
25
  const TEST_CONNECTION_OPTIONS = normalizePostgresStorageConfig(BASE_CONFIG);
24
26
 
25
- const migrate = async (direction: framework.migrations.Direction) => {
27
+ const runMigrations = async (options: { down: boolean; up: boolean }) => {
26
28
  await using migrationManager: PowerSyncMigrationManager = new framework.MigrationManager();
27
29
  await using migrationAgent = factoryOptions.migrationAgent
28
30
  ? factoryOptions.migrationAgent(BASE_CONFIG)
@@ -31,28 +33,56 @@ export function postgresTestSetup(factoryOptions: PostgresTestStorageOptions) {
31
33
 
32
34
  const mockServiceContext = { configuration: { storage: BASE_CONFIG } } as unknown as ServiceContext;
33
35
 
34
- await migrationManager.migrate({
35
- direction: framework.migrations.Direction.Down,
36
- migrationContext: {
37
- service_context: mockServiceContext
38
- }
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()]
39
41
  });
40
42
 
41
- if (direction == framework.migrations.Direction.Up) {
43
+ if (options.down) {
44
+ await migrationManager.migrate({
45
+ direction: framework.migrations.Direction.Down,
46
+ migrationContext: {
47
+ service_context: mockServiceContext
48
+ },
49
+ logger
50
+ });
51
+ }
52
+
53
+ if (options.up) {
42
54
  await migrationManager.migrate({
43
55
  direction: framework.migrations.Direction.Up,
44
56
  migrationContext: {
45
57
  service_context: mockServiceContext
46
- }
58
+ },
59
+ logger
47
60
  });
48
61
  }
49
62
  };
50
63
 
64
+ const migrate = async (direction: framework.migrations.Direction) => {
65
+ await runMigrations({
66
+ down: true,
67
+ up: direction == framework.migrations.Direction.Up
68
+ });
69
+ };
70
+
71
+ const clearStorage = async () => {
72
+ await runMigrations({ down: false, up: true });
73
+
74
+ await using storageFactory = new PostgresBucketStorageFactory({
75
+ config: TEST_CONNECTION_OPTIONS,
76
+ slot_name_prefix: 'test_'
77
+ });
78
+ await truncateTables(storageFactory.db);
79
+ };
80
+
51
81
  return {
52
82
  reportFactory: async (options?: TestStorageOptions) => {
53
83
  try {
54
84
  if (!options?.doNotClear) {
55
- await migrate(framework.migrations.Direction.Up);
85
+ await clearStorage();
56
86
  }
57
87
 
58
88
  return new PostgresReportStorage({
@@ -67,7 +97,7 @@ export function postgresTestSetup(factoryOptions: PostgresTestStorageOptions) {
67
97
  factory: async (options?: TestStorageOptions) => {
68
98
  try {
69
99
  if (!options?.doNotClear) {
70
- await migrate(framework.migrations.Direction.Up);
100
+ await clearStorage();
71
101
  }
72
102
 
73
103
  return new PostgresBucketStorageFactory({
@@ -80,10 +110,7 @@ export function postgresTestSetup(factoryOptions: PostgresTestStorageOptions) {
80
110
  throw ex;
81
111
  }
82
112
  },
83
- migrate
113
+ migrate,
114
+ tableIdStrings: true
84
115
  };
85
116
  }
86
-
87
- export function postgresTestStorageFactoryGenerator(factoryOptions: PostgresTestStorageOptions) {
88
- return postgresTestSetup(factoryOptions).factory;
89
- }
@@ -1,9 +1,151 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`Postgres Sync Bucket Storage - Data > empty storage metrics 1`] = `
4
- {
5
- "operations_size_bytes": 16384,
6
- "parameters_size_bytes": 32768,
7
- "replication_size_bytes": 16384,
8
- }
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
+ ]
9
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
+ `;