juc500 정상동작
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
use std::net::{SocketAddr, TcpStream};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Child, Command, Stdio};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub const GUI_PORT: u16 = 8765;
|
||||
|
||||
/// Project root containing `juc500_app.py` (parent of `juc500-app/` in dev).
|
||||
pub fn project_root() -> PathBuf {
|
||||
if let Ok(root) = std::env::var("JUC500_ROOT") {
|
||||
let p = PathBuf::from(root);
|
||||
if p.join("juc500_app.py").is_file() {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
if let Ok(cwd) = std::env::current_dir() {
|
||||
if cwd.join("juc500_app.py").is_file() {
|
||||
return cwd;
|
||||
}
|
||||
let parent = cwd.parent().map(Path::to_path_buf);
|
||||
if let Some(ref p) = parent {
|
||||
if p.join("juc500_app.py").is_file() {
|
||||
return p.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Ok(exe) = std::env::current_exe() {
|
||||
let mut dir = exe.parent().map(Path::to_path_buf);
|
||||
for _ in 0..10 {
|
||||
let Some(ref d) = dir else { break };
|
||||
if d.join("juc500_app.py").is_file() {
|
||||
return d.clone();
|
||||
}
|
||||
if d.join("..").join("juc500_app.py").exists() {
|
||||
if let Ok(canon) = d.join("..").canonicalize() {
|
||||
if canon.join("juc500_app.py").is_file() {
|
||||
return canon;
|
||||
}
|
||||
}
|
||||
}
|
||||
dir = d.parent().map(Path::to_path_buf);
|
||||
}
|
||||
}
|
||||
PathBuf::from(".")
|
||||
}
|
||||
|
||||
pub fn resolve_python(root: &Path) -> PathBuf {
|
||||
if cfg!(windows) {
|
||||
let venv = root.join(".venv").join("Scripts").join("python.exe");
|
||||
if venv.is_file() {
|
||||
return venv;
|
||||
}
|
||||
} else {
|
||||
let venv = root.join(".venv").join("bin").join("python");
|
||||
if venv.is_file() {
|
||||
return venv;
|
||||
}
|
||||
}
|
||||
if cfg!(windows) {
|
||||
PathBuf::from("python")
|
||||
} else {
|
||||
PathBuf::from("python3")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kill_wormhole(root: &Path) {
|
||||
let py = resolve_python(root);
|
||||
let _ = Command::new(&py)
|
||||
.current_dir(root)
|
||||
.env("PYTHONPATH", root)
|
||||
.args([
|
||||
"-c",
|
||||
"from juc500_xfer.wormhole_kill import kill_wormhole_processes; \
|
||||
kill_wormhole_processes(force=True)",
|
||||
])
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.status();
|
||||
}
|
||||
|
||||
pub fn backend_running(port: u16) -> bool {
|
||||
let addr: SocketAddr = format!("127.0.0.1:{}", port).parse().unwrap();
|
||||
TcpStream::connect_timeout(&addr, Duration::from_millis(200)).is_ok()
|
||||
}
|
||||
|
||||
pub fn wait_backend(port: u16, timeout: Duration) -> bool {
|
||||
let deadline = Instant::now() + timeout;
|
||||
while Instant::now() < deadline {
|
||||
if backend_running(port) {
|
||||
return true;
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis(200));
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn start_backend(root: &Path) -> std::io::Result<Child> {
|
||||
kill_wormhole(root);
|
||||
let py = resolve_python(root);
|
||||
let app = root.join("juc500_app.py");
|
||||
Command::new(&py)
|
||||
.current_dir(root)
|
||||
.env("PYTHONPATH", root)
|
||||
.env("JUC500_TAURI", "1")
|
||||
.arg(&app)
|
||||
.arg("--backend")
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
}
|
||||
|
||||
pub fn stop_backend(child: &mut Option<Child>) {
|
||||
if let Some(mut c) = child.take() {
|
||||
let _ = c.kill();
|
||||
let _ = c.wait();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user