use std::sync::Arc;
use super::super::super::persist::SurrogateHwmPersist;
use super::super::super::registry::SurrogateRegistry;
use super::super::super::wal_appender::SurrogateWalAppender;
use super::types::SurrogateAssigner;
use crate::control::security::catalog::SystemCatalog;
use crate::control::state::SharedState;
impl SurrogateAssigner {
pub fn current_hwm(&self) -> u32 {
self.registry
.read()
.map(|reg| reg.current_hwm())
.unwrap_or_else(|p| p.into_inner().current_hwm())
}
pub(in crate::control::surrogate::assign) fn maybe_flush(
&self,
registry: &SurrogateRegistry,
catalog: &SystemCatalog,
) -> crate::Result<()> {
if self.should_use_reservation() {
return Ok(());
}
if registry.should_flush() {
let combined = CombinedPersist {
catalog,
wal_appender: self.wal_appender.as_ref(),
raft_shared: self.shared.get().and_then(|w| w.upgrade()),
};
registry.flush(&combined)?;
}
Ok(())
}
}
struct CombinedPersist<'a> {
catalog: &'a SystemCatalog,
wal_appender: &'a dyn SurrogateWalAppender,
raft_shared: Option<Arc<SharedState>>,
}
impl SurrogateHwmPersist for CombinedPersist<'_> {
fn checkpoint(&self, hwm: u32) -> crate::Result<()> {
self.catalog.put_surrogate_hwm(hwm)?;
self.wal_appender.record_alloc_to_wal(hwm)?;
if let Some(shared) = &self.raft_shared {
spawn_hwm_propose(Arc::clone(shared), hwm);
}
Ok(())
}
fn load(&self) -> crate::Result<u32> {
self.catalog.get_surrogate_hwm()
}
}
fn spawn_hwm_propose(shared: Arc<SharedState>, hwm: u32) {
let Ok(handle) = tokio::runtime::Handle::try_current() else {
tracing::debug!(
hwm,
"surrogate hwm checkpoint ran outside a Tokio runtime; \
skipping the metadata propose (hwm is durable locally; \
the next flush under a reactor re-proposes it)"
);
return;
};
handle.spawn(async move {
if let Err(e) = crate::control::metadata_proposer::propose_surrogate_hwm(&shared, hwm) {
tracing::warn!(hwm, error = %e, "surrogate hwm raft propose failed; followers may lag");
}
});
}