do_memory_storage_turso/
lib.rs1#![allow(clippy::expect_used)]
2#![allow(unsafe_code)] #![allow(clippy::unwrap_used)] #![allow(invalid_value)] #![allow(dead_code)] #![allow(clippy::excessive_nesting)] #![allow(unused_mut)] #![allow(unused_assignments)] #![allow(clippy::derivable_impls)] #![allow(clippy::should_implement_trait)] #![allow(clippy::unnecessary_map_or)] #![allow(clippy::useless_asref)] #![allow(clippy::cast_precision_loss)]
17#![allow(clippy::cast_possible_truncation)]
18#![allow(clippy::cast_sign_loss)]
19#![allow(clippy::cast_possible_wrap)]
20#![allow(clippy::cast_lossless)]
21#![allow(clippy::cognitive_complexity)]
23#![allow(clippy::missing_errors_doc)]
24#![allow(clippy::doc_markdown)]
25#![allow(clippy::must_use_candidate)]
26#![allow(clippy::return_self_not_must_use)]
27#![allow(clippy::map_unwrap_or)]
28#![allow(clippy::redundant_closure)]
29#![allow(clippy::redundant_closure_for_method_calls)]
30#![allow(clippy::match_same_arms)]
31#![allow(clippy::uninlined_format_args)]
32#![allow(clippy::needless_pass_by_value)]
34#![allow(clippy::unused_self)]
35#![allow(clippy::unused_async)]
36#![allow(clippy::format_in_format_args)]
37#![allow(clippy::to_string_in_format_args)]
38#![allow(clippy::unreadable_literal)]
39#![allow(clippy::struct_excessive_bools)]
40#![allow(clippy::panic)]
41#![allow(clippy::float_cmp)]
42#![allow(clippy::items_after_statements)]
43#![allow(clippy::wildcard_imports)]
44#![allow(clippy::used_underscore_binding)]
45#![allow(clippy::used_underscore_items)]
46#![allow(clippy::ptr_as_ptr)]
47#![allow(clippy::ptr_cast_constness)]
48#![allow(clippy::format_push_string)]
49#![allow(clippy::implicit_clone)]
50#![allow(clippy::missing_fields_in_debug)]
51#![allow(clippy::needless_raw_string_hashes)]
52#![allow(clippy::default_trait_access)]
53#![allow(clippy::missing_panics_doc)]
54#![allow(clippy::no_effect_underscore_binding)]
55#![allow(rust_2024_compatibility)]
56#![allow(tail_expr_drop_order)]
57#![allow(clippy::unnecessary_wraps)]
58#![allow(clippy::unchecked_time_subtraction)]
59#![allow(clippy::semicolon_if_nothing_returned)]
60#![allow(missing_docs)]
61#![allow(unknown_lints)]
62#![allow(clippy::unknown_lints)]
63
64use do_memory_core::{Error, Result};
88
89pub mod cache;
91pub mod pool;
92mod relationships;
93mod resilient;
94mod schema;
95#[cfg(test)]
96mod tests;
97
98#[cfg(feature = "hybrid_search")]
99mod fts5_schema;
100
101pub mod storage;
103
104pub mod trait_impls;
106
107pub mod turso_config;
109
110pub mod prepared;
112
113pub mod metrics;
115
116#[cfg(feature = "compression")]
118pub mod compression;
119
120#[cfg(feature = "compression")]
122pub mod transport;
123
124mod lib_impls;
126
127pub use lib_impls::TursoStorage;
129pub use lib_impls::{StorageMode, TursoConfig};
130
131#[async_trait::async_trait]
134pub trait SelfLearningMemoryExt {
135 async fn with_local_storage(
137 path: impl AsRef<std::path::Path> + Send,
138 ) -> Result<do_memory_core::memory::SelfLearningMemory>;
139 async fn with_in_memory_storage() -> Result<do_memory_core::memory::SelfLearningMemory>;
141}
142
143#[async_trait::async_trait]
144impl SelfLearningMemoryExt for do_memory_core::memory::SelfLearningMemory {
145 async fn with_local_storage(
146 path: impl AsRef<std::path::Path> + Send,
147 ) -> Result<do_memory_core::memory::SelfLearningMemory> {
148 let storage = TursoStorage::new_local(path).await?;
149 storage.initialize_schema().await?;
150
151 let cache = std::sync::Arc::new(
152 do_memory_storage_redb::RedbStorage::new(std::path::Path::new(":memory:"))
153 .await
154 .map_err(|e| do_memory_core::Error::Storage(e.to_string()))?,
155 );
156 Ok(do_memory_core::memory::SelfLearningMemory::with_storage(
157 do_memory_core::MemoryConfig::default(),
158 std::sync::Arc::new(storage),
159 cache,
160 ))
161 }
162
163 async fn with_in_memory_storage() -> Result<do_memory_core::memory::SelfLearningMemory> {
164 let storage = TursoStorage::new_in_memory().await?;
165 storage.initialize_schema().await?;
166
167 let cache = std::sync::Arc::new(
168 do_memory_storage_redb::RedbStorage::new(std::path::Path::new(":memory:"))
169 .await
170 .map_err(|e| do_memory_core::Error::Storage(e.to_string()))?,
171 );
172 Ok(do_memory_core::memory::SelfLearningMemory::with_storage(
173 do_memory_core::MemoryConfig::default(),
174 std::sync::Arc::new(storage),
175 cache,
176 ))
177 }
178}
179
180pub use cache::query_cache::{AdvancedCacheStats, AdvancedQueryCache, QueryKey};
182pub use cache::{
183 AdaptiveTTLCache, CacheConfig, CacheEntry, CacheStats, CacheStatsSnapshot, CachedTursoStorage,
184 TTLConfig, TTLConfigError,
185};
186
187pub use pool::{
189 AdaptiveConnectionPool, AdaptivePoolConfig, AdaptivePoolMetrics, AdaptivePooledConnection,
190};
191pub use pool::{
192 ConnectionPool, PoolConfig, PoolMetrics, PoolMetricsSnapshot, PoolStatistics, PooledConnection,
193};
194#[cfg(feature = "keepalive-pool")]
195pub use pool::{KeepAliveConfig, KeepAlivePool, KeepAliveStatistics};
196pub use prepared::{PreparedCacheConfig, PreparedCacheStats, PreparedStatementCache};
197pub use resilient::ResilientStorage;
198
199pub use metrics::{
201 ExportConfig, ExportFormat, ExportStats, ExportTarget, ExportedMetric, MetricType, MetricValue,
202 MetricsCollector, MetricsHttpServer, PrometheusExporter, TursoMetrics,
203};
204pub use storage::batch::episode_batch::BatchConfig;
205pub use storage::capacity::CapacityStatistics;
206pub use storage::episodes::EpisodeQuery;
207pub use storage::patterns::{PatternMetadata, PatternQuery};
208pub use trait_impls::StorageStatistics;
209
210#[cfg(feature = "compression")]
212pub use compression::{
213 CompressedPayload, CompressionAlgorithm, CompressionStatistics, compress, compress_embedding,
214 compress_json, decompress, decompress_embedding,
215};
216
217#[cfg(feature = "compression")]
219pub use transport::{
220 CompressedTransport, Transport, TransportCompressionConfig, TransportCompressionError,
221 TransportCompressionStats, TransportMetadata, TransportResponse,
222};
223
224#[cfg(test)]
235mod ext_tests {
236 use super::*;
237 use do_memory_core::memory::SelfLearningMemory;
238
239 #[tokio::test]
240 async fn test_with_in_memory_storage() {
241 let memory = SelfLearningMemory::with_in_memory_storage().await.unwrap();
242 let (primary, cache) = memory.storage_backends();
243 assert!(primary.is_some());
244 assert!(cache.is_some());
245 }
246
247 #[tokio::test]
248 #[ignore = "flaky in full suite: libsql concurrent connection race (ADR-027); passes in isolation"]
249 async fn test_with_local_storage() {
250 let dir = tempfile::tempdir().unwrap();
251 let path = dir.path().join("test.db");
252 let memory = SelfLearningMemory::with_local_storage(&path).await.unwrap();
253 let (primary, cache) = memory.storage_backends();
254 assert!(primary.is_some());
255 assert!(cache.is_some());
256 }
257}