use std::collections::HashSet;
use std::sync::atomic::Ordering;
use crate::data::executor::core_loop::CoreLoop;
use crate::types::TxnId;
pub(in crate::data::executor) const OVERLAY_LEASE_NS: i64 = 6 * 3_600 * 1_000_000_000;
pub(in crate::data::executor) const OVERLAY_REAP_BUDGET: usize = 1_024;
impl CoreLoop {
pub(in crate::data::executor) fn touch_overlay(&self, txn_id: TxnId) {
let ord = self.hlc.next_ordinal();
if let Some(overlay) = self.txn_overlays.get(&txn_id) {
overlay.touch(ord);
}
if let Some(overlay) = self.graph_txn_overlays.get(&txn_id) {
overlay.touch(ord);
}
}
pub(in crate::data::executor) fn drop_overlay_entry(&mut self, txn_id: TxnId) -> u64 {
let removed = u64::from(self.txn_overlays.remove(&txn_id).is_some())
+ u64::from(self.graph_txn_overlays.remove(&txn_id).is_some());
if removed > 0
&& let Some(m) = &self.metrics
{
m.active_txn_overlays.fetch_sub(removed, Ordering::Relaxed);
}
if let Some(created) = self.txn_created_columnar_engines.remove(&txn_id) {
for engine_key in created {
let still_empty = self
.columnar_engines
.get(&engine_key)
.is_some_and(|engine| engine.memtable().is_empty());
if still_empty {
self.columnar_engines.remove(&engine_key);
}
}
}
removed
}
pub(in crate::data::executor) fn reap_expired_overlays(&mut self) {
let threshold = self.hlc.peek().saturating_sub(OVERLAY_LEASE_NS);
let candidates: HashSet<TxnId> = self
.txn_overlays
.keys()
.chain(self.graph_txn_overlays.keys())
.copied()
.collect();
let mut expired: Vec<TxnId> = Vec::new();
for txn_id in candidates {
let value_ord = self.txn_overlays.get(&txn_id).map(|o| o.last_touch());
let graph_ord = self.graph_txn_overlays.get(&txn_id).map(|o| o.last_touch());
let Some(max_ord) = value_ord.into_iter().chain(graph_ord).max() else {
continue;
};
if max_ord < threshold {
expired.push(txn_id);
if expired.len() >= OVERLAY_REAP_BUDGET {
break;
}
}
}
if expired.is_empty() {
return;
}
let reaped = expired.len();
for txn_id in expired {
self.drop_overlay_entry(txn_id);
}
tracing::warn!(
core = self.core_id,
reaped,
"overlay lease GC: reclaimed abandoned per-txn staging overlays past \
lease (client vanished / teardown dispatch failed / leader moved \
mid-txn)"
);
}
}