Skip to main content

hydracache_sqlx/
lib.rs

1//! SQLx-facing integration crate for HydraCache database result caching.
2//!
3//! The database-neutral query cache API lives in `hydracache-db`. This crate
4//! keeps SQLx users on a convenient import path while avoiding a hard conceptual
5//! dependency between the generic adapter and SQLx itself.
6//!
7//! # Example
8//!
9//! ```rust
10//! use hydracache::HydraCache;
11//! use hydracache_sqlx::DbCache;
12//! use serde::{Deserialize, Serialize};
13//!
14//! #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15//! struct User {
16//!     id: i64,
17//!     name: String,
18//! }
19//!
20//! # #[tokio::main]
21//! # async fn main() -> hydracache_sqlx::Result<()> {
22//! let local = HydraCache::local().build();
23//!
24//! // SQLx users may import DbCache from this crate, but the type itself is
25//! // database-neutral and comes from hydracache-db.
26//! let queries = DbCache::new(local, "db");
27//!
28//! let user = queries
29//!     .cached::<User>()
30//!     .key("user:42")
31//!     .tag("user:42")
32//!     .fetch_with(|| async {
33//!         // This loader runs only on a cache miss. On a cache hit, HydraCache
34//!         // returns the cached User and this SQLx code is not executed.
35//!         Ok::<_, std::io::Error>(User {
36//!             id: 42,
37//!             name: "Ada".to_owned(),
38//!         })
39//!     })
40//!     .await?;
41//!
42//! assert_eq!(user.id, 42);
43//! # Ok(())
44//! # }
45//! ```
46
47pub use hydracache_db::{DbCache, DbCacheError, DbQuery, Result};
48
49/// SQLx-specific compatibility name for [`DbCache`].
50pub type SqlxCache<C = hydracache::PostcardCodec> = DbCache<C>;
51
52/// SQLx-specific compatibility name for [`DbQuery`].
53pub type SqlxQuery<T, C = hydracache::PostcardCodec> = DbQuery<T, C>;
54
55/// SQLx-specific compatibility name for [`DbCacheError`].
56pub type SqlxCacheError = DbCacheError;
57
58/// Re-export the SQLx crate used by this adapter.
59///
60/// This lets downstream users keep one adapter-aligned SQLx version in examples
61/// and integration code without hiding SQLx behind HydraCache abstractions.
62pub use sqlx;
63
64#[cfg(test)]
65mod tests {
66    use hydracache::HydraCache;
67    use serde::{Deserialize, Serialize};
68
69    use crate::{DbCache, SqlxCache};
70
71    #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
72    struct User {
73        id: u64,
74    }
75
76    #[tokio::test]
77    async fn sqlx_cache_alias_matches_database_cache_api() {
78        let query = SqlxCache::new(HydraCache::local().build(), "sqlx")
79            .cached::<User>()
80            .key("user:1");
81
82        assert_eq!(query.physical_key(), Some("sqlx:user:1".to_owned()));
83    }
84
85    #[tokio::test]
86    async fn db_cache_reexport_is_available_from_sqlx_crate() {
87        let query = DbCache::new(HydraCache::local().build(), "db")
88            .cached::<User>()
89            .key("user:1");
90
91        assert_eq!(query.physical_key(), Some("db:user:1".to_owned()));
92    }
93}