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 95 96 97 98
//! Cacheable trait and implementation of cache logic. use crate::CacheError; #[cfg(feature = "derive")] pub use hitbox_derive::Cacheable; /// Trait describes cache configuration per type that implements this trait. pub trait Cacheable { /// Method should return unique identifier for struct object. /// /// In cache storage it may prepends with cache version and Upstream name. /// /// # Examples /// /// ``` /// use hitbox::cache::Cacheable; /// use hitbox::CacheError; /// /// struct QueryNothing { /// id: Option<i32>, /// } /// /// impl Cacheable for QueryNothing { /// fn cache_key(&self) -> Result<String, CacheError> { /// let key = format!("{}::id::{}", self.cache_key_prefix(), self.id.map_or_else( /// || "None".to_owned(), |id| id.to_string()) /// ); /// Ok(key) /// } /// fn cache_key_prefix(&self) -> String { "database::QueryNothing".to_owned() } /// } /// /// let query = QueryNothing { id: Some(1) }; /// assert_eq!(query.cache_key().unwrap(), "database::QueryNothing::id::1"); /// let query = QueryNothing { id: None }; /// assert_eq!(query.cache_key().unwrap(), "database::QueryNothing::id::None"); /// ``` fn cache_key(&self) -> Result<String, CacheError>; /// Method return cache key prefix based on message type. fn cache_key_prefix(&self) -> String; /// Describe time-to-live (ttl) value for cache storage in seconds. /// /// After that time value will be removed from cache storage. fn cache_ttl(&self) -> u32 { 60 } /// Describe expire\stale timeout value for cache storage in seconds. /// /// After that time cached value marked as stale. /// /// ```ignore /// |__cache_is_valid__|__cache_is_stale__| -> time /// ^ ^ /// stale_ttl ttl (cache evicted) /// ``` fn cache_stale_ttl(&self) -> u32 { let ttl = self.cache_ttl(); let stale_time = 5; if ttl >= stale_time { ttl - stale_time } else { 0 } } /// Describe current cache version for this type. fn cache_version(&self) -> u32 { 0 } } #[cfg(test)] mod tests { use super::*; struct Message; impl Cacheable for Message { fn cache_key(&self) -> Result<String, CacheError> { Ok("Message".to_owned()) } fn cache_key_prefix(&self) -> String { "Message".to_owned() } fn cache_ttl(&self) -> u32 { 2 } } #[test] fn test_cache_stale_ttl_subtract_overflow() { let a = Message; assert_eq!(0, a.cache_stale_ttl()); } }