feat(app): add background worker for provider health checks

Introduce a `worker` module with `background_worker` that periodically refreshes provider health and emits status updates via the app's message channel. Add `spawn_background_worker` method to `App` for launching the worker as a Tokio task.
This commit is contained in:
2025-10-16 21:01:08 +02:00
parent ea04a25ed6
commit dc0fee2ee3
2 changed files with 63 additions and 0 deletions

View File

@@ -1,4 +1,5 @@
mod generation; mod generation;
mod worker;
pub mod messages; pub mod messages;
@@ -51,6 +52,16 @@ impl App {
active.abort(); active.abort();
} }
} }
/// Launch the background worker responsible for provider health checks.
pub fn spawn_background_worker(&self) -> JoinHandle<()> {
let manager = Arc::clone(&self.provider_manager);
let sender = self.message_tx.clone();
tokio::spawn(async move {
worker::background_worker(manager, sender).await;
})
}
} }
struct ActiveGeneration { struct ActiveGeneration {

View File

@@ -0,0 +1,52 @@
use std::sync::Arc;
use std::time::Duration;
use tokio::{sync::mpsc, time};
use owlen_core::provider::ProviderManager;
use super::AppMessage;
const HEALTH_CHECK_INTERVAL: Duration = Duration::from_secs(30);
/// Periodically refresh provider health and emit status updates into the app's
/// message channel. Exits automatically once the receiver side of the channel
/// is dropped.
pub async fn background_worker(
provider_manager: Arc<ProviderManager>,
message_tx: mpsc::UnboundedSender<AppMessage>,
) {
let mut interval = time::interval(HEALTH_CHECK_INTERVAL);
let mut last_statuses = provider_manager.provider_statuses().await;
loop {
interval.tick().await;
if message_tx.is_closed() {
break;
}
let statuses = provider_manager.refresh_health().await;
for (provider_id, status) in statuses {
let changed = match last_statuses.get(&provider_id) {
Some(previous) => previous != &status,
None => true,
};
last_statuses.insert(provider_id.clone(), status);
if changed
&& message_tx
.send(AppMessage::ProviderStatus {
provider_id,
status,
})
.is_err()
{
// Receiver dropped; terminate worker.
return;
}
}
}
}