orchflow_mux/
factory.rs

1use crate::backend::MuxBackend;
2use crate::muxd_backend::MuxdBackend as MuxdBackendImpl;
3use crate::tmux_backend::TmuxBackend;
4use log::{error, info, warn};
5use std::env;
6
7/// Create a mux backend based on environment configuration (async version)
8pub async fn create_mux_backend_async() -> Box<dyn MuxBackend> {
9    let backend_type = env::var("ORCH_MUX_BACKEND").unwrap_or_else(|_| {
10        info!("ORCH_MUX_BACKEND not set, defaulting to tmux");
11        "tmux".to_string()
12    });
13
14    info!("Creating mux backend with type: {backend_type}");
15
16    match backend_type.as_str() {
17        "muxd" => {
18            let url = env::var("MUXD_URL").unwrap_or_else(|_| {
19                info!("MUXD_URL not set, using default ws://localhost:7890/ws");
20                "ws://localhost:7890/ws".to_string()
21            });
22
23            let backend = MuxdBackendImpl::new(url);
24            info!("Successfully created MuxdBackend");
25            Box::new(backend)
26        }
27        "mock" => {
28            #[cfg(test)]
29            {
30                info!("Using MockBackend for testing");
31                Box::new(crate::mock_backend::MockBackend::new())
32            }
33            #[cfg(not(test))]
34            {
35                warn!("Mock backend only available in test builds, using tmux");
36                Box::new(TmuxBackend::new())
37            }
38        }
39        "tmux" => {
40            info!("Using TmuxBackend");
41            Box::new(TmuxBackend::new())
42        }
43        other => {
44            warn!("Unknown backend type '{other}', falling back to tmux");
45            Box::new(TmuxBackend::new())
46        }
47    }
48}
49
50/// Create a mux backend based on environment configuration (sync version)
51pub fn create_mux_backend() -> Box<dyn MuxBackend> {
52    let backend_type = env::var("ORCH_MUX_BACKEND").unwrap_or_else(|_| {
53        info!("ORCH_MUX_BACKEND not set, defaulting to tmux");
54        "tmux".to_string()
55    });
56
57    info!("Creating mux backend with type: {backend_type}");
58
59    match backend_type.as_str() {
60        "muxd" => {
61            let url = env::var("MUXD_URL").unwrap_or_else(|_| {
62                info!("MUXD_URL not set, using default ws://localhost:7890/ws");
63                "ws://localhost:7890/ws".to_string()
64            });
65
66            // Try to use existing runtime or create a new one
67            match tokio::runtime::Handle::try_current() {
68                Ok(_handle) => {
69                    // We're already in a runtime, use it
70                    let backend = MuxdBackendImpl::new(url);
71                    info!("Successfully created MuxdBackend");
72                    Box::new(backend)
73                }
74                Err(_) => {
75                    // No runtime exists, create a new one
76                    match tokio::runtime::Runtime::new() {
77                        Ok(_rt) => {
78                            let backend = MuxdBackendImpl::new(url);
79                            info!("Successfully created MuxdBackend");
80                            Box::new(backend)
81                        }
82                        Err(e) => {
83                            error!("Failed to create tokio runtime: {e}, falling back to tmux");
84                            Box::new(TmuxBackend::new())
85                        }
86                    }
87                }
88            }
89        }
90        "mock" => {
91            #[cfg(test)]
92            {
93                info!("Using MockBackend for testing");
94                Box::new(crate::mock_backend::MockBackend::new())
95            }
96            #[cfg(not(test))]
97            {
98                warn!("Mock backend only available in test builds, using tmux");
99                Box::new(TmuxBackend::new())
100            }
101        }
102        "tmux" => {
103            info!("Using TmuxBackend");
104            Box::new(TmuxBackend::new())
105        }
106        other => {
107            warn!("Unknown backend type '{other}', falling back to tmux");
108            Box::new(TmuxBackend::new())
109        }
110    }
111}
112
113#[cfg(test)]
114mod tests {
115    use crate::factory::create_mux_backend;
116    use std::env;
117
118    #[test]
119    fn test_default_backend_is_tmux() {
120        // Clear env var
121        env::remove_var("ORCH_MUX_BACKEND");
122
123        let _backend = create_mux_backend();
124        // We can't directly test the type, but we can verify it doesn't panic
125        // Test passes by reaching this point
126    }
127
128    #[test]
129    fn test_env_var_tmux() {
130        env::set_var("ORCH_MUX_BACKEND", "tmux");
131        let _backend = create_mux_backend();
132        // Test passes by reaching this point
133        env::remove_var("ORCH_MUX_BACKEND");
134    }
135
136    #[test]
137    fn test_env_var_muxd_falls_back() {
138        env::set_var("ORCH_MUX_BACKEND", "muxd");
139        let _backend = create_mux_backend();
140        // Should print warning and create tmux backend
141        // Test passes by reaching this point
142        env::remove_var("ORCH_MUX_BACKEND");
143    }
144
145    #[test]
146    fn test_env_var_mock() {
147        env::set_var("ORCH_MUX_BACKEND", "mock");
148        let _backend = create_mux_backend();
149        // In test mode, should create mock backend
150        // Test passes by reaching this point
151        env::remove_var("ORCH_MUX_BACKEND");
152    }
153}