pub struct MultiUserMemoryManager {Show 23 fields
pub user_memories: Cache<String, Arc<RwLock<MemorySystem>>>,
pub audit_logs: Arc<DashMap<String, Arc<RwLock<VecDeque<AuditEvent>>>>>,
pub shared_db: Arc<DB>,
pub base_path: PathBuf,
pub default_config: MemoryConfig,
pub audit_log_counter: Arc<AtomicUsize>,
pub graph_memories: Cache<String, Arc<RwLock<GraphMemory>>>,
pub neural_ner: Arc<NeuralNer>,
pub keyword_extractor: Arc<KeywordExtractor>,
pub user_evictions: Arc<AtomicUsize>,
pub server_config: ServerConfig,
pub event_broadcaster: Sender<MemoryEvent>,
pub streaming_extractor: Arc<StreamingMemoryExtractor>,
pub prospective_store: Arc<ProspectiveStore>,
pub todo_store: Arc<TodoStore>,
pub file_store: Arc<FileMemoryStore>,
pub feedback_store: Arc<RwLock<FeedbackStore>>,
pub backup_engine: Arc<ShodhBackupEngine>,
pub context_sessions: Arc<ContextSessions>,
pub context_broadcaster: Sender<ContextStatus>,
pub ab_test_manager: Arc<ABTestManager>,
pub session_store: Arc<SessionStore>,
pub relevance_engine: Arc<RelevanceEngine>,
/* private fields */
}Expand description
Multi-user memory manager - central state for the server
Fields§
§user_memories: Cache<String, Arc<RwLock<MemorySystem>>>Per-user memory systems with LRU eviction
audit_logs: Arc<DashMap<String, Arc<RwLock<VecDeque<AuditEvent>>>>>Per-user audit logs (in-memory cache)
Shared DB for all global stores (todos, reminders, files, feedback, audit)
base_path: PathBufBase storage path
default_config: MemoryConfigDefault config
audit_log_counter: Arc<AtomicUsize>Counter for audit log rotation checks
graph_memories: Cache<String, Arc<RwLock<GraphMemory>>>Per-user graph memory systems
neural_ner: Arc<NeuralNer>Neural NER for automatic entity extraction
keyword_extractor: Arc<KeywordExtractor>Statistical keyword extraction for graph population
user_evictions: Arc<AtomicUsize>User eviction counter for metrics
server_config: ServerConfigServer configuration
event_broadcaster: Sender<MemoryEvent>SSE event broadcaster for real-time dashboard updates
streaming_extractor: Arc<StreamingMemoryExtractor>Streaming memory extractor for implicit learning
prospective_store: Arc<ProspectiveStore>Prospective memory store for reminders/intentions
todo_store: Arc<TodoStore>GTD-style todo store
file_store: Arc<FileMemoryStore>File memory store for codebase integration
feedback_store: Arc<RwLock<FeedbackStore>>Implicit feedback store for memory reinforcement
backup_engine: Arc<ShodhBackupEngine>Backup engine for automated and manual backups
context_sessions: Arc<ContextSessions>Context status from Claude Code sessions
context_broadcaster: Sender<ContextStatus>SSE broadcaster for context status updates
ab_test_manager: Arc<ABTestManager>A/B testing manager for relevance scoring experiments
session_store: Arc<SessionStore>Session tracking store
relevance_engine: Arc<RelevanceEngine>Shared relevance engine for proactive memory surfacing (entity cache + learned weights persist)
Implementations§
Source§impl MultiUserMemoryManager
impl MultiUserMemoryManager
pub fn new(base_path: PathBuf, server_config: ServerConfig) -> Result<Self>
Sourcepub fn log_event(
&self,
user_id: &str,
event_type: &str,
memory_id: &str,
details: &str,
)
pub fn log_event( &self, user_id: &str, event_type: &str, memory_id: &str, details: &str, )
Log audit event (non-blocking with background persistence)
Sourcepub fn emit_event(&self, event: MemoryEvent)
pub fn emit_event(&self, event: MemoryEvent)
Emit SSE event to all connected dashboard clients
Sourcepub fn subscribe_events(&self) -> Receiver<MemoryEvent>
pub fn subscribe_events(&self) -> Receiver<MemoryEvent>
Subscribe to SSE events
Sourcepub fn get_history(
&self,
user_id: &str,
memory_id: Option<&str>,
) -> Vec<AuditEvent>
pub fn get_history( &self, user_id: &str, memory_id: Option<&str>, ) -> Vec<AuditEvent>
Get audit history for user
Sourcepub fn get_user_memory(
&self,
user_id: &str,
) -> Result<Arc<RwLock<MemorySystem>>>
pub fn get_user_memory( &self, user_id: &str, ) -> Result<Arc<RwLock<MemorySystem>>>
Get or create memory system for a user
Uses double-checked locking to prevent TOCTOU races where concurrent first-access requests both miss the cache and try to open RocksDB. RocksDB holds exclusive file locks, so the second open would fail.
Sourcepub fn evict_user(&self, user_id: &str)
pub fn evict_user(&self, user_id: &str)
Evict a user’s memory and graph from in-memory caches (releases DB handles). Does NOT delete data — used before restore to release file locks.
Sourcepub fn forget_user(&self, user_id: &str) -> Result<()>
pub fn forget_user(&self, user_id: &str) -> Result<()>
Delete user data (GDPR compliance)
Cleans up:
- In-memory caches (user_memories, graph_memories)
- Shared RocksDB: todos, projects, todo indices, reminders, files, feedback, audit
- Per-user filesystem: per-user RocksDB, graph DB, vector indices
Sourcepub fn get_stats(&self, user_id: &str) -> Result<MemoryStats>
pub fn get_stats(&self, user_id: &str) -> Result<MemoryStats>
Get statistics for a user
Sourcepub fn list_users(&self) -> Vec<String>
pub fn list_users(&self) -> Vec<String>
List all users
Sourcepub fn list_cached_users(&self) -> Vec<String>
pub fn list_cached_users(&self) -> Vec<String>
List users currently loaded in the Moka cache (no filesystem scan)
Sourcepub fn get_audit_logs(&self, user_id: &str, limit: usize) -> Vec<AuditEvent>
pub fn get_audit_logs(&self, user_id: &str, limit: usize) -> Vec<AuditEvent>
Get audit logs for a user
Sourcepub fn flush_all_databases(&self) -> Result<()>
pub fn flush_all_databases(&self) -> Result<()>
Flush all RocksDB databases
Sourcepub fn save_all_vector_indices(&self) -> Result<()>
pub fn save_all_vector_indices(&self) -> Result<()>
Save all vector indices to disk
Sourcepub fn get_neural_ner(&self) -> Arc<NeuralNer>
pub fn get_neural_ner(&self) -> Arc<NeuralNer>
Get neural NER for entity extraction
Sourcepub fn get_keyword_extractor(&self) -> Arc<KeywordExtractor>
pub fn get_keyword_extractor(&self) -> Arc<KeywordExtractor>
Get keyword extractor for statistical term extraction
Sourcepub fn get_user_graph(&self, user_id: &str) -> Result<Arc<RwLock<GraphMemory>>>
pub fn get_user_graph(&self, user_id: &str) -> Result<Arc<RwLock<GraphMemory>>>
Get or create graph memory for a user
Uses the same per-user creation lock as get_user_memory to prevent concurrent RocksDB open races on the graph directory.
Sourcepub fn get_user_graph_stats(&self, user_id: &str) -> Result<GraphStats>
pub fn get_user_graph_stats(&self, user_id: &str) -> Result<GraphStats>
Get graph statistics for a user
Sourcepub fn run_maintenance_all_users(&self) -> usize
pub fn run_maintenance_all_users(&self) -> usize
Run maintenance on all cached user memories
Sourcepub fn streaming_extractor(&self) -> &Arc<StreamingMemoryExtractor>
pub fn streaming_extractor(&self) -> &Arc<StreamingMemoryExtractor>
Get the streaming extractor
Sourcepub fn backup_engine(&self) -> &Arc<ShodhBackupEngine>
pub fn backup_engine(&self) -> &Arc<ShodhBackupEngine>
Get the backup engine
Sourcepub fn ab_test_manager(&self) -> &Arc<ABTestManager>
pub fn ab_test_manager(&self) -> &Arc<ABTestManager>
Get the A/B test manager
Sourcepub fn todo_store(&self) -> &Arc<TodoStore>
pub fn todo_store(&self) -> &Arc<TodoStore>
Get the todo store
Sourcepub fn prospective_store(&self) -> &Arc<ProspectiveStore>
pub fn prospective_store(&self) -> &Arc<ProspectiveStore>
Get the prospective store
Sourcepub fn file_store(&self) -> &Arc<FileMemoryStore>
pub fn file_store(&self) -> &Arc<FileMemoryStore>
Get the file store
Sourcepub fn feedback_store(&self) -> &Arc<RwLock<FeedbackStore>> ⓘ
pub fn feedback_store(&self) -> &Arc<RwLock<FeedbackStore>> ⓘ
Get the feedback store
Sourcepub fn session_store(&self) -> &Arc<SessionStore>
pub fn session_store(&self) -> &Arc<SessionStore>
Get the session store
Sourcepub fn context_sessions(&self) -> &Arc<ContextSessions> ⓘ
pub fn context_sessions(&self) -> &Arc<ContextSessions> ⓘ
Get context sessions
Sourcepub fn subscribe_context(&self) -> Receiver<ContextStatus>
pub fn subscribe_context(&self) -> Receiver<ContextStatus>
Subscribe to context status updates
Sourcepub fn broadcast_context(&self, status: ContextStatus)
pub fn broadcast_context(&self, status: ContextStatus)
Broadcast context status update
Sourcepub fn server_config(&self) -> &ServerConfig
pub fn server_config(&self) -> &ServerConfig
Get server config
Sourcepub fn user_evictions(&self) -> usize
pub fn user_evictions(&self) -> usize
Get user evictions count
Sourcepub fn users_in_cache(&self) -> usize
pub fn users_in_cache(&self) -> usize
Get users in cache count
Sourcepub fn check_and_emit_due_reminders(&self) -> usize
pub fn check_and_emit_due_reminders(&self) -> usize
Active reminder check: scan all users for due reminders, mark them triggered,
and emit REMINDER_DUE events to the broadcast channel.
Called by the dedicated 60-second reminder scheduler in main.rs. Returns the number of reminders triggered.
Sourcepub fn collect_secondary_store_refs(&self) -> Vec<(String, Arc<DB>)>
pub fn collect_secondary_store_refs(&self) -> Vec<(String, Arc<DB>)>
Collect references to all secondary store databases for comprehensive backup. All shared stores (todos, prospective, files, feedback, audit) share a single DB, so we return one reference. BackupEngine handles all CFs automatically.
Sourcepub fn run_backup_all_users(&self, max_backups: usize) -> usize
pub fn run_backup_all_users(&self, max_backups: usize) -> usize
Run backups for all active users
Sourcepub fn process_experience_into_graph(
&self,
user_id: &str,
experience: &Experience,
memory_id: &MemoryId,
) -> Result<()>
pub fn process_experience_into_graph( &self, user_id: &str, experience: &Experience, memory_id: &MemoryId, ) -> Result<()>
Process an experience and extract entities/relationships into the graph
SHO-102: Improved graph building with:
- Neural NER entities
- Tags as Technology/Concept entities
- All-caps terms (API, TUI, NER, etc.)
- Issue IDs (SHO-XX pattern)
- Semantic similarity edges between memories
Auto Trait Implementations§
impl !Freeze for MultiUserMemoryManager
impl !RefUnwindSafe for MultiUserMemoryManager
impl Send for MultiUserMemoryManager
impl Sync for MultiUserMemoryManager
impl Unpin for MultiUserMemoryManager
impl UnsafeUnpin for MultiUserMemoryManager
impl !UnwindSafe for MultiUserMemoryManager
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more