feat(raft): replicate schema DDL through the raft log
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled

- isRaftDdl + leader-only gate for CREATE/DROP/ALTER (not DATABASE)
- appendDdlToRaft ships original SQL; applyCommand re-executes via
  applyReplicatedDdl (idempotent on leader double-apply)
- Mixed DDL+DML batches use the DDL path so order is preserved
- Fix secondary-index point lookup to use entry.lsmKey (not filter col)
- E2E: CREATE only on leader, schema + index SELECT on follower
This commit is contained in:
2026-07-30 21:25:58 +03:00
parent 50f827f8cf
commit 095698ba82
10 changed files with 180 additions and 41 deletions
+8
View File
@@ -488,3 +488,11 @@ proc applyReplicatedDelete*(ctx: ExecutionContext, fullKey: string) =
if found and table.len > 0:
removeIndexesForRow(ctx, table, fullKey, cast[string](existing))
ctx.db.delete(fullKey)
proc isBenignRaftReplayError*(msg: string): bool =
## Leader re-applies committed DDL/DML after local execution; followers may
## also see IF EXISTS / race re-applies. Treat common idempotent failures as OK.
let m = msg.toLower()
"already exists" in m or "does not exist" in m or
"duplicate" in m or "unique" in m or
"unknown table" in m or "no such table" in m
+11
View File
@@ -179,6 +179,17 @@ proc isDDL*(stmt: Node): bool =
else:
result = false
proc isRaftDdl*(stmt: Node): bool =
## Schema changes that go through the Raft log when clustering is on.
## CREATE/DROP DATABASE are excluded — multi-DB is out of scope for v1 raft
## (state machine is wired only to the default database).
if not isDDL(stmt): return false
case stmt.kind
of nkCreateDatabase, nkDropDatabase:
result = false
else:
result = true
proc isWrite*(stmt: Node): bool =
## True for statements that mutate stored data. `nkCommitTxn` is included
## because COMMIT emits the transaction's buffered kvPairs.