Skip to main content

hydracache_db/
lib.rs

1//! Database-neutral query result caching helpers for HydraCache.
2//!
3//! This crate is intentionally a thin runtime adapter. It does not replace a
4//! database client, ORM, or query builder. Callers keep their database library
5//! as the query authority and provide an explicit cache key, tags, and TTL
6//! around the operation they want to cache.
7//!
8//! # Example
9//!
10//! ```rust
11//! use hydracache::HydraCache;
12//! use hydracache_db::{
13//!     DbCache, HydraCacheEntity, PreparedQueryPolicy, QueryCachePolicy, RefreshPolicy,
14//! };
15//! use serde::{Deserialize, Serialize};
16//!
17//! #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, HydraCacheEntity)]
18//! #[hydracache(entity = "user", collection = "users", id = i64)]
19//! struct User {
20//!     id: i64,
21//!     name: String,
22//! }
23//!
24//! # #[tokio::main]
25//! # async fn main() -> hydracache_db::Result<()> {
26//! let local = HydraCache::local().build();
27//!
28//! // The adapter wraps the local HydraCache instance. The namespace becomes
29//! // part of the physical cache key, so key("user:42") is stored as
30//! // "db:user:42".
31//! let queries = DbCache::new(local, "db");
32//!
33//! let policy = QueryCachePolicy::read_mostly()
34//!     // Metadata helper: key "user:42", tag "user:42", and tag "users".
35//!     .for_cache_entity::<User>(42)
36//!     .with_name("load-user")
37//!     .refresh_policy(
38//!         RefreshPolicy::new()
39//!             .refresh_ahead(std::time::Duration::from_secs(10))
40//!             .stale_while_revalidate(std::time::Duration::from_secs(300)),
41//!     );
42//!
43//! let user = queries
44//!     .cached_with::<User>(policy)
45//!     .load(|| async {
46//!         // This loader runs only on a cache miss. On a cache hit, HydraCache
47//!         // returns the cached User and this database code is not executed.
48//!         Ok::<_, std::io::Error>(User {
49//!             id: 42,
50//!             name: "Ada".to_owned(),
51//!         })
52//!     })
53//!     .await?;
54//!
55//! assert_eq!(user.id, 42);
56//! # Ok(())
57//! # }
58//! ```
59//!
60//! For hot repository methods, prepare stable metadata once and bind only the
61//! dynamic id on each call:
62//!
63//! ```rust
64//! use hydracache::HydraCache;
65//! use hydracache_db::{DbCache, HydraCacheEntity, PreparedQueryPolicy};
66//! use serde::{Deserialize, Serialize};
67//!
68//! #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, HydraCacheEntity)]
69//! #[hydracache(entity = "user", collection = "users", id = i64)]
70//! struct User {
71//!     id: i64,
72//!     name: String,
73//! }
74//!
75//! # #[tokio::main]
76//! # async fn main() -> hydracache_db::Result<()> {
77//! let queries = DbCache::new(HydraCache::local().build(), "db");
78//! let load_user = queries.prepare::<User>(
79//!     PreparedQueryPolicy::per_entity()
80//!         .cache_entity::<User>()
81//!         .with_name("load-user"),
82//! );
83//!
84//! let user = load_user
85//!     .load_id(42, || async {
86//!         Ok::<_, std::io::Error>(User {
87//!             id: 42,
88//!             name: "Ada".to_owned(),
89//!         })
90//!     })
91//!     .await?;
92//!
93//! assert_eq!(user.id, 42);
94//! # Ok(())
95//! # }
96//! ```
97//!
98//! For compact policy construction, use [`query_cache_policy!`]:
99//!
100//! ```rust
101//! use hydracache_db::{query_cache_policy, CacheEntity};
102//!
103//! struct User;
104//!
105//! impl CacheEntity for User {
106//!     type Id = i64;
107//!
108//!     const ENTITY: &'static str = "user";
109//!     const COLLECTION: Option<&'static str> = Some("users");
110//! }
111//!
112//! let user_id = 42_i64;
113//! let policy = query_cache_policy!(
114//!     name = "load-user",
115//!     entity = User,
116//!     id = user_id,
117//!     ttl_secs = 60,
118//! );
119//!
120//! assert_eq!(policy.name(), Some("load-user"));
121//! assert_eq!(policy.key_value(), Some("user:42"));
122//! ```
123
124extern crate self as hydracache_db;
125
126mod entity;
127mod error;
128mod policy;
129mod prepared;
130mod query;
131
132pub use entity::CacheEntity;
133pub use error::{DbCacheError, Result};
134pub use hydracache_macros::{query_cache_policy, HydraCacheEntity};
135pub use policy::QueryCachePolicy;
136pub use prepared::PreparedQueryPolicy;
137pub use query::{DbCache, DbQuery, PreparedDbQuery};
138
139/// Database-facing alias for local cache refresh/stale behavior.
140pub type RefreshPolicy = hydracache::RefreshOptions;
141
142#[cfg(test)]
143mod tests;