use tokio::sync::mpsc;
use crate::state::AppState;
pub trait HandlerConfig {
type Result: Clone;
fn get_resolving(&self, app: &AppState) -> bool;
fn set_resolving(&self, app: &mut AppState, value: bool);
fn get_preflight_resolving(&self, app: &AppState) -> bool;
fn set_preflight_resolving(&self, app: &mut AppState, value: bool);
fn stage_name(&self) -> &'static str;
fn update_cache(&self, app: &mut AppState, results: &[Self::Result]);
fn set_cache_dirty(&self, app: &mut AppState);
fn clear_preflight_items(&self, app: &mut AppState);
fn sync_to_modal(&self, app: &mut AppState, results: &[Self::Result], was_preflight: bool);
fn log_flag_clear(&self, app: &AppState, was_preflight: bool, cancelled: bool);
fn is_resolution_complete(&self, app: &AppState, results: &[Self::Result]) -> bool {
let _ = (app, results);
true
}
}
pub fn handle_result<C: HandlerConfig>(
app: &mut AppState,
results: &[C::Result],
tick_tx: &mpsc::UnboundedSender<()>,
config: &C,
) {
let cancelled = app
.preflight_cancelled
.load(std::sync::atomic::Ordering::Relaxed);
let was_preflight = config.get_preflight_resolving(app);
config.log_flag_clear(app, was_preflight, cancelled);
let is_complete = config.is_resolution_complete(app, results);
if is_complete {
config.set_resolving(app, false);
}
config.set_preflight_resolving(app, false);
if cancelled {
if was_preflight {
tracing::debug!(
"[Runtime] Ignoring {} result (preflight cancelled)",
config.stage_name()
);
config.clear_preflight_items(app);
}
let _ = tick_tx.send(());
return;
}
tracing::info!(
stage = config.stage_name(),
result_count = results.len(),
was_preflight = was_preflight,
"[Runtime] {} resolution worker completed",
config.stage_name()
);
config.update_cache(app, results);
config.sync_to_modal(app, results, was_preflight);
if was_preflight {
config.clear_preflight_items(app);
}
config.set_cache_dirty(app);
let _ = tick_tx.send(());
}