feat(daemon): per-surface status (set_state/state), idle-on-spawn, SPACESH_SOCK override
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use spacesh_proto::ids::{GroupId, SurfaceId, WorkspaceId};
|
||||
use spacesh_proto::status::SurfaceState;
|
||||
use spacesh_proto::workspace::{Group, SurfaceSpec, SurfaceView, Workspace, WorkspaceView};
|
||||
|
||||
use crate::state_store::PersistState;
|
||||
@@ -18,6 +19,8 @@ pub struct Registry {
|
||||
by_path: HashMap<String, WorkspaceId>,
|
||||
/// Live actors only. Absent id that exists in a workspace's `surfaces` = stopped.
|
||||
live: HashMap<SurfaceId, SurfaceHandle>,
|
||||
/// Ephemeral per-surface status. In-memory only (never persisted).
|
||||
states: HashMap<SurfaceId, SurfaceState>,
|
||||
}
|
||||
|
||||
impl Registry {
|
||||
@@ -111,6 +114,18 @@ impl Registry {
|
||||
self.live.contains_key(sid)
|
||||
}
|
||||
|
||||
// ---- surface state ----
|
||||
|
||||
pub fn set_state(&mut self, sid: &SurfaceId, state: SurfaceState) {
|
||||
self.states.insert(sid.clone(), state);
|
||||
}
|
||||
pub fn state(&self, sid: &SurfaceId) -> SurfaceState {
|
||||
self.states.get(sid).copied().unwrap_or_default()
|
||||
}
|
||||
pub fn drop_state(&mut self, sid: &SurfaceId) {
|
||||
self.states.remove(sid);
|
||||
}
|
||||
|
||||
// ---- groups ----
|
||||
|
||||
pub fn create_group(&mut self, name: String, color: String) -> GroupId {
|
||||
@@ -144,7 +159,11 @@ impl Registry {
|
||||
}
|
||||
fn to_view(&self, w: &Workspace) -> WorkspaceView {
|
||||
let surfaces = w.surfaces.iter().map(|(sid, spec)| {
|
||||
(sid.clone(), SurfaceView { spec: spec.clone(), running: self.live.contains_key(sid) })
|
||||
(sid.clone(), SurfaceView {
|
||||
spec: spec.clone(),
|
||||
running: self.live.contains_key(sid),
|
||||
state: self.state(sid),
|
||||
})
|
||||
}).collect();
|
||||
WorkspaceView {
|
||||
id: w.id.clone(), path: w.path.clone(), name: w.name.clone(),
|
||||
@@ -168,6 +187,7 @@ impl Registry {
|
||||
self.workspaces.clear();
|
||||
self.by_path.clear();
|
||||
self.live.clear();
|
||||
self.states.clear();
|
||||
for w in state.workspaces {
|
||||
self.by_path.insert(w.path.clone(), w.id.clone());
|
||||
self.workspaces.insert(w.id.clone(), w);
|
||||
@@ -243,4 +263,28 @@ mod tests {
|
||||
r.delete_group(&g);
|
||||
assert!(r.workspace(&ws).unwrap().group_id.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn state_defaults_idle_and_can_be_set() {
|
||||
let mut r = Registry::new();
|
||||
let (ws, _) = r.open_workspace(std::env::temp_dir());
|
||||
let sid = r.new_surface_id();
|
||||
r.add_surface_spec(&ws, sid.clone(), spec());
|
||||
assert_eq!(r.state(&sid), spacesh_proto::status::SurfaceState::Idle);
|
||||
r.set_state(&sid, spacesh_proto::status::SurfaceState::Work);
|
||||
assert_eq!(r.state(&sid), spacesh_proto::status::SurfaceState::Work);
|
||||
let v = r.workspace_view(&ws).unwrap();
|
||||
assert_eq!(v.surfaces.get(&sid).unwrap().state, spacesh_proto::status::SurfaceState::Work);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop_state_resets_to_idle() {
|
||||
let mut r = Registry::new();
|
||||
let (ws, _) = r.open_workspace(std::env::temp_dir());
|
||||
let sid = r.new_surface_id();
|
||||
r.add_surface_spec(&ws, sid.clone(), spec());
|
||||
r.set_state(&sid, spacesh_proto::status::SurfaceState::Error);
|
||||
r.drop_state(&sid);
|
||||
assert_eq!(r.state(&sid), spacesh_proto::status::SurfaceState::Idle);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user