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