swiftide_integrations/redb/
mod.rs

1//! Redb is a simple, portable, high-performance, ACID, embedded key-value store.
2//!
3//! Redb can be used as a fast, embedded node cache, without the need for external services.
4
5use anyhow::Result;
6use std::{path::PathBuf, sync::Arc};
7
8use derive_builder::Builder;
9
10mod node_cache;
11
12/// `Redb` provides a caching filter for indexing nodes using Redb.
13///
14/// Redb is a simple, portable, high-performance, ACID, embedded key-value store.
15/// It enables using a local file based cache without the need for external services.
16///
17/// # Example
18///
19/// ```no_run
20/// # use swiftide_integrations::redb::{Redb};
21/// Redb::builder()
22///     .database_path("/my/redb")
23///     .table_name("swiftide_test")
24///     .cache_key_prefix("my_cache")
25///     .build().unwrap();
26/// ```
27#[derive(Clone, Builder)]
28#[builder(build_fn(error = "anyhow::Error"), setter(into))]
29pub struct Redb {
30    /// The database to use for caching nodes. Allows overwriting the default database created from
31    /// `database_path`.
32    #[builder(setter(into), default = "Arc::new(self.default_database()?)")]
33    database: Arc<redb::Database>,
34
35    /// Path to the database, required if no database override is provided. This is the recommended
36    /// usage.
37    #[builder(setter(into, strip_option))]
38    database_path: Option<PathBuf>,
39    /// The name of the table to use for caching nodes. Defaults to "swiftide".
40    #[builder(default = "\"swiftide\".to_string()")]
41    table_name: String,
42    /// Prefix to be used for keys stored in the database to avoid collisions. Can be used to
43    /// manually invalidate the cache.
44    #[builder(default = "String::new()")]
45    cache_key_prefix: String,
46}
47
48impl std::fmt::Debug for Redb {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("Redb")
51            .field("database", &self.database)
52            .field("database_path", &self.database_path)
53            .field("table_name", &self.table_name)
54            .field("cache_key_prefix", &self.cache_key_prefix)
55            .finish()
56    }
57}
58
59impl RedbBuilder {
60    fn default_database(&self) -> Result<redb::Database> {
61        let db = redb::Database::create(
62            self.database_path
63                .clone()
64                .flatten()
65                .ok_or(anyhow::anyhow!("Expected database path"))?,
66        )?;
67
68        Ok(db)
69    }
70}
71
72impl Redb {
73    pub fn builder() -> RedbBuilder {
74        RedbBuilder::default()
75    }
76    pub fn node_key(&self, node: &swiftide_core::indexing::TextNode) -> String {
77        format!("{}.{}", self.cache_key_prefix, node.id())
78    }
79
80    pub fn table_definition(&self) -> redb::TableDefinition<'_, String, bool> {
81        redb::TableDefinition::<String, bool>::new(&self.table_name)
82    }
83
84    pub fn database(&self) -> &redb::Database {
85        &self.database
86    }
87}