Skip to main content

arama_cache/
lib.rs

1//! # arama-cache
2//!
3//! Caches AI inference results (thumbnails + feature vectors) for image
4//! and video files in SQLite, backed by the [`localcache`] engine
5//! (RFC 002). The cache database holds two namespaces — `image` and
6//! `video` — in a single file, with per-file freshness tracked by
7//! metadata-first change detection.
8//!
9//! ## Choosing a handle
10//!
11//! | Type | Purpose |
12//! |---|---|
13//! | [`ImageCacheWriter`] | Register, look up, and delete image entries |
14//! | [`ImageCacheReader`] | Look up image entries (parallel-friendly) |
15//! | [`VideoCacheWriter`] | Register, look up, and delete video entries |
16//! | [`VideoCacheReader`] | Look up video entries (parallel-friendly) |
17//!
18//! Writers serialize database writes through a single connection; both
19//! writers and readers serve lookups from a pool of `read_conns`
20//! read-only connections, so cloned readers can fan lookups out across
21//! threads.
22//!
23//! ## Basic usage
24//!
25//! ```rust,no_run
26//! use arama_cache::{
27//!     CacheConfig, DbLocation, ImageCacheConfig, ImageCacheWriter, LookupResult,
28//!     UpsertImageRequest,
29//! };
30//!
31//! # fn main() -> anyhow::Result<()> {
32//! let writer = ImageCacheWriter::as_session(ImageCacheConfig {
33//!     cache_config: CacheConfig {
34//!         db_location: DbLocation::AppCache(None),
35//!         read_conns: 4,
36//!         thumbnail_dir: Some("/var/cache/myapp/thumbs".into()),
37//!     },
38//! })?;
39//!
40//! writer.upsert(UpsertImageRequest {
41//!     path: "/data/photo.jpg".into(),
42//!     clip_vector: Some(vec![0.1, 0.2, 0.3]),
43//! })?;
44//!
45//! match writer.lookup(std::path::Path::new("/data/photo.jpg"))? {
46//!     LookupResult::Hit(entry) => {
47//!         println!("thumbnail: {:?}", entry.thumbnail_path);
48//!         println!("features:  {:?}", entry.features);
49//!     }
50//!     LookupResult::Invalidated => println!("file changed; will be recomputed"),
51//!     LookupResult::Miss => println!("not cached"),
52//! }
53//! # Ok(())
54//! # }
55//! ```
56//!
57//! ## `onetime` — single-shot calls
58//!
59//! ```rust,no_run
60//! use arama_cache::{DbLocation, ImageCacheWriter};
61//!
62//! # fn main() -> anyhow::Result<()> {
63//! let result = ImageCacheWriter::onetime(DbLocation::WorkDir(None))?
64//!     .lookup(std::path::Path::new("/data/photo.jpg"))?;
65//! # Ok(())
66//! # }
67//! ```
68//!
69//! ## Migrating from the v1 cache
70//!
71//! Applications upgrading from the `file-feature-cache`-backed v1
72//! database run [`migrate_v1_if_present`] once at startup; it is a no-op
73//! when there is nothing to migrate.
74
75mod core;
76pub mod types;
77
78pub use core::engine::{CacheConfig, CacheError, DbLocation, Result};
79pub use core::image::{ImageCacheConfig, ImageCacheReader, ImageCacheWriter};
80pub use core::migrate::{MigrationReport, migrate_v1_if_present};
81pub use core::video::{VideoCacheConfig, VideoCacheReader, VideoCacheWriter};
82pub use types::{
83    CacheRead, DirCacheSummary, ImageCacheEntry, ImageFeatures, LookupResult, UpsertImageRequest,
84    UpsertVideoRequest, VideoCacheEntry, VideoFeatures,
85};