MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / submit

Method submit

nodedb-wal/src/group_commit.rs:106–188  ·  view source on GitHub ↗

Submit a write and block until it's durable. Returns the assigned LSN once the batch containing this write has been fsynced to disk. If fsync fails, the error is propagated to all threads whose writes were in the failed batch.

(&self, writer: &Mutex<WalWriter>, write: PendingWrite)

Source from the content-addressed store, hash-verified

104 /// fsynced to disk. If fsync fails, the error is propagated to all threads
105 /// whose writes were in the failed batch.
106 pub fn submit(&self, writer: &Mutex<WalWriter>, write: PendingWrite) -> Result<CommitResult> {
107 // Enqueue the write.
108 {
109 let mut pending = self.pending.lock().map_err(|_| WalError::LockPoisoned {
110 context: "pending queue",
111 })?;
112 pending.push(write);
113 }
114
115 // Try to become the commit leader. If another thread holds the commit
116 // lock, we block here until it finishes — then we check if our write
117 // was already committed by that leader.
118 let _commit_guard = self
119 .commit_lock
120 .lock()
121 .map_err(|_| WalError::LockPoisoned {
122 context: "commit lock",
123 })?;
124
125 // Drain pending writes. If the previous leader already committed our
126 // write, the pending queue will be empty (our write was drained by
127 // that leader). If the queue is non-empty, we are the new leader.
128 let batch: Vec<PendingWrite> = {
129 let mut pending = self.pending.lock().map_err(|_| WalError::LockPoisoned {
130 context: "pending queue (drain)",
131 })?;
132 std::mem::take(&mut *pending)
133 };
134
135 if batch.is_empty() {
136 // Previous leader drained our write. Check if that commit
137 // succeeded or failed. This is the critical fix: without this
138 // check, a non-leader would return durable:true even if the
139 // leader's fsync failed.
140 if self.last_commit_failed.load(Ordering::Acquire) {
141 return Err(WalError::Io(std::io::Error::other(
142 "WAL fsync failed in previous group commit batch",
143 )));
144 }
145 let lsn = self.durable_lsn.load(Ordering::Acquire);
146 return Ok(CommitResult { lsn, durable: true });
147 }
148
149 // We are the leader — append and fsync.
150 let mut wal = writer.lock().map_err(|_| WalError::LockPoisoned {
151 context: "WAL writer",
152 })?;
153 let mut last_lsn = 0;
154
155 for w in &batch {
156 last_lsn = wal.append(
157 w.record_type,
158 w.tenant_id,
159 w.vshard_id,
160 w.database_id,
161 &w.payload,
162 )?;
163 }

Calls 8

takeFunction · 0.85
lockMethod · 0.80
pushMethod · 0.45
is_emptyMethod · 0.45
loadMethod · 0.45
appendMethod · 0.45
syncMethod · 0.45
storeMethod · 0.45