1use std::collections::HashMap;
7use std::hash::{Hash, Hasher};
8use std::path::{Path, PathBuf};
9use std::sync::Arc;
10use std::sync::atomic::{AtomicBool, Ordering};
11use std::time::{Duration, Instant};
12
13use tokio::sync::{RwLock, broadcast};
14use venus_core::widgets::{WidgetDef, WidgetValue};
15use venus_core::compile::{
16 CellCompiler, CompilationResult, CompilerConfig, ToolchainManager, UniverseBuilder,
17};
18use venus_core::execute::{ExecutorKillHandle, ProcessExecutor};
19use venus_core::graph::{CellId, CellInfo, CellParser, CellType, DefinitionCell, GraphEngine, MarkdownCell, MoveDirection, SourceEditor};
20use venus_core::paths::NotebookDirs;
21
22use crate::error::{ServerError, ServerResult};
23use crate::protocol::{CellOutput, CellState, CellStatus, ServerMessage};
24use crate::undo::{UndoManager, UndoableOperation};
25use venus_core::state::BoxedOutput;
26
27fn find_workspace_root(notebook_path: &Path) -> (Option<PathBuf>, Option<PathBuf>) {
30 let mut current = notebook_path.parent();
31
32 while let Some(dir) = current {
33 let cargo_toml = dir.join("Cargo.toml");
34 if cargo_toml.exists() {
35 return (Some(dir.to_path_buf()), Some(cargo_toml));
36 }
37 current = dir.parent();
38 }
39
40 (None, None)
41}
42
43pub type InterruptFlag = Arc<AtomicBool>;
45
46const MESSAGE_CHANNEL_CAPACITY: usize = 256;
50
51pub struct NotebookSession {
53 path: PathBuf,
55
56 workspace_cargo_toml: Option<PathBuf>,
58
59 cells: Vec<CellInfo>,
61
62 markdown_cells: Vec<MarkdownCell>,
64
65 definition_cells: Vec<DefinitionCell>,
67
68 graph: GraphEngine,
70
71 cell_states: HashMap<CellId, CellState>,
73
74 toolchain: ToolchainManager,
76
77 config: CompilerConfig,
79
80 universe_path: Option<PathBuf>,
82
83 deps_hash: u64,
85
86 tx: broadcast::Sender<ServerMessage>,
88
89 executing: bool,
91
92 cell_outputs: HashMap<CellId, Arc<BoxedOutput>>,
95
96 executor: ProcessExecutor,
99
100 execution_timeout: Option<Duration>,
103
104 interrupted: InterruptFlag,
108
109 widget_values: HashMap<CellId, HashMap<String, WidgetValue>>,
112
113 widget_defs: HashMap<CellId, Vec<WidgetDef>>,
116
117 cell_output_history: HashMap<CellId, Vec<OutputHistoryEntry>>,
120
121 cell_history_index: HashMap<CellId, usize>,
123
124 undo_manager: UndoManager,
126
127 pending_edits: HashMap<CellId, String>,
130}
131
132const MAX_HISTORY_PER_CELL: usize = 10;
134
135#[derive(Clone)]
137pub struct OutputHistoryEntry {
138 pub serialized: Arc<BoxedOutput>,
140 pub display: CellOutput,
142 pub timestamp: u64,
144}
145
146pub type SessionHandle = Arc<RwLock<NotebookSession>>;
148
149impl NotebookSession {
150 pub fn new(
158 path: impl AsRef<Path>,
159 interrupted: InterruptFlag,
160 ) -> ServerResult<(Self, broadcast::Receiver<ServerMessage>)> {
161 let path = path.as_ref().canonicalize().map_err(|e| ServerError::Io {
162 path: path.as_ref().to_path_buf(),
163 message: e.to_string(),
164 })?;
165
166 let (_workspace_root, workspace_cargo_toml) = find_workspace_root(&path);
168
169 let dirs = NotebookDirs::from_notebook_path(&path)?;
171
172 let toolchain = ToolchainManager::new()?;
173 let config = CompilerConfig::for_notebook(&dirs);
174
175 let (tx, rx) = broadcast::channel(MESSAGE_CHANNEL_CAPACITY);
176
177 let executor = ProcessExecutor::new(&dirs.state_dir)?;
179
180 let mut session = Self {
181 path,
182 workspace_cargo_toml,
183 cells: Vec::new(),
184 markdown_cells: Vec::new(),
185 definition_cells: Vec::new(),
186 graph: GraphEngine::new(),
187 cell_states: HashMap::new(),
188 toolchain,
189 config,
190 universe_path: None,
191 deps_hash: 0,
192 tx,
193 executing: false,
194 cell_outputs: HashMap::new(),
195 executor,
196 execution_timeout: None,
197 interrupted,
198 widget_values: HashMap::new(),
199 widget_defs: HashMap::new(),
200 cell_output_history: HashMap::new(),
201 cell_history_index: HashMap::new(),
202 undo_manager: UndoManager::new(),
203 pending_edits: HashMap::new(),
204 };
205
206 session.reload()?;
207
208 Ok((session, rx))
209 }
210
211 pub fn path(&self) -> &Path {
213 &self.path
214 }
215
216 pub fn subscribe(&self) -> broadcast::Receiver<ServerMessage> {
218 self.tx.subscribe()
219 }
220
221 fn get_cell(&self, cell_id: CellId) -> Option<&CellInfo> {
223 self.cells.iter().find(|c| c.id == cell_id)
224 }
225
226 fn set_cell_status(&mut self, cell_id: CellId, status: CellStatus) {
228 if let Some(CellState::Code { status: cell_status, .. }) = self.cell_states.get_mut(&cell_id) {
229 *cell_status = status;
230 }
231 }
232
233 pub fn broadcast(&self, msg: ServerMessage) {
235 let _ = self.tx.send(msg);
236 }
237
238 pub fn reload(&mut self) -> ServerResult<()> {
240 let source = std::fs::read_to_string(&self.path)?;
241
242 let mut parser = CellParser::new();
244 let parse_result = parser.parse_file(&self.path)?;
245 self.cells = parse_result.code_cells;
246 self.markdown_cells = parse_result.markdown_cells;
247 self.definition_cells = parse_result.definition_cells;
248
249 self.graph = GraphEngine::new();
251 for cell in &mut self.cells {
252 let real_id = self.graph.add_cell(cell.clone());
253 cell.id = real_id;
254 }
255 self.graph.resolve_dependencies()?;
256
257 let mut next_id = if let Some(max_code_id) = self.cells.iter().map(|c| c.id.as_usize()).max() {
259 max_code_id + 1
260 } else {
261 0
262 };
263 for md_cell in &mut self.markdown_cells {
264 md_cell.id = CellId::new(next_id);
265 next_id += 1;
266 }
267
268 for def_cell in &mut self.definition_cells {
270 def_cell.id = CellId::new(next_id);
271 next_id += 1;
272 }
273
274 if let Err(e) = self.write_virtual_notebook_file() {
277 tracing::warn!("Failed to write virtual notebook file: {}", e);
278 }
279
280 let mut universe_builder =
282 UniverseBuilder::new(self.config.clone(), self.toolchain.clone(), self.workspace_cargo_toml.clone());
283 universe_builder.parse_dependencies(&source, &self.definition_cells)?;
284
285 self.universe_path = Some(universe_builder.build()?);
286 self.deps_hash = universe_builder.deps_hash();
287
288 self.update_cell_states();
290
291 Ok(())
297 }
298
299 fn strip_display_name_from_description(doc_comment: &Option<String>) -> Option<String> {
304 doc_comment.as_ref().and_then(|doc| {
305 let lines: Vec<&str> = doc.lines().collect();
306
307 if let Some(first_line) = lines.first() {
309 let trimmed = first_line.trim();
310 if trimmed.starts_with('#') {
311 let remaining: Vec<&str> = lines.iter().skip(1).copied()
313 .collect();
314
315 let trimmed_lines: Vec<&str> = remaining.iter()
317 .skip_while(|line| line.trim().is_empty()).copied()
318 .collect();
319
320 if trimmed_lines.is_empty() {
321 return None;
322 }
323
324 return Some(trimmed_lines.join("\n"));
325 }
326 }
327
328 Some(doc.clone())
330 })
331 }
332
333 fn update_cell_states(&mut self) {
335 let mut new_states = HashMap::new();
336
337 for cell in &self.cells {
339 let existing = self.cell_states.get(&cell.id);
340
341 let (status, output, dirty) = if let Some(CellState::Code { status, output, dirty, .. }) = existing {
343 (*status, output.clone(), *dirty)
344 } else {
345 (CellStatus::default(), None, false)
347 };
348
349 let state = CellState::Code {
350 id: cell.id,
351 name: cell.name.clone(),
352 display_name: cell.display_name.clone(),
353 source: cell.source_code.clone(),
354 description: Self::strip_display_name_from_description(&cell.doc_comment),
355 return_type: cell.return_type.clone(),
356 dependencies: cell
357 .dependencies
358 .iter()
359 .map(|d| d.param_name.clone())
360 .collect(),
361 status,
362 output,
363 dirty,
364 };
365 new_states.insert(cell.id, state);
366 }
367
368 for md_cell in &self.markdown_cells {
370 let state = CellState::Markdown {
371 id: md_cell.id,
372 content: md_cell.content.clone(),
373 };
374 new_states.insert(md_cell.id, state);
375 }
376
377 for def_cell in &self.definition_cells {
379 let state = CellState::Definition {
380 id: def_cell.id,
381 content: def_cell.content.clone(),
382 definition_type: def_cell.definition_type,
383 doc_comment: def_cell.doc_comment.clone(),
384 };
385 new_states.insert(def_cell.id, state);
386 }
387
388 self.cell_states = new_states;
389 }
390
391 fn collect_cells_in_source_order(&self) -> Vec<(CellId, usize, CellType)> {
397 let mut all_cells: Vec<(CellId, usize, CellType)> = Vec::new();
398
399 for cell in &self.cells {
400 all_cells.push((cell.id, cell.span.start_line, CellType::Code));
401 }
402
403 for md_cell in &self.markdown_cells {
404 all_cells.push((md_cell.id, md_cell.span.start_line, CellType::Markdown));
405 }
406
407 for def_cell in &self.definition_cells {
408 all_cells.push((def_cell.id, def_cell.span.start_line, CellType::Definition));
409 }
410
411 all_cells.sort_by_key(|(_, line, _)| *line);
412 all_cells
413 }
414
415 fn write_virtual_notebook_file(&self) -> std::io::Result<()> {
416 use std::fs;
417
418 let dirs = NotebookDirs::from_notebook_path(&self.path)
419 .map_err(|e| std::io::Error::other(e.to_string()))?;
420 let universe_src = dirs.build_dir.join("universe").join("src");
421 fs::create_dir_all(&universe_src)?;
422
423 let mut lines = Vec::new();
424 let all_cells = self.collect_cells_in_source_order();
425
426 for (cell_id, _, cell_type) in all_cells {
428 match cell_type {
429 CellType::Code => {
430 if let Some(cell) = self.cells.iter().find(|c| c.id == cell_id) {
431 lines.push(cell.source_code.clone());
432 lines.push(String::new()); }
434 }
435 CellType::Definition => {
436 if let Some(def_cell) = self.definition_cells.iter().find(|c| c.id == cell_id) {
437 lines.push(def_cell.content.clone());
438 lines.push(String::new()); }
440 }
441 _ => {} }
443 }
444
445 let content = lines.join("\n");
446 fs::write(universe_src.join("notebook.rs"), content)?;
447
448 Ok(())
449 }
450
451 pub fn get_state(&self) -> ServerMessage {
455 let all_cells = self.collect_cells_in_source_order();
457 let source_order: Vec<CellId> = all_cells.into_iter().map(|(id, _, _)| id).collect();
458
459 let execution_order = match self.graph.topological_order() {
461 Ok(order) => order,
462 Err(e) => {
463 tracing::error!("Failed to compute execution order: {}", e);
464 Vec::new()
465 }
466 };
467
468 let (workspace_root, cargo_toml_path) = find_workspace_root(&self.path);
470
471 ServerMessage::NotebookState {
472 path: self.path.display().to_string(),
473 cells: self.cell_states.values().cloned().collect(),
474 source_order,
475 execution_order,
476 workspace_root: workspace_root.map(|p| p.display().to_string()),
477 cargo_toml_path: cargo_toml_path.map(|p| p.display().to_string()),
478 }
479 }
480
481 pub fn store_pending_edit(&mut self, cell_id: CellId, source: String) {
485 self.pending_edits.insert(cell_id, source);
486 }
487
488 pub async fn execute_cell(&mut self, cell_id: CellId) -> ServerResult<()> {
493 let cell_name = self
495 .get_cell(cell_id)
496 .map(|c| c.name.clone())
497 .ok_or(ServerError::CellNotFound(cell_id))?;
498
499 if let Some(new_source) = self.pending_edits.remove(&cell_id) {
501 self.edit_cell(cell_id, new_source)?;
502 }
503 if self.executing {
504 return Err(ServerError::ExecutionInProgress);
505 }
506
507 let cell = self
509 .cells
510 .iter()
511 .find(|c| c.name == cell_name)
512 .ok_or(ServerError::CellNotFound(cell_id))?
513 .clone();
514
515 let cell_id = cell.id; self.executing = true;
518
519 self.interrupted.store(false, Ordering::SeqCst);
521
522 let missing_deps: Vec<&str> = cell
524 .dependencies
525 .iter()
526 .filter(|dep| {
527 let producer = self.cells.iter().find(|c| c.name == dep.param_name);
528 match producer {
529 Some(c) => !self.cell_outputs.contains_key(&c.id),
530 None => true,
531 }
532 })
533 .map(|d| d.param_name.as_str())
534 .collect();
535
536 if !missing_deps.is_empty() {
537 self.set_cell_status(cell_id, CellStatus::Error);
538 self.broadcast(ServerMessage::CellError {
539 cell_id,
540 error: format!(
541 "Missing dependencies: {}. Run dependent cells first.",
542 missing_deps.join(", ")
543 ),
544 location: None,
545 });
546 self.executing = false;
547 return Ok(());
548 }
549
550 self.set_cell_status(cell_id, CellStatus::Compiling);
552
553 let mut compiler = CellCompiler::new(self.config.clone(), self.toolchain.clone());
554 if let Some(ref up) = self.universe_path {
555 compiler = compiler.with_universe(up.clone());
556 }
557
558 let result = compiler.compile(&cell, self.deps_hash);
559
560 match result {
561 CompilationResult::Success(compiled) | CompilationResult::Cached(compiled) => {
562 self.set_cell_status(cell_id, CellStatus::Running);
564 self.broadcast(ServerMessage::CellStarted { cell_id });
565
566 let start = Instant::now();
567
568 self.executor.register_cell(compiled, cell.dependencies.len());
570
571 let inputs: Vec<Arc<BoxedOutput>> = cell
573 .dependencies
574 .iter()
575 .filter_map(|dep| {
576 self.cells
577 .iter()
578 .find(|c| c.name == dep.param_name)
579 .and_then(|c| self.cell_outputs.get(&c.id).cloned())
580 })
581 .collect();
582
583 let widget_values = self.get_all_widget_values();
585 let widget_values_json = if widget_values.is_empty() {
586 Vec::new()
587 } else {
588 serde_json::to_vec(&widget_values).unwrap_or_default()
589 };
590
591 let exec_result = self.executor.execute_cell_with_widgets(
593 cell_id,
594 &inputs,
595 widget_values_json,
596 );
597
598 let duration = start.elapsed();
599
600 match exec_result {
601 Ok((output, widgets_json)) => {
602 let old_hash = self.cell_outputs.get(&cell_id)
604 .map(|old| Self::output_hash(old));
605 let new_hash = Self::output_hash(&output);
606 let output_changed = old_hash.is_none_or(|h| h != new_hash);
607
608 let output_arc = Arc::new(output);
610 self.cell_outputs.insert(cell_id, output_arc.clone());
611
612 self.executor.state_mut().store_output(cell_id, (*output_arc).clone());
614
615 let widgets: Vec<WidgetDef> = if widgets_json.is_empty() {
617 Vec::new()
618 } else {
619 serde_json::from_slice(&widgets_json).unwrap_or_default()
620 };
621 self.store_widget_defs(cell_id, widgets.clone());
622
623 let cell_output = CellOutput {
624 text: output_arc.display_text().map(|s| s.to_string()),
625 html: None,
626 image: None,
627 json: None,
628 widgets,
629 };
630
631 self.add_to_history(cell_id, output_arc.clone(), cell_output.clone());
633
634 if let Some(state) = self.cell_states.get_mut(&cell_id) {
635 state.set_status(CellStatus::Success);
636 state.set_output(Some(cell_output.clone()));
637 state.set_dirty(false);
638 }
639
640 if output_changed {
642 let dirty_cells = self.mark_dependents_dirty_and_get(cell_id);
643 for dirty_id in dirty_cells {
644 self.broadcast(ServerMessage::CellDirty { cell_id: dirty_id });
645 }
646 }
647
648 self.broadcast(ServerMessage::CellCompleted {
649 cell_id,
650 duration_ms: duration.as_millis() as u64,
651 output: Some(cell_output),
652 });
653 }
654 Err(e) => {
655 let was_interrupted = self.interrupted.swap(false, Ordering::SeqCst);
657 if matches!(e, venus_core::Error::Aborted) || was_interrupted {
658 self.set_cell_status(cell_id, CellStatus::Idle);
660 self.broadcast(ServerMessage::ExecutionAborted { cell_id: Some(cell_id) });
661 } else {
662 self.set_cell_status(cell_id, CellStatus::Error);
663 self.broadcast(ServerMessage::CellError {
664 cell_id,
665 error: e.to_string(),
666 location: None,
667 });
668 }
669 }
670 }
671 }
672 CompilationResult::Failed { errors, .. } => {
673 self.set_cell_status(cell_id, CellStatus::Error);
674
675 let compile_errors = errors
676 .iter()
677 .map(|e| crate::protocol::CompileErrorInfo {
678 message: e.message.clone(),
679 code: e.code.clone(),
680 location: e.spans.first().map(|s| crate::protocol::SourceLocation {
681 line: s.location.line as u32,
682 column: s.location.column as u32,
683 end_line: s.end_location.as_ref().map(|l| l.line as u32),
684 end_column: s.end_location.as_ref().map(|l| l.column as u32),
685 }),
686 rendered: e.rendered.clone(),
687 })
688 .collect();
689
690 self.broadcast(ServerMessage::CompileError {
691 cell_id,
692 errors: compile_errors,
693 });
694 }
695 }
696
697 self.executing = false;
698 Ok(())
699 }
700
701 pub async fn execute_all(&mut self) -> ServerResult<()> {
706 let order = self.graph.topological_order()?;
707 let start = Instant::now();
708 let timeout = self.execution_timeout;
709
710 for cell_id in order {
711 if timeout.is_some_and(|max_duration| start.elapsed() > max_duration) {
713 self.executor.abort();
714 self.broadcast(ServerMessage::ExecutionAborted { cell_id: Some(cell_id) });
715 return Err(ServerError::ExecutionTimeout);
716 }
717
718 self.execute_cell(cell_id).await?;
719 }
720 Ok(())
721 }
722
723 pub fn mark_dirty(&mut self, cell_id: CellId) {
728 if self.cell_outputs.contains_key(&cell_id) {
730 if let Some(state) = self.cell_states.get_mut(&cell_id) {
731 state.set_dirty(true);
732 }
733 }
734
735 let dependents = self.graph.invalidated_cells(cell_id);
737 for dep_id in dependents {
738 if self.cell_outputs.contains_key(&dep_id) {
739 if let Some(state) = self.cell_states.get_mut(&dep_id) {
740 state.set_dirty(true);
741 }
742 }
743 }
744 }
745
746 pub fn is_executing(&self) -> bool {
748 self.executing
749 }
750
751 pub fn abort(&mut self) -> bool {
757 if self.executing {
758 self.executor.abort();
760 self.broadcast(ServerMessage::ExecutionAborted { cell_id: None });
761 self.executing = false;
762 true
763 } else {
764 false
765 }
766 }
767
768 pub fn set_execution_timeout(&mut self, timeout: Option<Duration>) {
773 self.execution_timeout = timeout;
774 }
775
776 pub fn execution_timeout(&self) -> Option<Duration> {
778 self.execution_timeout
779 }
780
781 pub fn set_interrupted(&mut self, value: bool) {
786 self.interrupted.store(value, Ordering::SeqCst);
787 }
788
789 pub fn get_kill_handle(&self) -> Option<ExecutorKillHandle> {
794 self.executor.get_kill_handle()
795 }
796
797 pub fn restart_kernel(&mut self) -> ServerResult<()> {
807 if self.executing {
809 self.abort();
810 }
811
812 self.reload()?;
814
815 self.executor.shutdown();
817
818 let dirs = NotebookDirs::from_notebook_path(&self.path)?;
820
821 self.executor = ProcessExecutor::new(&dirs.state_dir)?;
823
824 self.cell_outputs.clear();
826 self.widget_values.clear();
827 self.widget_defs.clear();
828 self.cell_output_history.clear();
829 self.cell_history_index.clear();
830
831 for state in self.cell_states.values_mut() {
833 state.set_status(CellStatus::Idle);
834 state.clear_output();
835 state.set_dirty(false);
836 }
837
838 self.broadcast(ServerMessage::KernelRestarted { error: None });
840
841 let state_msg = self.get_state();
843 self.broadcast(state_msg);
844
845 Ok(())
846 }
847
848 pub fn clear_outputs(&mut self) {
857 for state in self.cell_states.values_mut() {
859 state.clear_output();
860 state.set_dirty(false); state.set_status(CellStatus::Idle);
862 }
863
864 self.cell_outputs.clear();
866 let _ = self.executor.state_mut().clear();
867
868 self.cell_output_history.clear();
870 self.cell_history_index.clear();
871
872 self.broadcast(ServerMessage::OutputsCleared { error: None });
874
875 let state_msg = self.get_state();
877 self.broadcast(state_msg);
878 }
879
880 pub fn get_dirty_cell_ids(&self) -> Vec<CellId> {
882 let order = match self.graph.topological_order() {
883 Ok(order) => order,
884 Err(e) => {
885 tracing::error!("Failed to compute order for dirty cells: {}", e);
886 Vec::new()
887 }
888 };
889 order
890 .into_iter()
891 .filter(|id| self.cell_states.get(id).is_some_and(|state| state.is_dirty()))
892 .collect()
893 }
894
895 pub fn update_widget_value(&mut self, cell_id: CellId, widget_id: String, value: WidgetValue) {
900 self.widget_values
901 .entry(cell_id)
902 .or_default()
903 .insert(widget_id, value);
904 }
905
906 pub fn get_widget_values(&self, cell_id: CellId) -> HashMap<String, WidgetValue> {
908 self.widget_values
909 .get(&cell_id)
910 .cloned()
911 .unwrap_or_default()
912 }
913
914 pub fn get_all_widget_values(&self) -> HashMap<String, WidgetValue> {
917 let mut all_values = HashMap::new();
918 for cell_widgets in self.widget_values.values() {
919 for (widget_id, value) in cell_widgets {
920 all_values.insert(widget_id.clone(), value.clone());
921 }
922 }
923 all_values
924 }
925
926 pub fn get_widget_defs(&self, cell_id: CellId) -> Vec<WidgetDef> {
928 self.widget_defs
929 .get(&cell_id)
930 .cloned()
931 .unwrap_or_default()
932 }
933
934 fn store_widget_defs(&mut self, cell_id: CellId, widgets: Vec<WidgetDef>) {
936 if widgets.is_empty() {
937 self.widget_defs.remove(&cell_id);
938 } else {
939 self.widget_defs.insert(cell_id, widgets);
940 }
941 }
942
943 fn add_to_history(&mut self, cell_id: CellId, serialized: Arc<BoxedOutput>, display: CellOutput) {
945 use std::time::{SystemTime, UNIX_EPOCH};
946
947 let timestamp = SystemTime::now()
948 .duration_since(UNIX_EPOCH)
949 .unwrap_or_default()
950 .as_millis() as u64;
951
952 let entry = OutputHistoryEntry {
953 serialized,
954 display,
955 timestamp,
956 };
957
958 let history = self.cell_output_history.entry(cell_id).or_default();
959 history.push(entry);
960
961 while history.len() > MAX_HISTORY_PER_CELL {
963 history.remove(0);
964 }
965
966 self.cell_history_index.insert(cell_id, history.len() - 1);
968 }
969
970 pub fn select_history_entry(&mut self, cell_id: CellId, index: usize) -> Option<CellOutput> {
973 let (serialized, display) = {
975 let history = self.cell_output_history.get(&cell_id)?;
976 let entry = history.get(index)?;
977 (entry.serialized.clone(), entry.display.clone())
978 };
979
980 self.cell_outputs.insert(cell_id, serialized.clone());
982 self.executor.state_mut().store_output(cell_id, (*serialized).clone());
983
984 if let Some(state) = self.cell_states.get_mut(&cell_id) {
986 state.set_output(Some(display.clone()));
987 }
988
989 self.cell_history_index.insert(cell_id, index);
991
992 let _ = self.mark_dependents_dirty_and_get(cell_id);
994
995 Some(display)
996 }
997
998 fn mark_dependents_dirty_and_get(&mut self, cell_id: CellId) -> Vec<CellId> {
1004 let dependents = self.graph.invalidated_cells(cell_id);
1006 let mut dirty_cells = Vec::new();
1007
1008 for dep_id in dependents.into_iter().skip(1) {
1011 if self.cell_outputs.contains_key(&dep_id) {
1013 if let Some(state) = self.cell_states.get_mut(&dep_id) {
1014 state.set_dirty(true);
1015 dirty_cells.push(dep_id);
1016 }
1017 }
1018 }
1019 dirty_cells
1020 }
1021
1022 fn output_hash(output: &BoxedOutput) -> u64 {
1024 let mut hasher = rustc_hash::FxHasher::default();
1025 output.bytes().hash(&mut hasher);
1026 hasher.finish()
1027 }
1028
1029 pub fn get_history_count(&self, cell_id: CellId) -> usize {
1031 self.cell_output_history.get(&cell_id).map(|h| h.len()).unwrap_or(0)
1032 }
1033
1034 pub fn get_history_index(&self, cell_id: CellId) -> usize {
1036 self.cell_history_index.get(&cell_id).copied().unwrap_or(0)
1037 }
1038
1039 pub fn cell_states(&self) -> &HashMap<CellId, CellState> {
1041 &self.cell_states
1042 }
1043
1044 pub fn insert_cell(&mut self, after_cell_id: Option<CellId>) -> ServerResult<String> {
1049 let after_name = after_cell_id.and_then(|id| {
1051 self.cells.iter().find(|c| c.id == id).map(|c| c.name.clone())
1052 });
1053
1054 let mut editor = SourceEditor::load(&self.path)?;
1056 let new_name = editor.insert_cell(after_name.as_deref())?;
1057 editor.save()?;
1058
1059 self.undo_manager.record(UndoableOperation::InsertCell {
1061 cell_name: new_name.clone(),
1062 after_cell_name: after_name,
1063 });
1064
1065 self.reload()?;
1068
1069 Ok(new_name)
1070 }
1071
1072 pub fn delete_cell(&mut self, cell_id: CellId) -> ServerResult<()> {
1076 let cell_name = self.cells
1078 .iter()
1079 .find(|c| c.id == cell_id)
1080 .map(|c| c.name.clone())
1081 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1082
1083 let dependents: Vec<String> = self.cells
1085 .iter()
1086 .filter(|c| c.id != cell_id) .filter(|c| {
1088 c.dependencies
1089 .iter()
1090 .any(|dep| dep.param_name == cell_name)
1091 })
1092 .map(|c| c.name.clone())
1093 .collect();
1094
1095 if !dependents.is_empty() {
1096 return Err(ServerError::InvalidOperation(format!(
1097 "Cannot delete cell '{}' because it is used by: {}",
1098 cell_name,
1099 dependents.join(", ")
1100 )));
1101 }
1102
1103 let mut editor = SourceEditor::load(&self.path)?;
1105
1106 let source = editor.get_cell_source(&cell_name)?;
1108 let after_cell_name = editor.get_previous_cell_name(&cell_name)?;
1109
1110 editor.delete_cell(&cell_name)?;
1111 editor.save()?;
1112
1113 self.undo_manager.record(UndoableOperation::DeleteCell {
1115 cell_name: cell_name.clone(),
1116 source,
1117 after_cell_name,
1118 });
1119
1120 self.reload()?;
1122
1123 Ok(())
1124 }
1125
1126 pub fn duplicate_cell(&mut self, cell_id: CellId) -> ServerResult<String> {
1131 let cell_name = self.cells
1133 .iter()
1134 .find(|c| c.id == cell_id)
1135 .map(|c| c.name.clone())
1136 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1137
1138 let mut editor = SourceEditor::load(&self.path)?;
1140 let new_name = editor.duplicate_cell(&cell_name)?;
1141 editor.save()?;
1142
1143 self.undo_manager.record(UndoableOperation::DuplicateCell {
1145 original_cell_name: cell_name,
1146 new_cell_name: new_name.clone(),
1147 });
1148
1149 self.reload()?;
1151
1152 Ok(new_name)
1153 }
1154
1155 pub fn move_cell(&mut self, cell_id: CellId, direction: MoveDirection) -> ServerResult<()> {
1159 let cell_name = self.cells
1161 .iter()
1162 .find(|c| c.id == cell_id)
1163 .map(|c| c.name.clone())
1164 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1165
1166 let mut editor = SourceEditor::load(&self.path)?;
1168 editor.move_cell(&cell_name, direction)?;
1169 editor.save()?;
1170
1171 self.undo_manager.record(UndoableOperation::MoveCell {
1173 cell_name,
1174 direction,
1175 });
1176
1177 self.reload()?;
1179
1180 Ok(())
1181 }
1182
1183 pub fn edit_cell(&mut self, cell_id: CellId, new_source: String) -> ServerResult<()> {
1187 let cell = self.cells
1189 .iter()
1190 .find(|c| c.id == cell_id)
1191 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1192
1193 let cell_name = cell.name.clone();
1194 let old_source = cell.source_code.clone();
1195
1196 let mut editor = SourceEditor::load(&self.path)?;
1198
1199 let (reconstructed, start_line, end_line) = editor.reconstruct_and_get_span(&cell_name, &new_source)?;
1201
1202 tracing::info!("Editing cell '{}' lines {}-{}, reconstructed length: {}", cell_name, start_line, end_line, reconstructed.len());
1203 editor.edit_raw_code(start_line, end_line, &reconstructed)?;
1204 editor.save()?;
1205
1206 self.undo_manager.record(UndoableOperation::EditCell {
1208 cell_id,
1209 start_line,
1210 end_line,
1211 old_source,
1212 new_source: new_source.clone(),
1213 });
1214
1215 let outputs_by_name: HashMap<String, Arc<BoxedOutput>> = self.cells.iter()
1218 .filter_map(|c| self.cell_outputs.get(&c.id).map(|o| (c.name.clone(), o.clone())))
1219 .collect();
1220
1221 self.reload()?;
1222
1223 self.cell_outputs.clear();
1225 for cell in &self.cells {
1226 if cell.name != cell_name {
1227 if let Some(output) = outputs_by_name.get(&cell.name) {
1228 self.cell_outputs.insert(cell.id, output.clone());
1229 }
1230 }
1231 }
1232
1233 Ok(())
1234 }
1235
1236 pub fn rename_cell(&mut self, cell_id: CellId, new_display_name: String) -> ServerResult<()> {
1240 let (cell_name, old_display_name) = self.cells
1242 .iter()
1243 .find(|c| c.id == cell_id)
1244 .map(|c| (c.name.clone(), c.display_name.clone()))
1245 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1246
1247 let mut editor = SourceEditor::load(&self.path)?;
1249 editor.rename_cell(&cell_name, &new_display_name)?;
1250 editor.save()?;
1251
1252 self.undo_manager.record(UndoableOperation::RenameCell {
1254 cell_name,
1255 old_display_name,
1256 new_display_name,
1257 });
1258
1259 self.reload()?;
1261
1262 Ok(())
1263 }
1264
1265 pub fn insert_markdown_cell(&mut self, content: String, after_cell_id: Option<CellId>) -> ServerResult<()> {
1269 let after_line = after_cell_id.and_then(|id| {
1271 self.cells.iter().find(|c| c.id == id)
1273 .map(|c| c.span.end_line)
1274 .or_else(|| {
1275 self.markdown_cells.iter().find(|m| m.id == id)
1277 .map(|m| m.span.end_line)
1278 })
1279 });
1280
1281 let mut editor = SourceEditor::load(&self.path)?;
1283 editor.insert_markdown_cell(&content, after_line)?;
1284
1285 let start_line = after_line.map(|l| l + 1).unwrap_or(0);
1287 let line_count = content.lines().count();
1288 let end_line = start_line + line_count;
1289
1290 editor.save()?;
1291
1292 self.undo_manager.record(UndoableOperation::InsertMarkdownCell {
1294 start_line,
1295 end_line,
1296 content: content.clone(),
1297 });
1298
1299 self.reload()?;
1301
1302 Ok(())
1303 }
1304
1305 pub fn edit_markdown_cell(&mut self, cell_id: CellId, new_content: String) -> ServerResult<()> {
1309 let md_cell = self.markdown_cells
1311 .iter()
1312 .find(|m| m.id == cell_id)
1313 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1314
1315 let start_line = md_cell.span.start_line;
1316 let end_line = md_cell.span.end_line;
1317 let old_content = md_cell.content.clone();
1318 let is_module_doc = md_cell.is_module_doc;
1319
1320 let mut editor = SourceEditor::load(&self.path)?;
1322 editor.edit_markdown_cell(start_line, end_line, &new_content, is_module_doc)?;
1323 editor.save()?;
1324
1325 self.undo_manager.record(UndoableOperation::EditMarkdownCell {
1327 start_line,
1328 end_line,
1329 old_content,
1330 new_content,
1331 is_module_doc,
1332 });
1333
1334 self.reload()?;
1336
1337 Ok(())
1338 }
1339
1340 pub fn delete_markdown_cell(&mut self, cell_id: CellId) -> ServerResult<()> {
1344 let md_cell = self.markdown_cells
1346 .iter()
1347 .find(|m| m.id == cell_id)
1348 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1349
1350 let start_line = md_cell.span.start_line;
1351 let end_line = md_cell.span.end_line;
1352 let content = md_cell.content.clone();
1353
1354 let mut editor = SourceEditor::load(&self.path)?;
1356 editor.delete_markdown_cell(start_line, end_line)?;
1357 editor.save()?;
1358
1359 self.undo_manager.record(UndoableOperation::DeleteMarkdownCell {
1361 start_line,
1362 content,
1363 });
1364
1365 self.reload()?;
1367
1368 Ok(())
1369 }
1370
1371 pub fn move_markdown_cell(&mut self, cell_id: CellId, direction: MoveDirection) -> ServerResult<()> {
1375 let md_cell = self.markdown_cells
1377 .iter()
1378 .find(|m| m.id == cell_id)
1379 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1380
1381 let start_line = md_cell.span.start_line;
1382 let end_line = md_cell.span.end_line;
1383
1384 let mut editor = SourceEditor::load(&self.path)?;
1386 editor.move_markdown_cell(start_line, end_line, direction)?;
1387 editor.save()?;
1388
1389 self.undo_manager.record(UndoableOperation::MoveMarkdownCell {
1391 start_line,
1392 end_line,
1393 direction,
1394 });
1395
1396 self.reload()?;
1398
1399 Ok(())
1400 }
1401
1402 fn infer_definition_type(content: &str) -> Option<venus_core::graph::DefinitionType> {
1409 use venus_core::graph::DefinitionType;
1410
1411 let trimmed = content.trim();
1412
1413 if trimmed.starts_with("use ") || trimmed.starts_with("pub use ") {
1415 return Some(DefinitionType::Import);
1416 }
1417
1418 if trimmed.contains("struct ") {
1420 return Some(DefinitionType::Struct);
1421 }
1422
1423 if trimmed.contains("enum ") {
1425 return Some(DefinitionType::Enum);
1426 }
1427
1428 if trimmed.contains("type ") && !trimmed.contains("fn ") {
1430 return Some(DefinitionType::TypeAlias);
1431 }
1432
1433 if trimmed.contains("fn ") && !trimmed.contains("#[venus::cell]") {
1435 return Some(DefinitionType::HelperFunction);
1436 }
1437
1438 None
1439 }
1440
1441 fn validate_definition_type(
1448 content: &str,
1449 declared_type: venus_core::graph::DefinitionType,
1450 ) -> ServerResult<()> {
1451 if let Some(inferred_type) = Self::infer_definition_type(content)
1452 && std::mem::discriminant(&inferred_type) != std::mem::discriminant(&declared_type) {
1453 tracing::warn!(
1454 "Definition type mismatch: declared {:?} but content suggests {:?}",
1455 declared_type,
1456 inferred_type
1457 );
1458 }
1461 Ok(())
1462 }
1463
1464 pub fn insert_definition_cell(
1471 &mut self,
1472 content: String,
1473 definition_type: venus_core::graph::DefinitionType,
1474 after_cell_id: Option<CellId>,
1475 ) -> ServerResult<CellId> {
1476 Self::validate_definition_type(&content, definition_type)?;
1478 let after_line = after_cell_id.and_then(|id| {
1480 self.cells.iter().find(|c| c.id == id)
1482 .map(|c| c.span.end_line)
1483 .or_else(|| {
1484 self.markdown_cells.iter().find(|m| m.id == id)
1486 .map(|m| m.span.end_line)
1487 })
1488 .or_else(|| {
1489 self.definition_cells.iter().find(|d| d.id == id)
1491 .map(|d| d.span.end_line)
1492 })
1493 });
1494
1495 let mut editor = SourceEditor::load(&self.path)?;
1497 editor.insert_raw_code(&content, after_line)?;
1498
1499 let start_line = after_line.map(|l| l + 1).unwrap_or(0);
1500 let line_count = content.lines().count();
1501 let end_line = start_line + line_count;
1502
1503 editor.save()?;
1504
1505 self.undo_manager.record(UndoableOperation::InsertDefinitionCell {
1507 start_line,
1508 end_line,
1509 content: content.clone(),
1510 definition_type,
1511 });
1512
1513 self.reload()?;
1515
1516 let new_cell_id = self.definition_cells
1518 .iter()
1519 .find(|d| d.span.start_line >= start_line && d.span.start_line <= end_line)
1520 .map(|d| d.id)
1521 .ok_or_else(|| ServerError::InvalidOperation("Failed to find inserted definition cell".to_string()))?;
1522
1523 Ok(new_cell_id)
1524 }
1525
1526 pub fn edit_definition_cell(&mut self, cell_id: CellId, new_content: String) -> ServerResult<Vec<CellId>> {
1531 let def_cell = self.definition_cells
1533 .iter()
1534 .find(|d| d.id == cell_id)
1535 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1536
1537 let start_line = def_cell.span.start_line;
1538 let end_line = def_cell.span.end_line;
1539 let old_content = def_cell.content.clone();
1540
1541 let mut editor = SourceEditor::load(&self.path)?;
1543 editor.edit_raw_code(start_line, end_line, &new_content)?;
1545 editor.save()?;
1546
1547 self.undo_manager.record(UndoableOperation::EditDefinitionCell {
1549 cell_id,
1550 start_line,
1551 end_line,
1552 old_content,
1553 new_content: new_content.clone(),
1554 });
1555
1556 self.reload()?;
1558
1559 let dirty_cells: Vec<CellId> = self.cells.iter()
1561 .filter(|c| self.cell_outputs.contains_key(&c.id)) .map(|c| c.id)
1563 .collect();
1564 for &cell_id in &dirty_cells {
1565 if let Some(state) = self.cell_states.get_mut(&cell_id) {
1566 state.set_dirty(true);
1567 }
1568 }
1569
1570 Ok(dirty_cells)
1571 }
1572
1573 pub fn delete_definition_cell(&mut self, cell_id: CellId) -> ServerResult<()> {
1577 let def_cell = self.definition_cells
1579 .iter()
1580 .find(|d| d.id == cell_id)
1581 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1582
1583 let start_line = def_cell.span.start_line;
1584 let end_line = def_cell.span.end_line;
1585 let content = def_cell.content.clone();
1586 let definition_type = def_cell.definition_type;
1587
1588 let mut editor = SourceEditor::load(&self.path)?;
1590 editor.delete_markdown_cell(start_line, end_line)?;
1591 editor.save()?;
1592
1593 self.undo_manager.record(UndoableOperation::DeleteDefinitionCell {
1595 start_line,
1596 end_line,
1597 content,
1598 definition_type,
1599 });
1600
1601 self.reload()?;
1603
1604 Ok(())
1605 }
1606
1607 pub fn move_definition_cell(&mut self, cell_id: CellId, direction: MoveDirection) -> ServerResult<()> {
1611 let def_cell = self.definition_cells
1613 .iter()
1614 .find(|d| d.id == cell_id)
1615 .ok_or_else(|| ServerError::CellNotFound(cell_id))?;
1616
1617 let start_line = def_cell.span.start_line;
1618 let end_line = def_cell.span.end_line;
1619
1620 let mut editor = SourceEditor::load(&self.path)?;
1622 editor.move_markdown_cell(start_line, end_line, direction)?;
1623 editor.save()?;
1624
1625 self.undo_manager.record(UndoableOperation::MoveDefinitionCell {
1627 start_line,
1628 end_line,
1629 direction,
1630 });
1631
1632 self.reload()?;
1634
1635 Ok(())
1636 }
1637
1638 pub fn undo(&mut self) -> ServerResult<String> {
1642 let operation = self.undo_manager.pop_undo()
1643 .ok_or_else(|| ServerError::InvalidOperation("Nothing to undo".to_string()))?;
1644
1645 let description = operation.undo_description();
1646
1647 let mut editor = SourceEditor::load(&self.path)?;
1649
1650 match &operation {
1651 UndoableOperation::InsertCell { cell_name, .. } => {
1652 editor.delete_cell(cell_name)?;
1654 }
1655 UndoableOperation::DeleteCell { source, after_cell_name, .. } => {
1656 editor.restore_cell(source, after_cell_name.as_deref())?;
1658 }
1659 UndoableOperation::DuplicateCell { new_cell_name, .. } => {
1660 editor.delete_cell(new_cell_name)?;
1662 }
1663 UndoableOperation::MoveCell { cell_name, direction } => {
1664 let reverse_direction = match direction {
1666 MoveDirection::Up => MoveDirection::Down,
1667 MoveDirection::Down => MoveDirection::Up,
1668 };
1669 editor.move_cell(cell_name, reverse_direction)?;
1670 }
1671 UndoableOperation::RenameCell { cell_name, old_display_name, .. } => {
1672 editor.rename_cell(cell_name, old_display_name)?;
1674 }
1675 UndoableOperation::EditCell { start_line, end_line, old_source, .. } => {
1676 editor.edit_raw_code(*start_line, *end_line, old_source)?;
1678 }
1679 UndoableOperation::InsertMarkdownCell { start_line, end_line, .. } => {
1680 editor.delete_markdown_cell(*start_line, *end_line)?;
1682 }
1683 UndoableOperation::EditMarkdownCell { start_line, end_line, old_content, is_module_doc, .. } => {
1684 editor.edit_markdown_cell(*start_line, *end_line, old_content, *is_module_doc)?;
1686 }
1687 UndoableOperation::DeleteMarkdownCell { start_line, content } => {
1688 let after_line = if *start_line > 0 { Some(start_line - 1) } else { None };
1690 editor.insert_markdown_cell(content, after_line)?;
1691 }
1692 UndoableOperation::MoveMarkdownCell { start_line, end_line, direction } => {
1693 let reverse_direction = match direction {
1695 MoveDirection::Up => MoveDirection::Down,
1696 MoveDirection::Down => MoveDirection::Up,
1697 };
1698 editor.move_markdown_cell(*start_line, *end_line, reverse_direction)?;
1699 }
1700 UndoableOperation::InsertDefinitionCell { start_line, end_line, .. } => {
1701 editor.delete_markdown_cell(*start_line, *end_line)?;
1703 }
1704 UndoableOperation::EditDefinitionCell { start_line, end_line, old_content, .. } => {
1705 editor.edit_markdown_cell(*start_line, *end_line, old_content, false)?;
1707 }
1708 UndoableOperation::DeleteDefinitionCell { start_line, content, .. } => {
1709 let after_line = if *start_line > 0 { Some(start_line - 1) } else { None };
1711 editor.insert_markdown_cell(content, after_line)?;
1712 }
1713 UndoableOperation::MoveDefinitionCell { start_line, end_line, direction } => {
1714 let reverse_direction = match direction {
1716 MoveDirection::Up => MoveDirection::Down,
1717 MoveDirection::Down => MoveDirection::Up,
1718 };
1719 editor.move_markdown_cell(*start_line, *end_line, reverse_direction)?;
1720 }
1721 }
1722
1723 editor.save()?;
1724
1725 self.undo_manager.record_redo(operation);
1727
1728 self.reload()?;
1730
1731 Ok(description)
1732 }
1733
1734 pub fn redo(&mut self) -> ServerResult<String> {
1738 let operation = self.undo_manager.pop_redo()
1739 .ok_or_else(|| ServerError::InvalidOperation("Nothing to redo".to_string()))?;
1740
1741 let description = operation.description();
1742
1743 let mut editor = SourceEditor::load(&self.path)?;
1745
1746 match &operation {
1747 UndoableOperation::InsertCell { after_cell_name, .. } => {
1748 let _ = editor.insert_cell(after_cell_name.as_deref())?;
1750 }
1751 UndoableOperation::DeleteCell { cell_name, .. } => {
1752 editor.delete_cell(cell_name)?;
1754 }
1755 UndoableOperation::DuplicateCell { original_cell_name, .. } => {
1756 let _ = editor.duplicate_cell(original_cell_name)?;
1758 }
1759 UndoableOperation::MoveCell { cell_name, direction } => {
1760 editor.move_cell(cell_name, *direction)?;
1762 }
1763 UndoableOperation::RenameCell { cell_name, new_display_name, .. } => {
1764 editor.rename_cell(cell_name, new_display_name)?;
1766 }
1767 UndoableOperation::EditCell { start_line, end_line, new_source, .. } => {
1768 editor.edit_raw_code(*start_line, *end_line, new_source)?;
1770 }
1771 UndoableOperation::InsertMarkdownCell { start_line, content, .. } => {
1772 let after_line = if *start_line > 0 { Some(start_line - 1) } else { None };
1774 editor.insert_markdown_cell(content, after_line)?;
1775 }
1776 UndoableOperation::EditMarkdownCell { start_line, end_line, new_content, is_module_doc, .. } => {
1777 editor.edit_markdown_cell(*start_line, *end_line, new_content, *is_module_doc)?;
1779 }
1780 UndoableOperation::DeleteMarkdownCell { start_line, content } => {
1781 let line_count = content.lines().count();
1784 let end_line = start_line + line_count;
1785 editor.delete_markdown_cell(*start_line, end_line)?;
1786 }
1787 UndoableOperation::MoveMarkdownCell { start_line, end_line, direction } => {
1788 editor.move_markdown_cell(*start_line, *end_line, *direction)?;
1790 }
1791 UndoableOperation::InsertDefinitionCell { start_line, content, .. } => {
1792 let after_line = if *start_line > 0 { Some(start_line - 1) } else { None };
1794 editor.insert_markdown_cell(content, after_line)?;
1795 }
1796 UndoableOperation::EditDefinitionCell { start_line, end_line, new_content, .. } => {
1797 editor.edit_markdown_cell(*start_line, *end_line, new_content, false)?;
1799 }
1800 UndoableOperation::DeleteDefinitionCell { start_line, content, .. } => {
1801 let line_count = content.lines().count();
1803 let end_line = start_line + line_count;
1804 editor.delete_markdown_cell(*start_line, end_line)?;
1805 }
1806 UndoableOperation::MoveDefinitionCell { start_line, end_line, direction } => {
1807 editor.move_markdown_cell(*start_line, *end_line, *direction)?;
1809 }
1810 }
1811
1812 editor.save()?;
1813
1814 self.undo_manager.record(operation);
1816
1817 self.reload()?;
1819
1820 Ok(description)
1821 }
1822
1823 pub fn get_undo_redo_state(&self) -> ServerMessage {
1825 ServerMessage::UndoRedoState {
1826 can_undo: self.undo_manager.can_undo(),
1827 can_redo: self.undo_manager.can_redo(),
1828 undo_description: self.undo_manager.undo_description(),
1829 redo_description: self.undo_manager.redo_description(),
1830 }
1831 }
1832
1833 pub fn clear_undo_history(&mut self) {
1837 self.undo_manager.clear();
1838 }
1839}
1840
1841#[cfg(test)]
1842mod tests {
1843 use super::*;
1844
1845 #[test]
1846 fn test_session_creation() {
1847 let (tx, _rx) = broadcast::channel::<ServerMessage>(16);
1849 drop(tx);
1850 }
1851}