fix(raft): multi-stmt write gate, rich apply, delete kv convention
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
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
- Reject follower writes if any statement in the batch is DML/COMMIT (not only stmts[0]). - COMMIT always emits empty-valued kvPairs for isDelete entries. - applyCommand updates LSM plus secondary B-tree/FTS/HNSW indexes (applyReplicatedPut/Delete) so follower index scans see replicated rows. - Tests: not-leader append, commit timeout, index apply unit, E2E index-backed SELECT on follower.
This commit is contained in:
@@ -253,8 +253,14 @@ proc executeQuery(db: LSMTree, ctx: ExecutionContext, query: string, params: seq
|
||||
return (true, QueryResult(), "")
|
||||
|
||||
# C3b: writes go through the Raft log — only the leader may accept them.
|
||||
if raftNode != nil and isWrite(astNode.stmts[0]):
|
||||
if raftNode.state != rsLeader:
|
||||
# Inspect every statement so "SELECT 1; INSERT ..." cannot bypass the gate.
|
||||
if raftNode != nil:
|
||||
var hasWrite = false
|
||||
for stmt in astNode.stmts:
|
||||
if isWrite(stmt):
|
||||
hasWrite = true
|
||||
break
|
||||
if hasWrite and raftNode.state != rsLeader:
|
||||
let who = if raftNode.leaderId.len > 0: raftNode.leaderId else: "none elected"
|
||||
return (false, QueryResult(), "not leader; leader is '" & who & "'")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user