Skip to main content

text_document_frontend/
app_context.rs

1// Generated by Qleany v1.7.3 from frontend_app_context.tera
2
3use common::database::db_context::DbContext;
4use common::event::EventHub;
5use common::long_operation::LongOperationManager;
6use common::undo_redo::UndoRedoManager;
7use flume::{Receiver, Sender};
8use std::sync::{Arc, Mutex};
9
10/// Application context that holds all shared state.
11///
12/// Shutdown lifecycle: when [`AppContext::shutdown`] is called the shared
13/// `shutdown_tx` is dropped, which makes every cloned `shutdown_rx`
14/// (held by `EventHubClient::start` threads) see `Disconnected` on its
15/// next `recv()` and exit. No polling and no atomic flag needed.
16#[derive(Clone, Debug)]
17pub struct AppContext {
18    pub db_context: DbContext,
19    pub event_hub: Arc<EventHub>,
20    /// Receiver clones are handed to background event-hub threads.
21    /// Threads exit when the matching sender is dropped via
22    /// [`AppContext::shutdown`].
23    pub shutdown_rx: Receiver<()>,
24    /// Shared single sender. `shutdown()` takes it out, dropping
25    /// the only live `Sender` and unblocking every receiver clone.
26    /// Wrapped in `Mutex<Option<…>>` so `shutdown()` stays `&self`
27    /// (the alternative — store the sender directly in `AppContext`
28    /// — would force every clone to hold its own sender clone and
29    /// `Disconnect` would only fire after the last clone dropped,
30    /// defeating the explicit `shutdown()` API).
31    shutdown_tx: Arc<Mutex<Option<Sender<()>>>>,
32    pub undo_redo_manager: Arc<Mutex<UndoRedoManager>>,
33    pub long_operation_manager: Arc<Mutex<LongOperationManager>>,
34}
35
36impl AppContext {
37    pub fn new() -> Self {
38        let db_context = DbContext::new().expect("Failed to create database context");
39
40        let event_hub = Arc::new(EventHub::new());
41        // Bounded(1) is enough — we only ever drop the sender, never
42        // actually send a unit on this channel. The bound keeps the
43        // allocation tiny.
44        let (shutdown_tx, shutdown_rx) = flume::bounded(1);
45
46        let undo_redo_manager = Arc::new(Mutex::new(UndoRedoManager::new()));
47        let long_operation_manager = Arc::new(Mutex::new(LongOperationManager::new()));
48
49        // Inject event hub into long_operation_manager
50        {
51            let mut lom = long_operation_manager.lock().unwrap();
52            lom.set_event_hub(&event_hub);
53        }
54
55        Self {
56            db_context,
57            event_hub,
58            shutdown_rx,
59            shutdown_tx: Arc::new(Mutex::new(Some(shutdown_tx))),
60            undo_redo_manager,
61            long_operation_manager,
62        }
63    }
64
65    /// Signal background event-hub threads to stop. Idempotent — the
66    /// second call is a no-op because the sender has already been
67    /// taken.
68    pub fn shutdown(&self) {
69        let _ = self.shutdown_tx.lock().unwrap().take();
70    }
71}
72
73impl Default for AppContext {
74    fn default() -> Self {
75        Self::new()
76    }
77}