mirror of
https://github.com/hexedtech/codemp.git
synced 2025-04-03 18:11:41 +02:00
105 lines
2.4 KiB
Rust
105 lines
2.4 KiB
Rust
|
|
use std::{collections::HashMap, sync::Arc, fmt::Display};
|
|
use tokio::sync::{mpsc, watch};
|
|
use tracing::error;
|
|
|
|
use crate::actor::workspace::Workspace;
|
|
|
|
|
|
#[derive(Debug)]
|
|
enum WorkspaceAction {
|
|
ADD {
|
|
key: String,
|
|
w: Box<Workspace>,
|
|
},
|
|
REMOVE {
|
|
key: String
|
|
},
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct WorkspacesView {
|
|
watch: watch::Receiver<HashMap<String, Arc<Workspace>>>,
|
|
op: mpsc::Sender<WorkspaceAction>,
|
|
}
|
|
|
|
impl WorkspacesView {
|
|
pub fn borrow(&self) -> watch::Ref<HashMap<String, Arc<Workspace>>> {
|
|
self.watch.borrow()
|
|
}
|
|
|
|
pub async fn add(&mut self, w: Workspace) {
|
|
self.op.send(WorkspaceAction::ADD { key: w.id.to_string(), w: Box::new(w) }).await.unwrap();
|
|
}
|
|
|
|
pub async fn remove(&mut self, key: String) {
|
|
self.op.send(WorkspaceAction::REMOVE { key }).await.unwrap();
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct StateManager {
|
|
pub workspaces: WorkspacesView,
|
|
pub run: watch::Receiver<bool>,
|
|
run_tx: watch::Sender<bool>,
|
|
}
|
|
|
|
impl Drop for StateManager {
|
|
fn drop(&mut self) {
|
|
self.run_tx.send(false).unwrap_or_else(|e| {
|
|
error!("Could not stop StateManager worker: {:?}", e);
|
|
})
|
|
}
|
|
}
|
|
|
|
impl StateManager {
|
|
pub fn new() -> Self {
|
|
let (tx, rx) = mpsc::channel(32); // TODO quantify backpressure
|
|
let (workspaces_tx, workspaces_rx) = watch::channel(HashMap::new());
|
|
let (run_tx, run_rx) = watch::channel(true);
|
|
|
|
let s = StateManager {
|
|
workspaces: WorkspacesView { watch: workspaces_rx, op: tx },
|
|
run_tx, run: run_rx,
|
|
};
|
|
|
|
s.workspaces_worker(rx, workspaces_tx);
|
|
|
|
return s;
|
|
}
|
|
|
|
fn workspaces_worker(&self, mut rx: mpsc::Receiver<WorkspaceAction>, tx: watch::Sender<HashMap<String, Arc<Workspace>>>) {
|
|
let run = self.run.clone();
|
|
tokio::spawn(async move {
|
|
let mut store = HashMap::new();
|
|
|
|
while run.borrow().to_owned() {
|
|
if let Some(event) = rx.recv().await {
|
|
match event {
|
|
WorkspaceAction::ADD { key, w } => {
|
|
store.insert(key, Arc::new(*w)); // TODO put in hashmap
|
|
},
|
|
WorkspaceAction::REMOVE { key } => {
|
|
store.remove(&key);
|
|
},
|
|
}
|
|
tx.send(store.clone()).unwrap();
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
pub fn view(&self) -> WorkspacesView {
|
|
return self.workspaces.clone();
|
|
}
|
|
|
|
/// get a workspace Arc directly, without passing by the WorkspacesView
|
|
pub fn get(&self, key: &String) -> Option<Arc<Workspace>> {
|
|
if let Some(w) = self.workspaces.borrow().get(key) {
|
|
return Some(w.clone());
|
|
}
|
|
return None;
|
|
}
|
|
}
|