@delali/sirannon-db 0.4.1-next.88 → 0.4.1-next.89

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,6 +1,6 @@
1
- export { assembleFromDestination, restoreBackup } from '../chunk-M3POIJ4C.mjs';
2
- export { backupPiecesSafeToDelete, planBackupRestore } from '../chunk-GCOJFQOL.mjs';
3
- import '../chunk-O3FX3SD4.mjs';
1
+ export { assembleFromDestination, restoreBackup } from '../chunk-RBA6WMXU.mjs';
2
+ export { backupPiecesSafeToDelete, planBackupRestore } from '../chunk-EOESJH5I.mjs';
3
+ import '../chunk-V4NPLS4E.mjs';
4
4
  export { verifyBackupRecord } from '../chunk-DX4WGJL7.mjs';
5
5
  import '../chunk-QGVRRKB2.mjs';
6
6
  import '../chunk-BUWJH3D3.mjs';
@@ -1,5 +1,5 @@
1
1
  import { ReplicationError, BatchValidationError } from './chunk-BLMRNSUG.mjs';
2
- import { CHANGES_TABLE, META_TABLE, MIGRATIONS_TABLE, REPLACED_ROWS_TABLE, APPLIED_CHANGES_TABLE, STAGED_PUSH_CHANGES_TABLE, COLUMN_VERSIONS_TABLE, DEVICE_CURSORS_TABLE, PEER_STATE_TABLE, SYNC_STATE_TABLE, STAGED_CHANGES_TABLE, isReservedIdentifier } from './chunk-ZAUHAJ4G.mjs';
2
+ import { CHANGES_TABLE, META_TABLE, MIGRATIONS_TABLE, REPLACED_ROWS_TABLE, ROLLED_BACK_CHANGES_TABLE, APPLIED_CHANGES_TABLE, STAGED_PUSH_CHANGES_TABLE, COLUMN_VERSIONS_TABLE, DEVICE_CURSORS_TABLE, PEER_STATE_TABLE, SYNC_STATE_TABLE, STAGED_CHANGES_TABLE, isReservedIdentifier } from './chunk-ZD5FP3IW.mjs';
3
3
  import { SirannonError } from './chunk-KINDFBQP.mjs';
4
4
 
5
5
  // src/core/sync/hlc.ts
@@ -434,6 +434,77 @@ async function deleteAllReplacedRows(conn) {
434
434
  await conn.exec(`DELETE FROM "${REPLACED_ROWS_TABLE}"`);
435
435
  }
436
436
 
437
+ // src/core/system-catalog/rolled-back-changes-table.ts
438
+ var INSERT_ROLLED_BACK_COLUMNS = "seq, rolled_back_at, rolled_back_in_term, table_name, operation, row_id, old_data, new_data, node_id, tx_id, hlc, compared_with_primary";
439
+ var KEEP_STRONGER_COMPARISON = "ON CONFLICT(seq) DO UPDATE SET compared_with_primary = MAX(compared_with_primary, excluded.compared_with_primary)";
440
+ function originPlaceholders(originCount) {
441
+ return Array.from({ length: originCount }, () => "?").join(", ");
442
+ }
443
+ async function ensureRolledBackChangesTable(conn) {
444
+ await conn.exec(
445
+ `CREATE TABLE IF NOT EXISTS "${ROLLED_BACK_CHANGES_TABLE}" (
446
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
447
+ seq INTEGER NOT NULL UNIQUE,
448
+ rolled_back_at REAL NOT NULL,
449
+ rolled_back_in_term TEXT NOT NULL,
450
+ table_name TEXT NOT NULL,
451
+ operation TEXT NOT NULL,
452
+ row_id TEXT NOT NULL,
453
+ old_data TEXT,
454
+ new_data TEXT,
455
+ node_id TEXT NOT NULL,
456
+ tx_id TEXT NOT NULL,
457
+ hlc TEXT NOT NULL,
458
+ compared_with_primary INTEGER NOT NULL
459
+ )`
460
+ );
461
+ }
462
+ async function insertRolledBackChangesAfterHlc(conn, changesTable, origins, hlc, term, nowSeconds) {
463
+ if (origins.length === 0) return;
464
+ const stmt = await conn.prepare(
465
+ `INSERT INTO "${ROLLED_BACK_CHANGES_TABLE}" (${INSERT_ROLLED_BACK_COLUMNS})
466
+ SELECT seq, ?, ?, table_name, operation, row_id, old_data, new_data, node_id, tx_id, hlc, 1 FROM "${changesTable}"
467
+ WHERE hlc != '' AND hlc > ? AND node_id IN (${originPlaceholders(origins.length)})
468
+ ORDER BY seq
469
+ ${KEEP_STRONGER_COMPARISON}`
470
+ );
471
+ await stmt.run(nowSeconds, term.toString(), hlc ?? "", ...origins);
472
+ }
473
+ async function insertRolledBackChangesNotFromPrimary(conn, changesTable, origins, primaryNodeId, term, nowSeconds) {
474
+ if (origins.length === 0) return;
475
+ const stmt = await conn.prepare(
476
+ `INSERT INTO "${ROLLED_BACK_CHANGES_TABLE}" (${INSERT_ROLLED_BACK_COLUMNS})
477
+ SELECT seq, ?, ?, table_name, operation, row_id, old_data, new_data, node_id, tx_id, hlc, 0 FROM "${changesTable}"
478
+ WHERE hlc != '' AND node_id IN (${originPlaceholders(origins.length)}) AND node_id != ?
479
+ ORDER BY seq
480
+ ${KEEP_STRONGER_COMPARISON}`
481
+ );
482
+ await stmt.run(nowSeconds, term.toString(), ...origins, primaryNodeId);
483
+ }
484
+ async function selectRolledBackChanges(conn) {
485
+ const stmt = await conn.prepare(
486
+ `SELECT ${INSERT_ROLLED_BACK_COLUMNS} FROM "${ROLLED_BACK_CHANGES_TABLE}" ORDER BY id`
487
+ );
488
+ const rows = await stmt.all();
489
+ return rows.map((row) => ({
490
+ seq: BigInt(row.seq),
491
+ rolledBackAt: Number(row.rolled_back_at),
492
+ rolledBackInTerm: BigInt(row.rolled_back_in_term),
493
+ tableName: row.table_name,
494
+ operation: row.operation,
495
+ rowId: row.row_id,
496
+ oldData: row.old_data,
497
+ newData: row.new_data,
498
+ nodeId: row.node_id,
499
+ txId: row.tx_id,
500
+ hlc: row.hlc,
501
+ comparedWithPrimary: Number(row.compared_with_primary) === 1
502
+ }));
503
+ }
504
+ async function deleteRolledBackChanges(conn) {
505
+ await conn.exec(`DELETE FROM "${ROLLED_BACK_CHANGES_TABLE}"`);
506
+ }
507
+
437
508
  // src/core/system-catalog/applied-changes-table.ts
438
509
  async function ensureAppliedChangesTable(conn) {
439
510
  await conn.exec(`
@@ -492,12 +563,12 @@ async function selectAppliedSourceSeqsInRange(conn, sourceNodeId, fromSeq, toSeq
492
563
  }
493
564
 
494
565
  // src/core/system-catalog/changes-history.ts
495
- function originPlaceholders(originCount) {
566
+ function originPlaceholders2(originCount) {
496
567
  return Array.from({ length: originCount }, () => "?").join(", ");
497
568
  }
498
569
  function selectOutboundHistoryChangesSql(tableName, originCount) {
499
570
  return `SELECT ${CHANGE_LOG_COLUMNS} FROM "${tableName}"
500
- WHERE seq > ? AND hlc != '' AND node_id IN (${originPlaceholders(originCount)})
571
+ WHERE seq > ? AND hlc != '' AND node_id IN (${originPlaceholders2(originCount)})
501
572
  ORDER BY seq ASC LIMIT ?`;
502
573
  }
503
574
  async function selectNewestHistoryChange(conn, tableName, origins, bounds = {}) {
@@ -506,7 +577,7 @@ async function selectNewestHistoryChange(conn, tableName, origins, bounds = {})
506
577
  const hlcFilter = bounds.beforeHlc === void 0 ? "" : "AND hlc < ?";
507
578
  const stmt = await conn.prepare(
508
579
  `SELECT seq, hlc, tx_id FROM "${tableName}"
509
- WHERE hlc != '' AND node_id IN (${originPlaceholders(origins.length)}) ${seqFilter} ${hlcFilter}
580
+ WHERE hlc != '' AND node_id IN (${originPlaceholders2(origins.length)}) ${seqFilter} ${hlcFilter}
510
581
  ORDER BY hlc DESC, seq DESC LIMIT 1`
511
582
  );
512
583
  const params = [...origins];
@@ -524,7 +595,7 @@ async function selectMaxHistoryChangeSeq(conn, tableName, origins) {
524
595
  if (origins.length === 0) return 0n;
525
596
  const stmt = await conn.prepare(
526
597
  `SELECT COALESCE(MAX(seq), 0) AS seq FROM "${tableName}"
527
- WHERE hlc != '' AND node_id IN (${originPlaceholders(origins.length)})`
598
+ WHERE hlc != '' AND node_id IN (${originPlaceholders2(origins.length)})`
528
599
  );
529
600
  const row = await stmt.get(...origins);
530
601
  return seqFromColumn(row?.seq);
@@ -541,7 +612,7 @@ async function selectHistoryChangesAfterHlc(conn, tableName, origins, hlc) {
541
612
  if (origins.length === 0) return [];
542
613
  const stmt = await conn.prepare(
543
614
  `SELECT seq, table_name, operation, row_id, old_data, new_data FROM "${tableName}"
544
- WHERE hlc > ? AND node_id IN (${originPlaceholders(origins.length)})
615
+ WHERE hlc > ? AND node_id IN (${originPlaceholders2(origins.length)})
545
616
  ORDER BY seq DESC`
546
617
  );
547
618
  return await stmt.all(hlc, ...origins);
@@ -549,7 +620,7 @@ async function selectHistoryChangesAfterHlc(conn, tableName, origins, hlc) {
549
620
  async function deleteHistoryChangesAfterHlc(conn, tableName, origins, hlc) {
550
621
  if (origins.length === 0) return;
551
622
  const stmt = await conn.prepare(
552
- `DELETE FROM "${tableName}" WHERE hlc > ? AND node_id IN (${originPlaceholders(origins.length)})`
623
+ `DELETE FROM "${tableName}" WHERE hlc > ? AND node_id IN (${originPlaceholders2(origins.length)})`
553
624
  );
554
625
  await stmt.run(hlc, ...origins);
555
626
  }
@@ -880,6 +951,7 @@ async function ensureReplicationStateTables(conn) {
880
951
  await ensurePeerStateTable(conn);
881
952
  await ensureBatchApplyTables(conn);
882
953
  await ensureSyncStateTable(conn);
954
+ await ensureRolledBackChangesTable(conn);
883
955
  }
884
956
 
885
957
  // src/core/system-catalog/staged-changes-table.ts
@@ -1140,4 +1212,4 @@ function attributeChangeSeqs(batch) {
1140
1212
  });
1141
1213
  }
1142
1214
 
1143
- export { HLC, IDENTIFIER_RE, MAX_CHANGE_SEQ, PkResolver, SEQ_STRING_RE, TABLE_XINFO_HIDDEN, assertSafeIdentifier, attributeChangeSeqs, canonicaliseForChecksum, deleteAllReplacedRows, deleteAllStagedChanges, deleteAppliedChangesAfterSeq, deleteChangesBeforeUpToSeqSql, deleteColumnVersions, deleteColumnVersionsAfterHlc, deleteExpiredDeviceCursors, deleteHistoryChangesAfterHlc, deleteMetaValue, deletePeerState, deletePeerStates, deletePrimaryTermStart, deleteReplacedRowsOfTable, deleteStagedChangesUpToSeq, deleteStagedPushChanges, deleteStampedChangesUpToSeq, deleteSyncTableStates, ensureBatchApplyTables, ensureChangesTable, ensureDeviceCursorsTable, ensureMetaTable, ensureMigrationsTable, ensureReplacedRowsTable, ensureReplicationStateTables, ensureStagedChangesTable, ensureStagedPushChangesTable, extractDroppedTable, highestMigrationVersion, indexColumns, insertAppliedChangesFromStagedPush, insertDdlChange, insertMetaValueIfAbsent, prepareDeleteMigration, prepareDeleteRowColumnVersions, prepareInsertAppliedChange, prepareInsertMigration, prepareInsertStagedPushChange, prepareUpdateMigrationChecksum, prepareUpsertColumnVersion, prepareUpsertNewerColumnVersion, primaryKeyColumns, referencedTables, replaceMigrationHistory, selectAnchoredTerm, selectAppliedMigrations, selectAppliedMigrationsNewestFirst, selectAppliedSourceSeqsInRange, selectChangesAfterSeqSql, selectCompletedSyncTableNames, selectCountOutboundChanges, selectCountTableRows, selectDeviceCursorExists, selectFirstStagedTransactionEnd, selectHistoryBase, selectHistoryChangesAfterHlc, selectHistoryTransaction, selectIndexSql, selectMaxAppliedSourceSeq, selectMaxAppliedSourceSeqByNode, selectMaxAssignedChangeSeq, selectMaxChangeHlc, selectMaxChangeSeq, selectMaxColumnVersionHlc, selectMaxColumnVersionHlcForRow, selectMaxHistoryChangeSeq, selectMaxNodeChangeSeq, selectMaxRowChangeHlc, selectMaxStagedSeq, selectMetaValue, selectMinChangeSeqSql, selectMinDeviceCursorBoundary, selectMinPeerAckedSeq, selectNewestHistoryChange, selectNodeChangesAfterSeqSql, selectOrdinaryTableName, selectOutboundChangesSql, selectOutboundHistoryChangesSql, selectPeerAckedSeq, selectPrimaryTermStart, selectQuarantined, selectStagedChangesInRange, selectStagedPushChangesAfter, selectStagedPushSeqsInRange, selectStagedPushTail, selectSyncMetaRow, selectTableExists, selectTableSql, selectTablesChangesInRangeSql, selectTriggerSql, selectUserSchemaObjects, selectUserTableNames, setForeignKeysEnabled, tableColumnsWithGenerated, tableIndexList, tableInfoRows, tablePkColumns, updateChangeStampsAboveMetaSeqSql, updateChangeStampsAfterSeqSql, updateDeviceCursor, upsertAnchoredTerm, upsertDeviceCursor, upsertHistoryBase, upsertMetaMaxChangeSeqSql, upsertMetaValue, upsertMetaValueAndMaxChangeSeqSql, upsertPeerAckedSeq, upsertPrimaryTermStart, upsertQuarantined, upsertStagedChangeSql, upsertSyncMeta, upsertSyncTableStatus, validateDdlSafety, validateIdentifier };
1215
+ export { HLC, IDENTIFIER_RE, MAX_CHANGE_SEQ, PkResolver, SEQ_STRING_RE, TABLE_XINFO_HIDDEN, assertSafeIdentifier, attributeChangeSeqs, canonicaliseForChecksum, deleteAllReplacedRows, deleteAllStagedChanges, deleteAppliedChangesAfterSeq, deleteChangesBeforeUpToSeqSql, deleteColumnVersions, deleteColumnVersionsAfterHlc, deleteExpiredDeviceCursors, deleteHistoryChangesAfterHlc, deleteMetaValue, deletePeerState, deletePeerStates, deletePrimaryTermStart, deleteReplacedRowsOfTable, deleteRolledBackChanges, deleteStagedChangesUpToSeq, deleteStagedPushChanges, deleteStampedChangesUpToSeq, deleteSyncTableStates, ensureBatchApplyTables, ensureChangesTable, ensureDeviceCursorsTable, ensureMetaTable, ensureMigrationsTable, ensureReplacedRowsTable, ensureReplicationStateTables, ensureRolledBackChangesTable, ensureStagedChangesTable, ensureStagedPushChangesTable, extractDroppedTable, highestMigrationVersion, indexColumns, insertAppliedChangesFromStagedPush, insertDdlChange, insertMetaValueIfAbsent, insertRolledBackChangesAfterHlc, insertRolledBackChangesNotFromPrimary, prepareDeleteMigration, prepareDeleteRowColumnVersions, prepareInsertAppliedChange, prepareInsertMigration, prepareInsertStagedPushChange, prepareUpdateMigrationChecksum, prepareUpsertColumnVersion, prepareUpsertNewerColumnVersion, primaryKeyColumns, referencedTables, replaceMigrationHistory, selectAnchoredTerm, selectAppliedMigrations, selectAppliedMigrationsNewestFirst, selectAppliedSourceSeqsInRange, selectChangesAfterSeqSql, selectCompletedSyncTableNames, selectCountOutboundChanges, selectCountTableRows, selectDeviceCursorExists, selectFirstStagedTransactionEnd, selectHistoryBase, selectHistoryChangesAfterHlc, selectHistoryTransaction, selectIndexSql, selectMaxAppliedSourceSeq, selectMaxAppliedSourceSeqByNode, selectMaxAssignedChangeSeq, selectMaxChangeHlc, selectMaxChangeSeq, selectMaxColumnVersionHlc, selectMaxColumnVersionHlcForRow, selectMaxHistoryChangeSeq, selectMaxNodeChangeSeq, selectMaxRowChangeHlc, selectMaxStagedSeq, selectMetaValue, selectMinChangeSeqSql, selectMinDeviceCursorBoundary, selectMinPeerAckedSeq, selectNewestHistoryChange, selectNodeChangesAfterSeqSql, selectOrdinaryTableName, selectOutboundChangesSql, selectOutboundHistoryChangesSql, selectPeerAckedSeq, selectPrimaryTermStart, selectQuarantined, selectRolledBackChanges, selectStagedChangesInRange, selectStagedPushChangesAfter, selectStagedPushSeqsInRange, selectStagedPushTail, selectSyncMetaRow, selectTableExists, selectTableSql, selectTablesChangesInRangeSql, selectTriggerSql, selectUserSchemaObjects, selectUserTableNames, setForeignKeysEnabled, tableColumnsWithGenerated, tableIndexList, tableInfoRows, tablePkColumns, updateChangeStampsAboveMetaSeqSql, updateChangeStampsAfterSeqSql, updateDeviceCursor, upsertAnchoredTerm, upsertDeviceCursor, upsertHistoryBase, upsertMetaMaxChangeSeqSql, upsertMetaValue, upsertMetaValueAndMaxChangeSeqSql, upsertPeerAckedSeq, upsertPrimaryTermStart, upsertQuarantined, upsertStagedChangeSql, upsertSyncMeta, upsertSyncTableStatus, validateDdlSafety, validateIdentifier };
@@ -22,6 +22,30 @@ function parseMajorVersion(version) {
22
22
 
23
23
  // src/replication/coordinator/group-rules.ts
24
24
  var MIN_AUTOMATIC_FAILOVER_VOTERS = 3;
25
+ var MAX_GROUP_VOTERS = 7;
26
+ var FIRST_FEATURE_LEVEL = 1;
27
+ var IN_SYNC_ACKNOWLEDGEMENT_FEATURE_LEVEL = 2;
28
+ function majorityOf(voterCount) {
29
+ return Math.floor(voterCount / 2) + 1;
30
+ }
31
+ function recordInSyncMajority(state) {
32
+ const voters = state.votingDataBearingNodeIds;
33
+ const inSyncVoters = state.inSyncNodeIds.filter((nodeId) => voters.includes(nodeId)).length;
34
+ if (state.inSyncMajorityTerm >= state.primaryTerm || inSyncVoters < majorityOf(voters.length)) return state;
35
+ return { ...state, inSyncMajorityTerm: state.primaryTerm };
36
+ }
37
+ function assertVoterCap(voterCount, groupId) {
38
+ if (voterCount > MAX_GROUP_VOTERS) {
39
+ throw new RangeError(
40
+ `Replication group '${groupId}' would hold ${voterCount} voters and pending voters, more than the limit of ${MAX_GROUP_VOTERS}`
41
+ );
42
+ }
43
+ }
44
+ function assertFeatureLevel(featureLevel) {
45
+ if (!Number.isSafeInteger(featureLevel) || featureLevel < FIRST_FEATURE_LEVEL) {
46
+ throw new RangeError(`featureLevel must be a safe integer of at least ${FIRST_FEATURE_LEVEL}`);
47
+ }
48
+ }
25
49
  function assertNonEmpty(value, name) {
26
50
  if (value.length === 0) {
27
51
  throw new TypeError(`${name} must not be empty`);
@@ -99,10 +123,9 @@ function arraysEqual(left, right) {
99
123
  function sameNodeIdSet(left, right) {
100
124
  return left.length === right.length && left.every((nodeId) => right.includes(nodeId));
101
125
  }
102
- function markDisplacedPrimaryForRepair(state, displacedPrimaryId, nextPrimaryId) {
126
+ function removeDisplacedPrimaryFromInSyncSet(state, displacedPrimaryId, nextPrimaryId) {
103
127
  if (!displacedPrimaryId || displacedPrimaryId === nextPrimaryId) return;
104
128
  state.inSyncNodeIds = removeNodeId(state.inSyncNodeIds, displacedPrimaryId);
105
- state.repairingNodeIds = setMembership(state.repairingNodeIds, displacedPrimaryId, true);
106
129
  }
107
130
  function cloneCompatibility(compatibility) {
108
131
  return compatibility ? { ...compatibility } : void 0;
@@ -125,6 +148,11 @@ function nextInSyncSetState(state, input, nowMs) {
125
148
  assertSubset(inSyncNodeIds, state.votingDataBearingNodeIds, "inSyncNodeIds");
126
149
  assertNoInSyncAdditions(state.inSyncNodeIds, inSyncNodeIds);
127
150
  const durabilityPointSeq = input.durabilityPointSeq !== void 0 && input.durabilityPointSeq > state.durabilityPointSeq ? input.durabilityPointSeq : state.durabilityPointSeq;
151
+ const primaryRemoval = input.expectedPrimaryNodeId !== void 0 && inSyncNodeIds.length < state.inSyncNodeIds.length;
152
+ if (primaryRemoval && inSyncNodeIds.length < majorityOf(state.votingDataBearingNodeIds.length)) {
153
+ if (durabilityPointSeq === state.durabilityPointSeq) return state;
154
+ return { ...state, durabilityPointSeq, updatedAtMs: nowMs };
155
+ }
128
156
  if (arraysEqual(inSyncNodeIds, state.inSyncNodeIds) && durabilityPointSeq === state.durabilityPointSeq) {
129
157
  return state;
130
158
  }
@@ -133,9 +161,15 @@ function nextInSyncSetState(state, input, nowMs) {
133
161
  function nextAdmittedInSyncState(state, input, nowMs) {
134
162
  assertNodeInGroup(state, input.nodeId);
135
163
  const pendingVoter = state.pendingVoterNodeIds.includes(input.nodeId);
136
- if (state.currentPrimary?.nodeId !== input.sourceNodeId || input.expectedPrimaryTerm !== void 0 && state.primaryTerm !== input.expectedPrimaryTerm || state.drainingNodeIds.includes(input.nodeId) || state.faultedNodeIds.includes(input.nodeId) || (pendingVoter || state.repairingNodeIds.includes(input.nodeId)) && input.rejoinSyncCompleted !== true || input.appliedSeq < state.durabilityPointSeq) {
164
+ const repairing = state.repairingNodeIds.includes(input.nodeId);
165
+ const pendingVoterNeedsCopy = pendingVoter && state.featureLevel < IN_SYNC_ACKNOWLEDGEMENT_FEATURE_LEVEL;
166
+ if (state.currentPrimary?.nodeId !== input.sourceNodeId || input.expectedPrimaryTerm !== void 0 && state.primaryTerm !== input.expectedPrimaryTerm || state.drainingNodeIds.includes(input.nodeId) || state.faultedNodeIds.includes(input.nodeId) || (pendingVoterNeedsCopy || repairing) && input.rejoinSyncCompleted !== true || input.appliedSeq < state.durabilityPointSeq) {
137
167
  return state;
138
168
  }
169
+ if (input.clearRepairingOnly === true) {
170
+ if (!repairing) return state;
171
+ return { ...state, repairingNodeIds: removeNodeId(state.repairingNodeIds, input.nodeId), updatedAtMs: nowMs };
172
+ }
139
173
  const inSyncNodeIds = state.inSyncNodeIds.includes(input.nodeId) ? state.inSyncNodeIds : [...state.inSyncNodeIds, input.nodeId];
140
174
  const repairingNodeIds = removeNodeId(state.repairingNodeIds, input.nodeId);
141
175
  if (pendingVoter) {
@@ -187,6 +221,9 @@ function buildReplicationGroupState(input, nowMs = Date.now()) {
187
221
  const pendingVoterNodeIds = normaliseNodeIds(input.pendingVoterNodeIds ?? [], "pendingVoterNodeIds");
188
222
  assertNonNegativeTerm(input.primaryTerm ?? 0n);
189
223
  assertNonNegativeSeq(input.durabilityPointSeq ?? 0n, "durabilityPointSeq");
224
+ const featureLevel = input.featureLevel ?? FIRST_FEATURE_LEVEL;
225
+ assertFeatureLevel(featureLevel);
226
+ assertVoterCap(votingDataBearingNodeIds.length + pendingVoterNodeIds.length, input.groupId);
190
227
  assertPrimaryInGroup(input.currentPrimary ?? null, votingDataBearingNodeIds);
191
228
  for (const nodeId of pendingVoterNodeIds) {
192
229
  if (votingDataBearingNodeIds.includes(nodeId)) {
@@ -198,7 +235,7 @@ function buildReplicationGroupState(input, nowMs = Date.now()) {
198
235
  assertSubset(drainingNodeIds, memberNodeIds, "drainingNodeIds");
199
236
  assertSubset(repairingNodeIds, memberNodeIds, "repairingNodeIds");
200
237
  assertSubset(faultedNodeIds, memberNodeIds, "faultedNodeIds");
201
- return {
238
+ return recordInSyncMajority({
202
239
  clusterId: input.clusterId,
203
240
  groupId: input.groupId,
204
241
  votingDataBearingNodeIds,
@@ -211,8 +248,10 @@ function buildReplicationGroupState(input, nowMs = Date.now()) {
211
248
  faultedNodeIds,
212
249
  pendingVoterNodeIds,
213
250
  compatibility: cloneCompatibility(input.compatibility),
251
+ featureLevel,
252
+ inSyncMajorityTerm: input.inSyncMajorityTerm ?? 0n,
214
253
  updatedAtMs: nowMs
215
- };
254
+ });
216
255
  }
217
256
  function cloneReplicationGroupState(state) {
218
257
  return {
@@ -229,4 +268,4 @@ function cloneReplicationGroupState(state) {
229
268
  };
230
269
  }
231
270
 
232
- export { MIN_AUTOMATIC_FAILOVER_VOTERS, arraysEqual, assertNonEmpty, assertNonNegativeSeq, assertNonNegativeTerm, assertPositiveTtl, assertPrimaryInGroup, buildReplicationGroupState, cloneCompatibility, cloneMetadata, cloneReplicationGroupState, compatibilityAllowsPromotion, groupMemberIds, isEligiblePromotionSession, isGroupMember, markDisplacedPrimaryForRepair, nextAdmittedInSyncState, nextInSyncSetState, nextMaintenanceState, normaliseNodeIds, removeNodeId, sameNodeIdSet, setMembership };
271
+ export { FIRST_FEATURE_LEVEL, IN_SYNC_ACKNOWLEDGEMENT_FEATURE_LEVEL, MIN_AUTOMATIC_FAILOVER_VOTERS, assertFeatureLevel, assertNonEmpty, assertNonNegativeSeq, assertNonNegativeTerm, assertPositiveTtl, assertPrimaryInGroup, assertVoterCap, buildReplicationGroupState, cloneCompatibility, cloneMetadata, cloneReplicationGroupState, compatibilityAllowsPromotion, groupMemberIds, isEligiblePromotionSession, isGroupMember, majorityOf, nextAdmittedInSyncState, nextInSyncSetState, nextMaintenanceState, normaliseNodeIds, recordInSyncMajority, removeDisplacedPrimaryFromInSyncSet, removeNodeId, sameNodeIdSet, setMembership };
@@ -1,4 +1,4 @@
1
- import { encodeWireRowsInPlace, assertSqlAllowed } from './chunk-ZAUHAJ4G.mjs';
1
+ import { encodeWireRowsInPlace, assertSqlAllowed } from './chunk-ZD5FP3IW.mjs';
2
2
  import { withRowCounts, rowCountsOf, allMetered, addRowCounts } from './chunk-E2GRX4ZD.mjs';
3
3
  import { SirannonError, QueryError, TransactionError } from './chunk-KINDFBQP.mjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { execute, commitFailure, asQueryError } from './chunk-ZWW53O5P.mjs';
1
+ import { execute, commitFailure, asQueryError } from './chunk-C3OVUSZP.mjs';
2
2
  import { rowCountsOf } from './chunk-E2GRX4ZD.mjs';
3
3
 
4
4
  // src/core/group-executor.ts
@@ -1,4 +1,4 @@
1
- import { pipe, instance, check, union, object, optional, string, safeParse } from './chunk-O3FX3SD4.mjs';
1
+ import { pipe, instance, check, union, object, optional, string, safeParse } from './chunk-V4NPLS4E.mjs';
2
2
  import { EncryptionError } from './chunk-5O4J6LQQ.mjs';
3
3
  import { SirannonError } from './chunk-KINDFBQP.mjs';
4
4
 
@@ -1,6 +1,6 @@
1
- import { IDENTIFIER_RE, selectCountTableRows, canonicaliseForChecksum, selectUserSchemaObjects, validateDdlSafety, selectUserTableNames, referencedTables } from './chunk-MTOQ6QIS.mjs';
1
+ import { IDENTIFIER_RE, selectCountTableRows, canonicaliseForChecksum, selectUserSchemaObjects, validateDdlSafety, selectUserTableNames, referencedTables } from './chunk-2EYLKZZY.mjs';
2
2
  import { ReplicationError } from './chunk-BLMRNSUG.mjs';
3
- import { INTERNAL_TABLE_PREFIX } from './chunk-ZAUHAJ4G.mjs';
3
+ import { INTERNAL_TABLE_PREFIX } from './chunk-ZD5FP3IW.mjs';
4
4
  import { createHash } from 'crypto';
5
5
 
6
6
  var DumpOps = class {
@@ -1,7 +1,7 @@
1
1
  import { readSelectItems, findClauses } from './chunk-D3YF2G7X.mjs';
2
2
  import { operationRegistryDigest } from './chunk-KB4OLJAD.mjs';
3
3
  import { tokenizeSql } from './chunk-SEL4A4WT.mjs';
4
- import { custom, array, string, object, nullable, optional, literal, safeParse, getDotPath } from './chunk-O3FX3SD4.mjs';
4
+ import { custom, array, string, object, nullable, optional, literal, safeParse, getDotPath } from './chunk-V4NPLS4E.mjs';
5
5
  import { readFileSync, mkdirSync, writeFileSync } from 'fs';
6
6
  import { resolve, dirname } from 'path';
7
7
  import { pathToFileURL } from 'url';
@@ -1,9 +1,9 @@
1
- import { withoutRowCounts, runWriterTransaction, queryMetered, execute, executeBatch } from './chunk-ZWW53O5P.mjs';
2
- import { HLC, ensureMetaTable, selectMetaValue, IDENTIFIER_RE, attributeChangeSeqs, validateDdlSafety, insertDdlChange, extractDroppedTable, selectMaxChangeSeq, updateChangeStampsAfterSeqSql, selectOutboundHistoryChangesSql, selectOutboundChangesSql, selectNodeChangesAfterSeqSql, prepareUpsertNewerColumnVersion, canonicaliseForChecksum, upsertMetaValue, selectMaxColumnVersionHlcForRow, selectMaxRowChangeHlc, validateIdentifier, prepareDeleteRowColumnVersions, prepareUpsertColumnVersion, selectTableExists, selectAppliedSourceSeqsInRange, selectStagedPushTail, selectStagedPushSeqsInRange, deleteStagedPushChanges, prepareInsertStagedPushChange, selectStagedPushChangesAfter, insertAppliedChangesFromStagedPush, prepareInsertAppliedChange } from './chunk-MTOQ6QIS.mjs';
1
+ import { withoutRowCounts, runWriterTransaction, queryMetered, execute, executeBatch } from './chunk-C3OVUSZP.mjs';
2
+ import { HLC, ensureMetaTable, selectMetaValue, IDENTIFIER_RE, attributeChangeSeqs, validateDdlSafety, insertDdlChange, extractDroppedTable, selectMaxChangeSeq, updateChangeStampsAfterSeqSql, selectOutboundHistoryChangesSql, selectOutboundChangesSql, selectNodeChangesAfterSeqSql, prepareUpsertNewerColumnVersion, canonicaliseForChecksum, upsertMetaValue, selectMaxColumnVersionHlcForRow, selectMaxRowChangeHlc, validateIdentifier, prepareDeleteRowColumnVersions, prepareUpsertColumnVersion, selectTableExists, selectAppliedSourceSeqsInRange, selectStagedPushTail, selectStagedPushSeqsInRange, deleteStagedPushChanges, prepareInsertStagedPushChange, selectStagedPushChangesAfter, insertAppliedChangesFromStagedPush, prepareInsertAppliedChange } from './chunk-2EYLKZZY.mjs';
3
3
  import { BatchValidationError, ConflictError, ReplicationError } from './chunk-BLMRNSUG.mjs';
4
- import { CHANGES_TABLE, isReservedIdentifier, decodeTaggedValues, encodeTaggedValues } from './chunk-ZAUHAJ4G.mjs';
4
+ import { CHANGES_TABLE, isReservedIdentifier, decodeTaggedValues, encodeTaggedValues } from './chunk-ZD5FP3IW.mjs';
5
5
  import { sha256Hex } from './chunk-GVCNMPOS.mjs';
6
- import { record, string, unknown, object, optional, nullable, picklist, safeParse, summarize } from './chunk-O3FX3SD4.mjs';
6
+ import { record, string, unknown, object, optional, nullable, picklist, safeParse, summarize } from './chunk-V4NPLS4E.mjs';
7
7
  import { lateRowCountsOf } from './chunk-K43WJORM.mjs';
8
8
  import { rowCountsOf, totalRowCounts, addRowCounts } from './chunk-E2GRX4ZD.mjs';
9
9
  import { invokeCallerCallback } from './chunk-HO2XTXVX.mjs';
@@ -1,4 +1,4 @@
1
- import { planBackupRestore, EncryptionKeyring } from './chunk-GCOJFQOL.mjs';
1
+ import { planBackupRestore, EncryptionKeyring } from './chunk-EOESJH5I.mjs';
2
2
  import { listStoredFilePieces, fetchStoredFile, checkpointLog } from './chunk-QGVRRKB2.mjs';
3
3
  import { reportQuietly, LOG_HEADER_BYTES, LOG_FRAME_HEADER_BYTES, readLogHeader, foldLogChecksum, MAGIC_WITH_LITTLE_ENDIAN_CONTENT, LOG_FORMAT_VERSION } from './chunk-BUWJH3D3.mjs';
4
4
  import { readBackupChains, DEFAULT_CHAIN_NAME } from './chunk-6CABU54O.mjs';
@@ -1,5 +1,5 @@
1
- import { selectOrdinaryTableName, deleteReplacedRowsOfTable, selectMinChangeSeqSql, selectMaxChangeSeq, deleteChangesBeforeUpToSeqSql, deleteAllReplacedRows, selectTableExists, ensureChangesTable, ensureReplacedRowsTable, ensureMetaTable, insertMetaValueIfAbsent, selectMetaValue, selectTriggerSql, selectChangesAfterSeqSql, selectTablesChangesInRangeSql, tableInfoRows, primaryKeyColumns, tableColumnsWithGenerated, tableIndexList, indexColumns, selectTableSql, TABLE_XINFO_HIDDEN, deleteExpiredDeviceCursors, selectMinDeviceCursorBoundary, SEQ_STRING_RE, selectIndexSql } from './chunk-MTOQ6QIS.mjs';
2
- import { CDC_TRIGGER_PREFIX, CHANGES_TABLE, isReservedIdentifier, META_TABLE, encodeTaggedValues, REPLACED_ROWS_TABLE, changedAtToEventTimestamp, decodeTaggedValues, DEVICE_CURSORS_TABLE, SAFE_INT_BOUND_TEXT } from './chunk-ZAUHAJ4G.mjs';
1
+ import { selectOrdinaryTableName, deleteReplacedRowsOfTable, selectMinChangeSeqSql, selectMaxChangeSeq, deleteChangesBeforeUpToSeqSql, deleteAllReplacedRows, selectTableExists, ensureChangesTable, ensureReplacedRowsTable, ensureMetaTable, insertMetaValueIfAbsent, selectMetaValue, selectTriggerSql, selectChangesAfterSeqSql, selectTablesChangesInRangeSql, tableInfoRows, primaryKeyColumns, tableColumnsWithGenerated, tableIndexList, indexColumns, selectTableSql, TABLE_XINFO_HIDDEN, deleteExpiredDeviceCursors, selectMinDeviceCursorBoundary, SEQ_STRING_RE, selectIndexSql } from './chunk-2EYLKZZY.mjs';
2
+ import { CDC_TRIGGER_PREFIX, CHANGES_TABLE, isReservedIdentifier, META_TABLE, encodeTaggedValues, REPLACED_ROWS_TABLE, changedAtToEventTimestamp, decodeTaggedValues, DEVICE_CURSORS_TABLE, SAFE_INT_BOUND_TEXT } from './chunk-ZD5FP3IW.mjs';
3
3
  import { tokenizeSql, isKeyword } from './chunk-SEL4A4WT.mjs';
4
4
  import { randomHex } from './chunk-BGJ5JVYL.mjs';
5
5
  import { invokeCallerCallback, reportCallerFailure, toError } from './chunk-HO2XTXVX.mjs';
@@ -146,6 +146,22 @@ function minLength(requirement, message$1) {
146
146
  };
147
147
  }
148
148
  // @__NO_SIDE_EFFECTS__
149
+ function minValue(requirement, message$1) {
150
+ return {
151
+ kind: "validation",
152
+ type: "min_value",
153
+ reference: minValue,
154
+ async: false,
155
+ expects: `>=${requirement instanceof Date ? requirement.toJSON() : /* @__PURE__ */ _stringify(requirement)}`,
156
+ requirement,
157
+ message: message$1,
158
+ "~run"(dataset, config$1) {
159
+ if (dataset.typed && !(dataset.value >= this.requirement)) _addIssue(this, "value", dataset, config$1, { received: dataset.value instanceof Date ? dataset.value.toJSON() : /* @__PURE__ */ _stringify(dataset.value) });
160
+ return dataset;
161
+ }
162
+ };
163
+ }
164
+ // @__NO_SIDE_EFFECTS__
149
165
  function regex(requirement, message$1) {
150
166
  return {
151
167
  kind: "validation",
@@ -162,6 +178,22 @@ function regex(requirement, message$1) {
162
178
  };
163
179
  }
164
180
  // @__NO_SIDE_EFFECTS__
181
+ function safeInteger(message$1) {
182
+ return {
183
+ kind: "validation",
184
+ type: "safe_integer",
185
+ reference: safeInteger,
186
+ async: false,
187
+ expects: null,
188
+ requirement: Number.isSafeInteger,
189
+ message: message$1,
190
+ "~run"(dataset, config$1) {
191
+ if (dataset.typed && !this.requirement(dataset.value)) _addIssue(this, "safe integer", dataset, config$1);
192
+ return dataset;
193
+ }
194
+ };
195
+ }
196
+ // @__NO_SIDE_EFFECTS__
165
197
  function getFallback(schema, dataset, config$1) {
166
198
  return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
167
199
  }
@@ -582,4 +614,4 @@ function summarize(issues) {
582
614
  return summary;
583
615
  }
584
616
 
585
- export { array, check, custom, getDotPath, instance, literal, maxLength, minLength, nullable, number, object, optional, picklist, pipe, record, regex, safeParse, string, summarize, union, unknown };
617
+ export { array, check, custom, getDotPath, instance, literal, maxLength, minLength, minValue, nullable, number, object, optional, picklist, pipe, record, regex, safeInteger, safeParse, string, summarize, union, unknown };
@@ -13,6 +13,7 @@ var DEVICE_CURSORS_TABLE = "_sirannon_device_cursors";
13
13
  var STAGED_CHANGES_TABLE = "_sirannon_staged_changes";
14
14
  var STAGED_PUSH_CHANGES_TABLE = "_sirannon_staged_push_changes";
15
15
  var REPLACED_ROWS_TABLE = "_sirannon_replaced_rows";
16
+ var ROLLED_BACK_CHANGES_TABLE = "_sirannon_rolled_back_changes";
16
17
  var CDC_TRIGGER_PREFIX = "_sirannon_trg_";
17
18
  var LIVE_PROBE_TABLE_PREFIX = "_sirannon_live_probe_";
18
19
  var KEY_CHANGE_CAPTURE_PREFIX = "_sirannon_key_change_";
@@ -302,4 +303,4 @@ function decodeHexBytes(hex) {
302
303
  return bytes;
303
304
  }
304
305
 
305
- export { APPLIED_CHANGES_TABLE, CDC_TRIGGER_PREFIX, CHANGES_TABLE, COLUMN_VERSIONS_TABLE, DEVICE_CURSORS_TABLE, INTERNAL_TABLE_PREFIX, KEY_CHANGE_CAPTURE_PREFIX, LIVE_PROBE_TABLE_PREFIX, META_TABLE, MIGRATIONS_TABLE, PEER_STATE_TABLE, REPLACED_ROWS_TABLE, SAFE_INT_BOUND_TEXT, STAGED_CHANGES_TABLE, STAGED_PUSH_CHANGES_TABLE, SYNC_STATE_TABLE, assertSqlAllowed, changedAtToEventTimestamp, decodeTaggedValues, encodeTaggedValues, encodeWireRowsInPlace, eventTimestampToChangedAt, isReservedIdentifier };
306
+ export { APPLIED_CHANGES_TABLE, CDC_TRIGGER_PREFIX, CHANGES_TABLE, COLUMN_VERSIONS_TABLE, DEVICE_CURSORS_TABLE, INTERNAL_TABLE_PREFIX, KEY_CHANGE_CAPTURE_PREFIX, LIVE_PROBE_TABLE_PREFIX, META_TABLE, MIGRATIONS_TABLE, PEER_STATE_TABLE, REPLACED_ROWS_TABLE, ROLLED_BACK_CHANGES_TABLE, SAFE_INT_BOUND_TEXT, STAGED_CHANGES_TABLE, STAGED_PUSH_CHANGES_TABLE, SYNC_STATE_TABLE, assertSqlAllowed, changedAtToEventTimestamp, decodeTaggedValues, encodeTaggedValues, encodeWireRowsInPlace, eventTimestampToChangedAt, isReservedIdentifier };
@@ -1,9 +1,9 @@
1
- import { runCodegen } from '../chunk-RWPKDNT3.mjs';
1
+ import { runCodegen } from '../chunk-K3Z4TEP2.mjs';
2
2
  import '../chunk-D3YF2G7X.mjs';
3
3
  import '../chunk-KB4OLJAD.mjs';
4
4
  import '../chunk-SEL4A4WT.mjs';
5
5
  import '../chunk-GVCNMPOS.mjs';
6
- import '../chunk-O3FX3SD4.mjs';
6
+ import '../chunk-V4NPLS4E.mjs';
7
7
  import '../chunk-KINDFBQP.mjs';
8
8
 
9
9
  // src/codegen/cli.ts
@@ -1,7 +1,7 @@
1
- export { CODEGEN_USAGE, OPERATION_MANIFEST_VERSION, buildOperationManifest, parseOperationManifest, renderGoOperations, renderOperationTypes, renderPythonOperations, runCodegen, selectColumns } from '../chunk-RWPKDNT3.mjs';
1
+ export { CODEGEN_USAGE, OPERATION_MANIFEST_VERSION, buildOperationManifest, parseOperationManifest, renderGoOperations, renderOperationTypes, renderPythonOperations, runCodegen, selectColumns } from '../chunk-K3Z4TEP2.mjs';
2
2
  import '../chunk-D3YF2G7X.mjs';
3
3
  import '../chunk-KB4OLJAD.mjs';
4
4
  import '../chunk-SEL4A4WT.mjs';
5
5
  import '../chunk-GVCNMPOS.mjs';
6
- import '../chunk-O3FX3SD4.mjs';
6
+ import '../chunk-V4NPLS4E.mjs';
7
7
  import '../chunk-KINDFBQP.mjs';
@@ -1,19 +1,19 @@
1
- import { Transaction, MetricsCollector, readOutcome, failedStatementOutcome, settleLateOutcome, ROW_COUNTS_UNKNOWN, leavesOutcomeUnknown, LWWResolver, REMOTE_ORIGIN_NODE_ID, BatchReader, BatchApplier, recordLocalColumnVersions, writeOutcome, batchWriteOutcome, StatementRecorder, loadPersistedHlc, isWellFormedHlc, HLC_CLOCK_META_KEY, readOneOutcome } from '../chunk-VKCUSREW.mjs';
2
- export { MetricsCollector, Transaction } from '../chunk-VKCUSREW.mjs';
3
- import { executeGroup } from '../chunk-ULUZUBON.mjs';
4
- import { query, queryRowsForWire, queryOne, asQueryError, runInSavepoint, runWriterTransaction, withoutRowCounts, execute, executeBatchSummary, bindParams, executeBatch, queryMetered, queryForWire, queryOneMetered } from '../chunk-ZWW53O5P.mjs';
5
- export { execute, executeBatch, query, queryOne } from '../chunk-ZWW53O5P.mjs';
1
+ import { Transaction, MetricsCollector, readOutcome, failedStatementOutcome, settleLateOutcome, ROW_COUNTS_UNKNOWN, leavesOutcomeUnknown, LWWResolver, REMOTE_ORIGIN_NODE_ID, BatchReader, BatchApplier, recordLocalColumnVersions, writeOutcome, batchWriteOutcome, StatementRecorder, loadPersistedHlc, isWellFormedHlc, HLC_CLOCK_META_KEY, readOneOutcome } from '../chunk-PR2APVRF.mjs';
2
+ export { MetricsCollector, Transaction } from '../chunk-PR2APVRF.mjs';
3
+ import { executeGroup } from '../chunk-DQ5EB7CS.mjs';
4
+ import { query, queryRowsForWire, queryOne, asQueryError, runInSavepoint, runWriterTransaction, withoutRowCounts, execute, executeBatchSummary, bindParams, executeBatch, queryMetered, queryForWire, queryOneMetered } from '../chunk-C3OVUSZP.mjs';
5
+ export { execute, executeBatch, query, queryOne } from '../chunk-C3OVUSZP.mjs';
6
6
  import { unsupported, findClauses, readSource, readSortTerms, readWindow, readSelectItems } from '../chunk-D3YF2G7X.mjs';
7
- import { reconcileMigrationChecksums, migrationContentChecksum, resolveDeviceRetentionPolicy, ensureCdcEpoch, SubscriptionBuilderImpl, ChangeTracker, SubscriptionManager, startPolling, DEVICE_SYNC_PUSHED_SEQ_META_KEY, runBulkLoad, parseColumnDefinitions, dropMainSchemaTriggers, createMainSchemaTriggers, TransactionGrouper, PrimedSubscription, dropCdcTriggers, escId, ROWID_ALIASES, installKeyChangeCaptureTriggers, dropKeyChangeCaptureTriggers } from '../chunk-2ZQOZFX7.mjs';
8
- export { ChangeTracker, isBulkLoadDurability, runBulkLoad } from '../chunk-2ZQOZFX7.mjs';
9
- import { EncryptionKeyring, planBackupRestore, backupPiecesSafeToDelete, resolveEncryptionKey, wipeEncryptionKey } from '../chunk-GCOJFQOL.mjs';
10
- export { backupPiecesSafeToDelete, planBackupRestore } from '../chunk-GCOJFQOL.mjs';
11
- import { ensureMigrationsTable, prepareUpdateMigrationChecksum, prepareInsertMigration, selectAppliedMigrationsNewestFirst, prepareDeleteMigration, selectAppliedMigrations, selectTableExists, selectMetaValue, deleteMetaValue, ensureMetaTable, upsertMetaValue, SEQ_STRING_RE, replaceMigrationHistory, highestMigrationVersion, selectCountOutboundChanges, ensureChangesTable, ensureBatchApplyTables, ensureStagedPushChangesTable, PkResolver, selectMaxChangeSeq, selectMaxAppliedSourceSeq, tableColumnsWithGenerated, TABLE_XINFO_HIDDEN, selectTableSql, primaryKeyColumns, tableIndexList, upsertMetaMaxChangeSeqSql, updateChangeStampsAboveMetaSeqSql, upsertMetaValueAndMaxChangeSeqSql, insertMetaValueIfAbsent, HLC, selectMaxChangeHlc, setForeignKeysEnabled, IDENTIFIER_RE, validateDdlSafety, ensureStagedChangesTable, upsertStagedChangeSql, selectFirstStagedTransactionEnd, deleteStagedChangesUpToSeq, selectMaxStagedSeq, deleteAllStagedChanges, selectStagedChangesInRange, assertSafeIdentifier } from '../chunk-MTOQ6QIS.mjs';
7
+ import { reconcileMigrationChecksums, migrationContentChecksum, resolveDeviceRetentionPolicy, ensureCdcEpoch, SubscriptionBuilderImpl, ChangeTracker, SubscriptionManager, startPolling, DEVICE_SYNC_PUSHED_SEQ_META_KEY, runBulkLoad, parseColumnDefinitions, dropMainSchemaTriggers, createMainSchemaTriggers, TransactionGrouper, PrimedSubscription, dropCdcTriggers, escId, ROWID_ALIASES, installKeyChangeCaptureTriggers, dropKeyChangeCaptureTriggers } from '../chunk-S36XLMIW.mjs';
8
+ export { ChangeTracker, isBulkLoadDurability, runBulkLoad } from '../chunk-S36XLMIW.mjs';
9
+ import { EncryptionKeyring, planBackupRestore, backupPiecesSafeToDelete, resolveEncryptionKey, wipeEncryptionKey } from '../chunk-EOESJH5I.mjs';
10
+ export { backupPiecesSafeToDelete, planBackupRestore } from '../chunk-EOESJH5I.mjs';
11
+ import { ensureMigrationsTable, prepareUpdateMigrationChecksum, prepareInsertMigration, selectAppliedMigrationsNewestFirst, prepareDeleteMigration, selectAppliedMigrations, selectTableExists, selectMetaValue, deleteMetaValue, ensureMetaTable, upsertMetaValue, SEQ_STRING_RE, replaceMigrationHistory, highestMigrationVersion, selectCountOutboundChanges, ensureChangesTable, ensureBatchApplyTables, ensureStagedPushChangesTable, PkResolver, selectMaxChangeSeq, selectMaxAppliedSourceSeq, tableColumnsWithGenerated, TABLE_XINFO_HIDDEN, selectTableSql, primaryKeyColumns, tableIndexList, upsertMetaMaxChangeSeqSql, updateChangeStampsAboveMetaSeqSql, upsertMetaValueAndMaxChangeSeqSql, insertMetaValueIfAbsent, HLC, selectMaxChangeHlc, setForeignKeysEnabled, IDENTIFIER_RE, validateDdlSafety, ensureStagedChangesTable, upsertStagedChangeSql, selectFirstStagedTransactionEnd, deleteStagedChangesUpToSeq, selectMaxStagedSeq, deleteAllStagedChanges, selectStagedChangesInRange, assertSafeIdentifier } from '../chunk-2EYLKZZY.mjs';
12
12
  import { ReplicationError } from '../chunk-BLMRNSUG.mjs';
13
- import { MIGRATIONS_TABLE, META_TABLE, CHANGES_TABLE, assertSqlAllowed, LIVE_PROBE_TABLE_PREFIX, eventTimestampToChangedAt, encodeTaggedValues, INTERNAL_TABLE_PREFIX, isReservedIdentifier, decodeTaggedValues, changedAtToEventTimestamp, KEY_CHANGE_CAPTURE_PREFIX } from '../chunk-ZAUHAJ4G.mjs';
13
+ import { MIGRATIONS_TABLE, META_TABLE, CHANGES_TABLE, assertSqlAllowed, LIVE_PROBE_TABLE_PREFIX, eventTimestampToChangedAt, encodeTaggedValues, INTERNAL_TABLE_PREFIX, isReservedIdentifier, decodeTaggedValues, changedAtToEventTimestamp, KEY_CHANGE_CAPTURE_PREFIX } from '../chunk-ZD5FP3IW.mjs';
14
14
  import { tokenizeSql, isKeyword, parameterName } from '../chunk-SEL4A4WT.mjs';
15
15
  import '../chunk-GVCNMPOS.mjs';
16
- import '../chunk-O3FX3SD4.mjs';
16
+ import '../chunk-V4NPLS4E.mjs';
17
17
  import { defaultStagingDir } from '../chunk-Y4SP7CRF.mjs';
18
18
  import { startCopyWithoutHoldingWriter, readMainDatabasePath } from '../chunk-I4JY5QPA.mjs';
19
19
  import { lateRowCountsOf, lateGroupOutcomesOf, withoutLateRowCounts, withLateRowCounts } from '../chunk-K43WJORM.mjs';
@@ -1,6 +1,6 @@
1
- import { executeGroup } from '../chunk-ULUZUBON.mjs';
2
- import '../chunk-ZWW53O5P.mjs';
3
- import '../chunk-ZAUHAJ4G.mjs';
1
+ import { executeGroup } from '../chunk-DQ5EB7CS.mjs';
2
+ import '../chunk-C3OVUSZP.mjs';
3
+ import '../chunk-ZD5FP3IW.mjs';
4
4
  import { WORKER_CANCELLED_CODE, serializeError, WORKER_BEGIN_FAILED_CODE, WORKER_COPY_STOPPED_CODE } from '../chunk-75IBRE73.mjs';
5
5
  import { addRowCounts, rowCountsOf, withRowCounts } from '../chunk-E2GRX4ZD.mjs';
6
6
  import { SirannonError } from '../chunk-KINDFBQP.mjs';
@@ -1,5 +1,5 @@
1
1
  import { IOptions } from 'etcd3';
2
- import { C as ClusterCoordinator, A as AcquireControllerLeaseInput, a as AcquireControllerLeaseResult, b as ControllerLeaseWatcher, c as CoordinatorWatchDisposer, R as RegisterNodeSessionInput, d as CoordinatorNodeSession, N as NodeSessionWatcher, S as SetReplicationGroupStateInput, e as ReplicationGroupState, f as CreateReplicationGroupStateResult, g as AddVoterInput, V as VoterChangeResult, h as RemoveVoterInput, i as ReplicationGroupWatcher, j as CompareAndAdvancePrimaryTermInput, k as CompareAndAdvancePrimaryTermResult, U as UpdateInSyncSetInput, l as AdmitNodeToInSyncSetInput, m as UpdateNodeMaintenanceInput, P as PromoteEligibleReplicaInput } from '../../types-MczwKtul.js';
2
+ import { C as ClusterCoordinator, A as AcquireControllerLeaseInput, a as AcquireControllerLeaseResult, b as ControllerLeaseWatcher, c as CoordinatorWatchDisposer, R as RegisterNodeSessionInput, d as CoordinatorNodeSession, N as NodeSessionWatcher, S as SetReplicationGroupStateInput, e as ReplicationGroupState, f as CreateReplicationGroupStateResult, g as AddVoterInput, V as VoterChangeResult, h as RemoveVoterInput, i as RaiseFeatureLevelInput, j as ReplicationGroupWatcher, k as CompareAndAdvancePrimaryTermInput, l as CompareAndAdvancePrimaryTermResult, U as UpdateInSyncSetInput, m as AdmitNodeToInSyncSetInput, n as UpdateNodeMaintenanceInput, P as PromoteEligibleReplicaInput } from '../../types-qJL9h6Qe.js';
3
3
 
4
4
  /**
5
5
  * Sets the etcd endpoints that the etcd coordinator connects to, the key prefix that it stores group state under, and
@@ -94,6 +94,8 @@ declare class EtcdClusterCoordinator implements ClusterCoordinator {
94
94
  addVoter(input: AddVoterInput): Promise<VoterChangeResult>;
95
95
  /** Removes a voter or a pending voter from the group, while the group's voters match the expected list. */
96
96
  removeVoter(input: RemoveVoterInput): Promise<VoterChangeResult>;
97
+ /** Raises the group's feature level, while every member holds a live session that supports the new level. */
98
+ raiseFeatureLevel(input: RaiseFeatureLevelInput): Promise<ReplicationGroupState | null>;
97
99
  /** Returns the group's state, or null when etcd has no state for the group. */
98
100
  getReplicationGroupState(clusterId: string, groupId: string): Promise<ReplicationGroupState | null>;
99
101
  /** Calls `watcher` with the new state after each change to the group, and returns a function that stops the watch. */