1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Copyright 2019-2026 Apilium Technologies OÜ. All rights reserved.
// SPDX-License-Identifier: Apache-2.0 OR Commercial
//! Storage backend trait definition
//!
//! This module defines the common interface for all storage backends.
//! Implementations include SQLite (for IoT) and RocksDB (for production).
use crate::error::Result;
use crate::types::{Action, Entry, Hash, Link, Record};
use serde::{Deserialize, Serialize};
/// Trait for storage backends - enables different implementations
/// (SQLite, RocksDB, LMDB, Memory, etc.)
///
/// Note: Not Sync because some backends (like SQLite) have single-writer limitations.
/// For async usage, wrap in Arc<Mutex<Storage>> or use a connection pool.
pub trait StorageBackend: Send {
/// Store an action
fn put_action(&self, action: &Action) -> Result<Hash>;
/// Store an entry
fn put_entry(&self, entry: &Entry) -> Result<Hash>;
/// Store a record (action + optional entry)
fn put_record(&self, record: &Record) -> Result<Hash>;
/// Store multiple records in a single transaction (batch operation)
///
/// This is more efficient than calling `put_record` multiple times
/// as it reduces transaction overhead.
///
/// Default implementation falls back to individual puts.
fn put_records_batch(&self, records: &[Record]) -> Result<Vec<Hash>> {
records.iter().map(|r| self.put_record(r)).collect()
}
/// Get action by hash
fn get_action(&self, hash: &Hash) -> Result<Option<Action>>;
/// Get entry by hash
fn get_entry(&self, hash: &Hash) -> Result<Option<Entry>>;
/// Get latest action sequence number
fn get_latest_seq(&self) -> Result<u32>;
/// Get records by sequence range (for sync)
///
/// Returns records with sequence numbers in [from_seq, to_seq), limited by `limit`.
/// Used for incremental synchronization between peers.
fn get_records_by_seq_range(
&self,
from_seq: u32,
to_seq: u32,
limit: u32,
) -> Result<Vec<Record>>;
/// Get storage statistics
fn stats(&self) -> Result<StorageStats>;
/// Add a link
fn add_link(&self, link: &Link) -> Result<i64>;
/// Delete a link (soft delete)
fn delete_link(&self, link_id: i64) -> Result<()>;
/// Get links from base
fn get_links(&self, base: &Hash, link_type: Option<u8>) -> Result<Vec<Link>>;
/// Set metadata
fn set_metadata(&self, key: &str, value: &str) -> Result<()>;
/// Get metadata
fn get_metadata(&self, key: &str) -> Result<Option<String>>;
/// Vacuum/compact the storage
fn vacuum(&self) -> Result<()>;
/// Check if storage is within size limits
fn check_limits(&self) -> Result<bool>;
}
/// Storage statistics
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct StorageStats {
/// Number of actions stored
pub action_count: u64,
/// Number of entries stored
pub entry_count: u64,
/// Number of active links
pub link_count: u64,
/// Database size in bytes
pub db_size: usize,
}