holger_cli/
lib.rs

1
2pub async fn run() -> Result<()> {
3    env_logger::init();
4    let cli = Cli::parse();
5
6    match cli.command {
7        Commands::Start { config} => {
8            println!("Starting Holger {:?}",config);
9
10            let mut holger = holger_ron::read_ron_config(config)?;
11            let backend=holger.instantiate_backends();
12
13            let r=wire_holger(&mut holger);
14            print_wiring_summary(&holger);
15            let cfg = PrettyConfig::new()
16                .depth_limit(4)
17                .separate_tuple_members(true)
18                .enumerate_arrays(true);
19
20            println!("{}", to_string_pretty(&holger, cfg)?);
21
22
23            holger.start()?;
24
25            println!("Holger is running. Press Ctrl+C to stop.");
26
27            // ✅ Block until Ctrl+C
28            let (tx, rx) = std::sync::mpsc::channel();
29            ctrlc::set_handler(move || {
30                let _ = tx.send(());
31            })?;
32
33            // Wait for signal
34            rx.recv().expect("Failed to receive signal");
35
36            //            holger.stop()?;
37            println!("Holger stopped.");
38            //            Ok(())
39        }
40    }
41
42    Ok(())
43}
44
45
46// znippy-cli/src/main.rs
47use ron::ser::{to_string_pretty, PrettyConfig};
48
49use clap::{Parser, Subcommand};
50use std::path::PathBuf;
51use anyhow::Result;
52use holger_ron::{wire_holger, Holger};
53//use holger_core::config::factory;
54//use holger_core::load_config_from_path;
55
56#[derive(Parser)]
57#[command(name = "holger")]
58#[command(about = "Holger: Guards your artifacts at rest.", long_about = None)]
59struct Cli {
60    #[command(subcommand)]
61    command: Commands,
62}
63
64#[derive(Subcommand)]
65enum Commands {
66    /// Start Holger
67    Start {
68        #[arg(short, long)]
69        config: PathBuf,
70
71    },
72
73}
74
75
76
77pub fn print_wiring_summary(holger: &Holger) {
78    println!("--- Wiring Summary ---");
79
80    for (i, repo) in holger.repositories.iter().enumerate() {
81        let upstreams = repo.ron_upstreams.len();
82        let in_exists = repo.ron_in.is_some();
83        let out_exists = repo.ron_out.is_some();
84
85        println!(
86            "[Repo #{i}] {} | upstreams:{} in:{} out:{}",
87            repo.ron_name, upstreams, in_exists, out_exists
88        );
89    }
90
91    println!("--- Wiring Check ---");
92    let mut ok = true;
93    for repo in &holger.repositories {
94        if repo.ron_out.is_some() && holger.exposed_endpoints.is_empty() {
95            println!("!! Repo {} has `ron_out` but no exposed endpoints wired", repo.ron_name);
96            ok = false;
97        }
98        if repo.ron_out.is_some() && holger.storage_endpoints.is_empty() {
99            println!("!! Repo {} has `ron_out` but no storage endpoints wired", repo.ron_name);
100            ok = false;
101        }
102    }
103
104    if ok {
105        println!("Wiring looks OK.");
106    } else {
107        println!("Wiring has issues.");
108    }
109
110
111    println!("--- Reverse Wiring ---");
112
113    for (i, ep) in holger.exposed_endpoints.iter().enumerate() {
114        println!(
115            "[Exposed #{i}] {} | in:{} out:{}",
116            ep.ron_name,
117            ep.wired_in_repositories.len(),
118            ep.wired_out_repositories.len()
119        );
120    }
121
122    for (i, st) in holger.storage_endpoints.iter().enumerate() {
123        println!(
124            "[Storage #{i}] {} | in:{} out:{}",
125            st.ron_name,
126            st.wired_in_repositories.len(),
127            st.wired_out_repositories.len()
128        );
129    }
130    println!("--- Aggregated Routes Debug ---");
131
132    for (i, ep) in holger.exposed_endpoints.iter().enumerate() {
133        println!(
134            "[Exposed #{i}] {} | aggregated_routes: {}",
135            ep.ron_name,
136            if ep.aggregated_routes.is_some() { "yes" } else { "no" }
137        );
138
139        if !ep.wired_out_repositories.is_empty() {
140            for &repo_ptr in &ep.wired_out_repositories {
141                if repo_ptr.is_null() {
142                    println!("    -> null pointer (skipped)");
143                    continue;
144                }
145                let repo = unsafe { &*repo_ptr };
146                println!(
147                    "    -> wired repo: {} | backend: {}",
148                    repo.ron_name,
149                    if repo.backend_repository.is_some() { "ready" } else { "none" }
150                );
151            }
152        } else {
153            println!("    -> no wired out repositories");
154        }
155    }
156
157    println!("--- Aggregated Routes Deep Check ---");
158
159    for (i, ep) in holger.exposed_endpoints.iter().enumerate() {
160        let mut possible_routes = 0;
161        let mut ready_routes = 0;
162
163        println!(
164            "[Exposed #{i}] {} | aggregated_routes: {}",
165            ep.ron_name,
166            if ep.aggregated_routes.is_some() { "yes" } else { "no" }
167        );
168
169        if ep.wired_out_repositories.is_empty() {
170            println!("    -> no wired out repositories");
171        } else {
172            for &repo_ptr in &ep.wired_out_repositories {
173                if repo_ptr.is_null() {
174                    println!("    -> null pointer (skipped)");
175                    continue;
176                }
177                let repo = unsafe { &*repo_ptr };
178                possible_routes += 1;
179
180                let expected = &ep.ron_name;
181                let actual = if let Some(io) = &repo.ron_out {
182                    &io.ron_exposed_endpoint
183                } else {
184                    "<none>"
185                };
186
187                let backend_ready = repo.backend_repository.is_some();
188                if backend_ready {
189                    ready_routes += 1;
190                }
191
192                println!(
193                    "    -> wired repo: {} | backend:{} | expected:{} vs actual:{}",
194                    repo.ron_name,
195                    if backend_ready { "ready" } else { "none" },
196                    expected,
197                    actual
198                );
199            }
200        }
201
202        println!(
203            "    -> route candidates: {} | ready for FastRoutes: {}",
204            possible_routes, ready_routes
205        );
206    }
207}