@syncular/server 0.30.5 → 0.30.7

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.
@@ -1,3 +1,4 @@
1
+ import { retainRollbackFailure, rollbackAfterError } from './storage-errors';
1
2
  import { validateCommitPruneQuery } from './prune';
2
3
  import { StorageQueryError } from './storage-errors';
3
4
  import type { CommitPruneQuery, CommitPruneResult } from './storage';
@@ -469,9 +470,8 @@ class SqliteTransaction implements StorageTransaction {
469
470
  // connection.
470
471
  try {
471
472
  this.#storage.db.exec('ROLLBACK');
472
- } catch {
473
- // Surface the COMMIT failure; a rollback failure would otherwise
474
- // mask it.
473
+ } catch (rollbackError) {
474
+ retainRollbackFailure(error, rollbackError);
475
475
  }
476
476
  throw error;
477
477
  } finally {
@@ -725,8 +725,9 @@ END`);
725
725
  }
726
726
  this.db.exec('COMMIT');
727
727
  } catch (error) {
728
- this.db.exec('ROLLBACK');
729
- throw error;
728
+ rollbackAfterError(() => {
729
+ this.db.exec('ROLLBACK');
730
+ }, error);
730
731
  }
731
732
  });
732
733
  }
@@ -799,8 +800,9 @@ END`);
799
800
  .run(partition);
800
801
  this.db.exec('COMMIT');
801
802
  } catch (error) {
802
- this.db.exec('ROLLBACK');
803
- throw error;
803
+ rollbackAfterError(() => {
804
+ this.db.exec('ROLLBACK');
805
+ }, error);
804
806
  }
805
807
  return {
806
808
  partition,
@@ -1002,8 +1004,9 @@ END`);
1002
1004
  open = false;
1003
1005
  return result;
1004
1006
  } catch (error) {
1005
- if (open) this.db.exec('ROLLBACK');
1006
- throw error;
1007
+ rollbackAfterError(() => {
1008
+ if (open) this.db.exec('ROLLBACK');
1009
+ }, error);
1007
1010
  } finally {
1008
1011
  release();
1009
1012
  }
@@ -1085,8 +1088,9 @@ END`);
1085
1088
  removedCommits: Number(removed.changes),
1086
1089
  };
1087
1090
  } catch (error) {
1088
- this.db.exec('ROLLBACK');
1089
- throw error;
1091
+ rollbackAfterError(() => {
1092
+ this.db.exec('ROLLBACK');
1093
+ }, error);
1090
1094
  }
1091
1095
  });
1092
1096
  }
@@ -1202,8 +1206,9 @@ END`);
1202
1206
  this.db.exec('COMMIT');
1203
1207
  return toStoredCheckpoint(row);
1204
1208
  } catch (error) {
1205
- this.db.exec('ROLLBACK');
1206
- throw error;
1209
+ rollbackAfterError(() => {
1210
+ this.db.exec('ROLLBACK');
1211
+ }, error);
1207
1212
  }
1208
1213
  });
1209
1214
  }
@@ -1260,8 +1265,9 @@ END`);
1260
1265
  this.db.exec('COMMIT');
1261
1266
  return Number(updated.changes) === 1 ? 'activated' : 'stale';
1262
1267
  } catch (error) {
1263
- this.db.exec('ROLLBACK');
1264
- throw error;
1268
+ rollbackAfterError(() => {
1269
+ this.db.exec('ROLLBACK');
1270
+ }, error);
1265
1271
  }
1266
1272
  });
1267
1273
  }
@@ -150,3 +150,22 @@ export function isD1ConstraintError(error: unknown): boolean {
150
150
  )
151
151
  );
152
152
  }
153
+
154
+ /** Preserve the operation failure when transaction cleanup also fails. */
155
+ export function retainRollbackFailure(
156
+ error: unknown,
157
+ rollbackError: unknown,
158
+ ): void {
159
+ if (error instanceof Error && !('rollbackError' in error)) {
160
+ Object.defineProperty(error, 'rollbackError', { value: rollbackError });
161
+ }
162
+ }
163
+
164
+ export function rollbackAfterError(run: () => void, error: unknown): never {
165
+ try {
166
+ run();
167
+ } catch (rollbackError) {
168
+ retainRollbackFailure(error, rollbackError);
169
+ }
170
+ throw error;
171
+ }
package/src/storage.ts CHANGED
@@ -288,6 +288,8 @@ export interface StoredPushResult {
288
288
  }
289
289
 
290
290
  export interface ClientSubscription {
291
+ /** Codec accepted by the last pull; absent on records written before schema windows. */
292
+ readonly schemaVersion?: number;
291
293
  readonly id: string;
292
294
  readonly table: string;
293
295
  /** Requested scopes of the client's most recent pull (§8.1). */