forceps/
lib.rs

1//! `forceps` is a simple and easy-to-use on-disk cache/database for large files.
2//!
3//! **This crate is intended to be used with the [`tokio`] runtime.**
4//!
5//! `forceps` is made to be an easy-to-use, thread-safe, performant, and asynchronous disk cache
6//! that has easy reading and manipulation of data. It levereges tokio's async `fs` APIs
7//! and fast task schedulers to perform IO operations, and `sled` as a fast metadata database.
8//!
9//! ## Features
10//!
11//! - Asynchronous APIs
12//! - Fast and reliable reading/writing
13//! - Optional memory-cache layer
14//! - Tuned for large-file databases
15//! - Included cache eviction (LRU/FIFO)
16//! - Easily accessible value metadata
17//! - Optimized for cache `HIT`s
18//! - Easy error handling
19//! - `bytes` crate support (non-optional)
20//!
21//! ## Database and Meta-database
22//!
23//! This database solution easily separates data into two databases: the LFS (large-file-storage)
24//! database, and the metadata database. The LFS database is powered using Tokio's async filesystem
25//! operations, whereas the metadata database is powered using [`sled`].
26//!
27//! The advantage of splitting these two up is simple: Accessing metadata (for things like database
28//! eviction) is realatively cheap and efficient, with the only downside being that `async` is not
29//! present.
30//!
31//! # Examples
32//!
33//! ```rust,no_run
34//! use std::error::Error;
35//! use forceps::Cache;
36//!
37//! #[tokio::main]
38//! async fn main() -> Result<(), Box<dyn Error>> {
39//!     let cache = Cache::new("./cache")
40//!         .build()
41//!         .await?;
42//!
43//!     cache.write(b"MY_KEY", b"Hello World").await?;
44//!     let data = cache.read(b"MY_KEY").await?;
45//!     assert_eq!(data.as_ref(), b"Hello World");
46//!
47//!     Ok(())
48//! }
49//! ```
50
51#![warn(missing_docs)]
52#![warn(rustdoc::broken_intra_doc_links)]
53
54use std::error;
55use std::io;
56
57/// Global error type for the `forceps` crate, which is used in the `Result` types of all calls to
58/// forcep APIs.
59#[derive(Debug)]
60pub enum ForcepError {
61    /// An I/O operation error. This can occur on reads, writes, or builds.
62    Io(io::Error),
63    /// Error deserialization metadata information (most likely corrupted)
64    MetaDe(bson::error::Error),
65    /// Error serializing metadata information
66    MetaSer(bson::error::Error),
67    /// Error with metadata sled database operation
68    MetaDb(sled::Error),
69    /// The entry was found successfully, but the metadata was strangely not present
70    MetaNotFound,
71    /// The entry for the specified key is not found
72    NotFound,
73}
74/// Re-export of [`ForcepError`]
75pub type Error = ForcepError;
76/// Result that is returned by all error-bound operations of `forceps`.
77pub type Result<T> = std::result::Result<T, ForcepError>;
78
79impl std::fmt::Display for ForcepError {
80    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        match self {
82            Self::Io(e) => write!(fmt, "an I/O error occurred: {}", e),
83            Self::MetaDe(e) => write!(fmt, "there was a problem deserializing metadata: {e}"),
84            Self::MetaSer(e) => write!(fmt, "there was a problem serializing metadata: {e}"),
85            Self::MetaDb(e) => write!(fmt, "an error with the metadata database occurred: {e}"),
86            Self::MetaNotFound => write!(
87                fmt,
88                "the entry for the key provided was found, but the metadata was strangely not present"
89            ),
90            Self::NotFound => write!(fmt, "the entry for the key provided was not found"),
91        }
92    }
93}
94impl error::Error for ForcepError {
95    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
96        match self {
97            Self::Io(e) => Some(e),
98            Self::MetaDe(e) => Some(e),
99            Self::MetaSer(e) => Some(e),
100            Self::MetaDb(e) => Some(e),
101            Self::MetaNotFound => None,
102            Self::NotFound => None,
103        }
104    }
105}
106
107mod mem_cache;
108mod tmp;
109
110mod hash;
111pub use hash::HashBytes;
112
113mod cache;
114pub use cache::{Cache, CacheBuilder};
115
116mod metadata;
117pub(crate) use metadata::MetaDb;
118pub use metadata::Metadata;
119
120/// A collection of [`Cache`] eviction algorithms and generics
121///
122/// This module contains the [`Evictor`] trait, which is used to signify a structure or enum that
123/// is used to evict items out of a cache, as well as some implementations of that trait.
124///
125/// [`Evictor`]: crate::evictors::Evictor
126pub mod evictors;