Skip to main content

hx_remote/
registry.rs

1use serde::{Deserialize, Serialize};
2use std::env;
3use std::fs;
4use std::path::PathBuf;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct InstanceInfo {
8    pub pid: u32,
9    pub socket_path: PathBuf,
10    pub name: Option<String>,
11}
12
13pub fn instances_dir() -> PathBuf {
14    let cache_root = env::var_os("XDG_CACHE_HOME")
15        .filter(|value| !value.is_empty())
16        .map(PathBuf::from)
17        .or_else(|| {
18            env::var_os("HOME")
19                .filter(|value| !value.is_empty())
20                .map(|home| PathBuf::from(home).join(".cache"))
21        })
22        .unwrap_or_else(env::temp_dir);
23    cache_root.join("hx-remote").join("instances")
24}
25
26pub fn register_instance(info: &InstanceInfo) -> std::io::Result<()> {
27    let dir = instances_dir();
28    fs::create_dir_all(&dir)?;
29    let path = dir.join(format!("{}.json", info.pid));
30    let json = serde_json::to_string(info)?;
31    fs::write(path, json)
32}
33
34pub fn unregister_instance(pid: u32) {
35    let _ = fs::remove_file(instances_dir().join(format!("{}.json", pid)));
36}
37
38pub fn get_active_instances() -> Vec<InstanceInfo> {
39    let dir = instances_dir();
40    let Ok(entries) = fs::read_dir(dir) else {
41        return vec![];
42    };
43
44    let mut instances = Vec::new();
45    for entry in entries.flatten() {
46        let path = entry.path();
47        if path.extension().is_some_and(|ext| ext == "json")
48            && let Ok(contents) = fs::read_to_string(&path)
49        {
50            if let Ok(info) = serde_json::from_str::<InstanceInfo>(&contents) {
51                // Check if socket is actually listening
52                if crate::client::socket_is_listening(&info.socket_path).unwrap_or(false) {
53                    instances.push(info);
54                } else {
55                    let _ = fs::remove_file(&path);
56                }
57            } else {
58                let _ = fs::remove_file(&path);
59            }
60        }
61    }
62
63    // Sort by pid so that index is stable
64    instances.sort_by_key(|info| info.pid);
65    instances
66}