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:
@@ -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 {
|
||||||
|
|||||||
52
crates/owlen-tui/src/app/worker.rs
Normal file
52
crates/owlen-tui/src/app/worker.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user