purple_ssh/handler/
sync.rs1use std::sync::Arc;
2use std::sync::atomic::AtomicBool;
3use std::sync::mpsc;
4
5use log::{error, info, warn};
6
7use crate::event::AppEvent;
8
9pub fn spawn_provider_sync(
10 section: &crate::providers::config::ProviderSection,
11 tx: mpsc::Sender<AppEvent>,
12 cancel: Arc<AtomicBool>,
13 env: Arc<crate::runtime::env::Env>,
14) {
15 let name = section.id.to_string();
19 let token = section.token.clone();
20 let section_clone = section.clone();
21 let tx_fallback = tx.clone();
22 let name_fallback = name.clone();
23 log::debug!("Spawning provider sync thread: {name}");
24 if let Err(e) = std::thread::Builder::new()
25 .name(format!("sync-{}", name))
26 .spawn(move || {
27 let provider = match crate::providers::get_provider_with_config(§ion_clone) {
28 Some(p) => p,
29 None => {
30 warn!("[config] Unknown provider requested for sync: {name}");
31 let _ = tx.send(AppEvent::SyncError {
32 provider: name,
33 message: crate::messages::SYNC_UNKNOWN_PROVIDER.to_string(),
34 });
35 return;
36 }
37 };
38 info!("Provider sync started: {name}");
39 let progress_tx = tx.clone();
40 let progress_name = name.clone();
41 let progress = move |msg: &str| {
42 let _ = progress_tx.send(AppEvent::SyncProgress {
43 provider: progress_name.clone(),
44 message: msg.to_string(),
45 });
46 };
47 match provider.fetch_hosts_with_progress(&token, &cancel, &env, &progress) {
48 Ok(hosts) => {
49 if hosts.is_empty() {
50 warn!("[config] Provider sync returned 0 hosts: {name} (check API token permissions)");
51 } else {
52 info!("Provider sync completed: {name}, {} hosts found", hosts.len());
53 }
54 let _ = tx.send(AppEvent::SyncComplete {
55 provider: name,
56 hosts,
57 });
58 }
59 Err(crate::providers::ProviderError::PartialResult {
60 hosts,
61 failures,
62 total,
63 }) => {
64 warn!("[external] Provider sync partial: {name}, {} hosts, {} failures", hosts.len(), failures);
65 let _ = tx.send(AppEvent::SyncPartial {
66 provider: name,
67 hosts,
68 failures,
69 total,
70 });
71 }
72 Err(e) => {
73 error!("[external] Provider sync failed: {name}: {e}");
74 let _ = tx.send(AppEvent::SyncError {
75 provider: name,
76 message: e.to_string(),
77 });
78 }
79 }
80 })
81 {
82 error!(
83 "[purple] Failed to spawn sync thread for {}: {}",
84 name_fallback, e
85 );
86 let _ = tx_fallback.send(AppEvent::SyncError {
87 provider: name_fallback,
88 message: crate::messages::SYNC_THREAD_SPAWN_FAILED.to_string(),
89 });
90 }
91}