11use super :: Executable ;
22use dora_core:: descriptor:: { Descriptor , DescriptorExt } ;
3+ use dora_message:: {
4+ cli_to_coordinator:: ControlRequest ,
5+ coordinator_to_cli:: { ControlRequestReply , NodeStatus } ,
6+ id:: NodeId ,
7+ } ;
38use eyre:: Context ;
49use std:: {
10+ collections:: HashMap ,
511 fs:: File ,
612 io:: Write ,
713 path:: { Path , PathBuf } ,
@@ -21,15 +27,33 @@ pub struct Graph {
2127 /// Open the HTML visualization in the browser
2228 #[ clap( long, action) ]
2329 open : bool ,
30+ /// Live mode with auto-refresh
31+ #[ clap( long, action) ]
32+ live : bool ,
33+ /// Output file path
34+ #[ clap( long, short = 'o' ) ]
35+ output : Option < PathBuf > ,
2436}
2537
2638impl Executable for Graph {
2739 fn execute ( self ) -> eyre:: Result < ( ) > {
28- create ( self . dataflow , self . mermaid , self . open )
40+ create (
41+ self . dataflow ,
42+ self . mermaid ,
43+ self . open ,
44+ self . output ,
45+ self . live ,
46+ )
2947 }
3048}
3149
32- fn create ( dataflow : std:: path:: PathBuf , mermaid : bool , open : bool ) -> eyre:: Result < ( ) > {
50+ fn create (
51+ dataflow : std:: path:: PathBuf ,
52+ mermaid : bool ,
53+ open : bool ,
54+ output : Option < PathBuf > ,
55+ live : bool ,
56+ ) -> eyre:: Result < ( ) > {
3357 if mermaid {
3458 let visualized = visualize_as_mermaid ( & dataflow) ?;
3559 println ! ( "{visualized}" ) ;
@@ -38,27 +62,35 @@ fn create(dataflow: std::path::PathBuf, mermaid: bool, open: bool) -> eyre::Resu
3862 ```mermaid code block on GitHub to display it."
3963 ) ;
4064 } else {
41- let html = visualize_as_html ( & dataflow) ?;
65+ let mut html = visualize_as_html ( & dataflow) ?;
66+ if live {
67+ html = html. replace (
68+ "<head>" ,
69+ "<head>\n <meta http-equiv=\" refresh\" content=\" 2\" >" ,
70+ ) ;
71+ }
4272
43- let working_dir = std:: env:: current_dir ( ) . wrap_err ( "failed to get current working dir" ) ?;
44- let graph_filename = match dataflow. file_stem ( ) . and_then ( |n| n. to_str ( ) ) {
45- Some ( name) => format ! ( "{name}-graph" ) ,
46- None => "graph" . into ( ) ,
47- } ;
48- let mut extra = 0 ;
49- let path = loop {
50- let adjusted_file_name = if extra == 0 {
51- format ! ( "{graph_filename}.html" )
52- } else {
53- format ! ( "{graph_filename}.{extra}.html" )
73+ let path = output. unwrap_or_else ( || {
74+ let working_dir = std:: env:: current_dir ( ) . unwrap ( ) ;
75+ let graph_filename = match dataflow. file_stem ( ) . and_then ( |n| n. to_str ( ) ) {
76+ Some ( name) => format ! ( "{name}-graph" ) ,
77+ None => "graph" . into ( ) ,
5478 } ;
55- let path = working_dir. join ( & adjusted_file_name) ;
56- if path. exists ( ) {
57- extra += 1 ;
58- } else {
59- break path;
79+ let mut extra = 0 ;
80+ loop {
81+ let adjusted_file_name = if extra == 0 {
82+ format ! ( "{graph_filename}.html" )
83+ } else {
84+ format ! ( "{graph_filename}.{extra}.html" )
85+ } ;
86+ let p = working_dir. join ( & adjusted_file_name) ;
87+ if p. exists ( ) {
88+ extra += 1 ;
89+ } else {
90+ break p;
91+ }
6092 }
61- } ;
93+ } ) ;
6294
6395 let mut file = File :: create ( & path) . context ( "failed to create graph HTML file" ) ?;
6496 file. write_all ( html. as_bytes ( ) ) ?;
0 commit comments