Skip to main content

do_memory_storage_redb/
patterns.rs

1//! Pattern storage operations for redb cache
2
3use crate::{Error, PATTERNS_TABLE, RedbStorage};
4use do_memory_core::{Pattern, Result, episode::PatternId};
5use redb::{ReadableDatabase, ReadableTable};
6use std::sync::Arc;
7use tracing::debug;
8use tracing::info;
9
10use crate::episodes::RedbQuery;
11
12impl RedbStorage {
13    /// Store a pattern in cache
14    pub async fn store_pattern(&self, pattern: &Pattern) -> Result<()> {
15        debug!("Storing pattern in cache: {}", pattern.id());
16        let db = Arc::clone(&self.db);
17        let pattern_id = pattern.id().to_string();
18        let pattern_bytes = postcard::to_allocvec(pattern)
19            .map_err(|e| Error::Storage(format!("Failed to serialize pattern: {}", e)))?;
20
21        tokio::task::spawn_blocking(move || {
22            let write_txn = db
23                .begin_write()
24                .map_err(|e| Error::Storage(format!("Failed to begin write transaction: {}", e)))?;
25
26            {
27                let mut table = write_txn
28                    .open_table(PATTERNS_TABLE)
29                    .map_err(|e| Error::Storage(format!("Failed to open patterns table: {}", e)))?;
30
31                table
32                    .insert(pattern_id.as_str(), pattern_bytes.as_slice())
33                    .map_err(|e| Error::Storage(format!("Failed to insert pattern: {}", e)))?;
34            }
35
36            write_txn
37                .commit()
38                .map_err(|e| Error::Storage(format!("Failed to commit transaction: {}", e)))?;
39
40            Ok::<(), Error>(())
41        })
42        .await
43        .map_err(|e| Error::Storage(format!("Task join error: {}", e)))??;
44
45        info!("Successfully cached pattern: {}", pattern.id());
46        Ok(())
47    }
48
49    /// Retrieve a pattern from cache
50    pub async fn get_pattern(&self, pattern_id: PatternId) -> Result<Option<Pattern>> {
51        debug!("Retrieving pattern from cache: {}", pattern_id);
52        let db = Arc::clone(&self.db);
53        let pattern_id_str = pattern_id.to_string();
54
55        tokio::task::spawn_blocking(move || {
56            let read_txn = db
57                .begin_read()
58                .map_err(|e| Error::Storage(format!("Failed to begin read transaction: {}", e)))?;
59
60            let table = read_txn
61                .open_table(PATTERNS_TABLE)
62                .map_err(|e| Error::Storage(format!("Failed to open patterns table: {}", e)))?;
63
64            match table
65                .get(pattern_id_str.as_str())
66                .map_err(|e| Error::Storage(format!("Failed to get pattern: {}", e)))?
67            {
68                Some(bytes_guard) => {
69                    let _bytes = bytes_guard.value();
70                    let pattern: Pattern =
71                        postcard::from_bytes(bytes_guard.value()).map_err(|e| {
72                            Error::Storage(format!("Failed to deserialize pattern: {}", e))
73                        })?;
74                    Ok(Some(pattern))
75                }
76                None => Ok(None),
77            }
78        })
79        .await
80        .map_err(|e| Error::Storage(format!("Task join error: {}", e)))?
81    }
82
83    /// Get all patterns from cache (with optional limit)
84    pub async fn get_all_patterns(&self, query: &RedbQuery) -> Result<Vec<Pattern>> {
85        debug!("Retrieving all patterns from cache");
86        let db = Arc::clone(&self.db);
87        let limit = query.limit;
88
89        tokio::task::spawn_blocking(move || {
90            let read_txn = db
91                .begin_read()
92                .map_err(|e| Error::Storage(format!("Failed to begin read transaction: {}", e)))?;
93
94            let table = read_txn
95                .open_table(PATTERNS_TABLE)
96                .map_err(|e| Error::Storage(format!("Failed to open patterns table: {}", e)))?;
97
98            let mut patterns = Vec::new();
99            let iter = table
100                .iter()
101                .map_err(|e| Error::Storage(format!("Failed to iterate patterns: {}", e)))?;
102
103            for (count, result) in iter.enumerate() {
104                if let Some(max) = limit {
105                    if count >= max {
106                        break;
107                    }
108                }
109
110                let (_, bytes_guard) = result
111                    .map_err(|e| Error::Storage(format!("Failed to read pattern entry: {}", e)))?;
112
113                let pattern: Pattern = postcard::from_bytes(bytes_guard.value())
114                    .map_err(|e| Error::Storage(format!("Failed to deserialize pattern: {}", e)))?;
115
116                patterns.push(pattern);
117            }
118
119            Ok(patterns)
120        })
121        .await
122        .map_err(|e| Error::Storage(format!("Task join error: {}", e)))?
123    }
124}