huskies: merge 762

This commit is contained in:
dave
2026-04-28 01:27:00 +00:00
parent de5b585157
commit 0d14fffe1c
6 changed files with 253 additions and 2 deletions
+51
View File
@@ -302,6 +302,50 @@ pub fn init_wizard_state(path: &Path) {
// ── Notification poller ─────────────────────────────────────────────────────
/// Spawn a background task that reads [`super::GatewayStatusEvent`]s from the
/// gateway broadcast channel and forwards each one to the configured rooms via
/// `transport`, formatted with a `[project-name]` prefix.
///
/// Survives broadcaster back-pressure: when the receiver falls behind
/// ([`tokio::sync::broadcast::error::RecvError::Lagged`]), the task
/// re-subscribes so it does not permanently stall.
///
/// The task exits cleanly when the broadcast channel is closed (i.e. when
/// `GatewayState` is dropped).
pub fn spawn_gateway_broadcaster_forwarder(
transport: std::sync::Arc<dyn crate::chat::ChatTransport>,
room_ids: Vec<String>,
mut rx: tokio::sync::broadcast::Receiver<super::GatewayStatusEvent>,
) {
tokio::spawn(async move {
loop {
match rx.recv().await {
Ok(event) => {
let (plain, html) =
super::polling::format_gateway_event(&event.project, &event.event);
for room_id in &room_ids {
if let Err(e) = transport.send_message(room_id, &plain, &html).await {
crate::slog!(
"[gateway-forwarder] Failed to forward event to {room_id}: {e}"
);
}
}
}
Err(tokio::sync::broadcast::error::RecvError::Lagged(n)) => {
crate::slog!(
"[gateway-forwarder] Broadcaster lagged by {n} messages; resubscribing"
);
rx = rx.resubscribe();
}
Err(tokio::sync::broadcast::error::RecvError::Closed) => {
crate::slog!("[gateway-forwarder] Broadcast channel closed; forwarder exiting");
break;
}
}
}
});
}
/// Spawn a background task that polls events from all project servers.
pub fn spawn_gateway_notification_poller(
transport: std::sync::Arc<dyn crate::chat::ChatTransport>,
@@ -374,12 +418,17 @@ pub fn spawn_gateway_notification_poller(
pub type ActiveProject = std::sync::Arc<tokio::sync::RwLock<String>>;
/// Attempt to spawn the Matrix bot against the gateway config directory.
///
/// `gateway_event_tx` — when `Some`, the bot will subscribe to the gateway
/// status broadcaster and forward [`super::GatewayStatusEvent`]s to its
/// configured Matrix rooms with a `[project-name]` prefix.
pub fn spawn_gateway_bot(
config_dir: &Path,
active_project: ActiveProject,
gateway_projects: Vec<String>,
gateway_project_urls: BTreeMap<String, String>,
port: u16,
gateway_event_tx: Option<tokio::sync::broadcast::Sender<super::GatewayStatusEvent>>,
) -> Option<tokio::task::AbortHandle> {
use crate::agents::AgentPool;
use crate::services::Services;
@@ -412,6 +461,7 @@ pub fn spawn_gateway_bot(
let timer_store = std::sync::Arc::new(crate::service::timer::TimerStore::load(
config_dir.join(".huskies").join("timers.json"),
));
let gateway_event_rx = gateway_event_tx.map(|tx| tx.subscribe());
crate::chat::transport::matrix::spawn_bot(
config_dir,
watcher_tx,
@@ -421,5 +471,6 @@ pub fn spawn_gateway_bot(
gateway_projects,
gateway_project_urls,
timer_store,
gateway_event_rx,
)
}
+5 -1
View File
@@ -16,7 +16,10 @@ pub mod registration;
pub use aggregation::format_aggregate_status_compact;
pub use config::{GatewayConfig, ProjectEntry};
pub use io::{fetch_all_project_pipeline_statuses, spawn_gateway_notification_poller};
pub use io::{
fetch_all_project_pipeline_statuses, spawn_gateway_broadcaster_forwarder,
spawn_gateway_notification_poller,
};
pub use registration::JoinedAgent;
use io::Client;
@@ -452,6 +455,7 @@ pub async fn save_bot_config_and_restart(state: &GatewayState, content: &str) ->
gateway_projects,
gateway_project_urls,
state.port,
Some(state.event_tx.clone()),
);
*handle = new_handle;
}