Skip to content

Commit 1448c55

Browse files
committed
Drain persistence barrier when PREPARE is durable, not on COMMIT
The barrier should block persistence only until the PREPARE record is confirmed durable. Once durable, subsequent transactions can persist normally. The previous code held the barrier until the coordinator sent COMMIT, unnecessarily blocking all persistence during the 2PC handshake round-trip. Now: prepare_reducer waits for PREPARE durability, then immediately drains the buffer. commit_prepared just removes from the registry. abort_prepared still needs to invert in-memory state (TODO).
1 parent eb8da3d commit 1448c55

1 file changed

Lines changed: 18 additions & 8 deletions

File tree

crates/core/src/host/module_host.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,6 +1810,11 @@ impl ModuleHost {
18101810
let _ = durable_offset.wait_for(current + 1).await;
18111811
}
18121812

1813+
// PREPARE is now durable. Deactivate the barrier and flush all
1814+
// buffered speculative transactions to the durability worker.
1815+
// Subsequent transactions can persist normally until the next PREPARE.
1816+
self.relational_db().finalize_prepare_commit();
1817+
18131818
Ok((prepare_id, result, return_value))
18141819
} else {
18151820
// Reducer failed -- no prepare_id since nothing to commit/abort.
@@ -1819,25 +1824,30 @@ impl ModuleHost {
18191824

18201825
/// Finalize a prepared transaction as COMMIT.
18211826
///
1822-
/// Deactivates the persistence barrier and flushes all buffered durability
1823-
/// requests to the durability worker.
1827+
/// The persistence barrier was already deactivated (and buffered requests
1828+
/// flushed) when the PREPARE became durable in `prepare_reducer`. This
1829+
/// method just removes the prepared tx from the registry.
1830+
///
1831+
/// TODO: Write a COMMIT record to the commitlog so replay knows to apply
1832+
/// the PREPARE.
18241833
pub fn commit_prepared(&self, prepare_id: &str) -> Result<(), String> {
1825-
let _info = self.prepared_txs
1834+
self.prepared_txs
18261835
.remove(prepare_id)
18271836
.ok_or_else(|| format!("no such prepared transaction: {prepare_id}"))?;
1828-
self.relational_db().finalize_prepare_commit();
18291837
Ok(())
18301838
}
18311839

18321840
/// Abort a prepared transaction.
18331841
///
1834-
/// Deactivates the persistence barrier, discards all buffered durability
1835-
/// requests, and inverts the PREPARE's in-memory changes.
1842+
/// Inverts the PREPARE's in-memory changes and writes an ABORT record
1843+
/// so replay knows to skip the PREPARE.
1844+
///
1845+
/// TODO: Actually invert in-memory state and write ABORT to commitlog.
18361846
pub fn abort_prepared(&self, prepare_id: &str) -> Result<(), String> {
1837-
let info = self.prepared_txs
1847+
let _info = self.prepared_txs
18381848
.remove(prepare_id)
18391849
.ok_or_else(|| format!("no such prepared transaction: {prepare_id}"))?;
1840-
self.relational_db().finalize_prepare_abort(&info.tx_data);
1850+
log::warn!("2PC abort for {prepare_id}: in-memory inversion not yet implemented");
18411851
Ok(())
18421852
}
18431853

0 commit comments

Comments
 (0)