Skip to main content

kapsl_rag/storage/
mod.rs

1use std::fs;
2use std::io;
3use std::path::PathBuf;
4
5#[derive(thiserror::Error, Debug)]
6pub enum DocStoreError {
7    #[error("io error: {0}")]
8    Io(String),
9}
10
11impl From<io::Error> for DocStoreError {
12    fn from(err: io::Error) -> Self {
13        DocStoreError::Io(err.to_string())
14    }
15}
16
17#[derive(Debug, Clone)]
18pub struct DocKey {
19    pub tenant_id: String,
20    pub workspace_id: String,
21    pub source_id: String,
22    pub doc_id: String,
23}
24
25pub trait DocStore: Send + Sync {
26    fn put(&self, key: &DocKey, bytes: &[u8]) -> Result<PathBuf, DocStoreError>;
27    fn get(&self, key: &DocKey) -> Result<Vec<u8>, DocStoreError>;
28    fn delete(&self, key: &DocKey) -> Result<(), DocStoreError>;
29}
30
31#[derive(Debug, Clone)]
32pub struct FsDocStore {
33    pub root: PathBuf,
34}
35
36impl FsDocStore {
37    pub fn new(root: impl Into<PathBuf>) -> Self {
38        Self { root: root.into() }
39    }
40
41    fn path_for(&self, key: &DocKey) -> PathBuf {
42        self.root
43            .join(&key.tenant_id)
44            .join(&key.workspace_id)
45            .join(&key.source_id)
46            .join(&key.doc_id)
47    }
48}
49
50impl DocStore for FsDocStore {
51    fn put(&self, key: &DocKey, bytes: &[u8]) -> Result<PathBuf, DocStoreError> {
52        let path = self.path_for(key);
53        if let Some(parent) = path.parent() {
54            fs::create_dir_all(parent)?;
55        }
56        fs::write(&path, bytes)?;
57        Ok(path)
58    }
59
60    fn get(&self, key: &DocKey) -> Result<Vec<u8>, DocStoreError> {
61        let path = self.path_for(key);
62        let data = fs::read(path)?;
63        Ok(data)
64    }
65
66    fn delete(&self, key: &DocKey) -> Result<(), DocStoreError> {
67        let path = self.path_for(key);
68        if path.exists() {
69            fs::remove_file(path)?;
70        }
71        Ok(())
72    }
73}