mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 09:48:44 +00:00
new redis ttl cache crate (untested)
This commit is contained in:
1 parent
c06c47f02e
commit
817b2c01df
13 files changed
+161
-8
No files matched your search
Generated
+11
@@ -5354,6 +5354,17 @@ dependencies = [
|
||||
"url 2.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redis_caching"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"errors",
|
||||
"r2d2_redis",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redis_common"
|
||||
version = "0.0.1"
|
||||
|
||||
+2
-1
@@ -15,6 +15,8 @@ members = [
|
||||
|
||||
# Shared libraries
|
||||
"crates/lib/actix_helpers",
|
||||
"crates/lib/caching/memory_caching",
|
||||
"crates/lib/caching/redis_caching",
|
||||
"crates/lib/clients/cloud_storage",
|
||||
"crates/lib/clients/fakeyou_client",
|
||||
"crates/lib/clients/google_drive_common",
|
||||
@@ -32,7 +34,6 @@ members = [
|
||||
"crates/lib/idempotency",
|
||||
"crates/lib/jobs_common",
|
||||
"crates/lib/media",
|
||||
"crates/lib/memory_caching",
|
||||
"crates/lib/redis_common",
|
||||
"crates/lib/sqlite_queries",
|
||||
"crates/lib/subprocess_common",
|
||||
|
||||
@@ -15,9 +15,9 @@ path = "src/lib.rs"
|
||||
[dependencies]
|
||||
|
||||
# Internal
|
||||
config = { path = "../config" }
|
||||
container_common = { path = "../container_common" }
|
||||
errors = { path = "../errors" }
|
||||
config = { path = "../../config" }
|
||||
container_common = { path = "../../container_common" }
|
||||
errors = { path = "../../errors" }
|
||||
|
||||
# External
|
||||
anyhow = "1.0.40"
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,28 @@
|
||||
[package]
|
||||
name = "redis_caching"
|
||||
edition = "2018"
|
||||
version = "0.0.1"
|
||||
authors = [
|
||||
"Brandon Thomas <bt@brand.io>",
|
||||
"Brandon Thomas <echelon@gmail.com>",
|
||||
]
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "redis_caching"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Internal
|
||||
errors = { path = "../../errors" }
|
||||
|
||||
# Redis Database
|
||||
r2d2_redis = "0.14.0"
|
||||
|
||||
# Serialization
|
||||
serde = "1.0.125"
|
||||
serde_derive = "1.0.125"
|
||||
serde_json = "1.0.64"
|
||||
|
||||
[dev-dependencies]
|
||||
# None yet
|
||||
@@ -0,0 +1,20 @@
|
||||
//! redis_caching
|
||||
//!
|
||||
//! Easy-to use Redis caching utility.
|
||||
//!
|
||||
|
||||
// Never allow these
|
||||
#![forbid(private_in_public)]
|
||||
#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things
|
||||
|
||||
// Okay to toggle
|
||||
#![forbid(unreachable_patterns)]
|
||||
#![forbid(unused_imports)]
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
// Always allow
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
pub mod redis_ttl_cache;
|
||||
@@ -0,0 +1,93 @@
|
||||
use r2d2_redis::RedisConnectionManager;
|
||||
use r2d2_redis::r2d2::{Pool, PooledConnection};
|
||||
use r2d2_redis::redis::Commands;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use errors::AnyhowResult;
|
||||
|
||||
const DEFAULT_TTL_SECONDS : usize = 60;
|
||||
|
||||
const REDIS_KEY_PREFIX : &'static str = "_c";
|
||||
|
||||
// TODO: Async Redis
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RedisTtlCache {
|
||||
redis_pool: Pool<RedisConnectionManager>,
|
||||
default_key_ttl: usize,
|
||||
}
|
||||
|
||||
impl RedisTtlCache {
|
||||
pub fn new(redis_pool: Pool<RedisConnectionManager>) -> Self {
|
||||
Self {
|
||||
redis_pool,
|
||||
default_key_ttl: DEFAULT_TTL_SECONDS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_connection(&self) -> AnyhowResult<RedisTtlCacheConnection> {
|
||||
let redis = self.redis_pool.get()?;
|
||||
Ok(RedisTtlCacheConnection {
|
||||
redis_connection: redis,
|
||||
default_key_ttl: self.default_key_ttl,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RedisTtlCacheConnection {
|
||||
redis_connection: PooledConnection<RedisConnectionManager>,
|
||||
default_key_ttl: usize,
|
||||
}
|
||||
|
||||
impl RedisTtlCacheConnection {
|
||||
|
||||
pub fn delete_from_cache(&mut self, item_key: &str) -> AnyhowResult<()> {
|
||||
let redis_key = Self::cache_key(item_key);
|
||||
let _r : Option<String> = self.redis_connection.del(redis_key)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_from_cache<T>(&mut self, item_key: &str) -> AnyhowResult<Option<T>> where T: for <'a> Deserialize<'a> {
|
||||
let redis_key = Self::cache_key(item_key);
|
||||
let maybe_value : Option<String> = self.redis_connection.get(redis_key)?;
|
||||
|
||||
if let Some(value) = maybe_value {
|
||||
let hydrated = serde_json::from_str::<T>(&value)?;
|
||||
return Ok(Some(hydrated));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn persist_to_cache<T>(&mut self, item_key: &str, item: T) -> AnyhowResult<()> where T: Serialize {
|
||||
let redis_key = Self::cache_key(item_key);
|
||||
let value = serde_json::to_string(&item)?;
|
||||
let _r : Option<String> = self.redis_connection.set_ex(redis_key, value, self.default_key_ttl)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn lazy_load_if_not_cached<T, F>(&mut self, item_key: &str, loader_func: &mut F)
|
||||
-> AnyhowResult<Option<T>>
|
||||
where for<'a> T: Serialize + Deserialize<'a> + Clone,
|
||||
F: FnMut() -> AnyhowResult<Option<T>>,
|
||||
{
|
||||
let maybe_value = self.get_from_cache(item_key)?;
|
||||
|
||||
if let Some(value) = maybe_value {
|
||||
return Ok(value);
|
||||
}
|
||||
|
||||
let maybe_value = loader_func()?;
|
||||
|
||||
if let Some(value) = maybe_value {
|
||||
self.persist_to_cache(item_key, value.clone())?;
|
||||
return Ok(Some(value));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
|
||||
fn cache_key(key: &str) -> String {
|
||||
format!("{}:{}", REDIS_KEY_PREFIX, key)
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ database_queries = { path = "../../../lib/database_queries" }
|
||||
enums = { path = "../../../_types/enums" }
|
||||
errors = { path = "../../../lib/errors" }
|
||||
jobs_common = { path = "../../../lib/jobs_common" }
|
||||
memory_caching = { path = "../../../lib/memory_caching" }
|
||||
memory_caching = { path = "../../../lib/caching/memory_caching" }
|
||||
tokens = { path = "../../../_types/tokens" }
|
||||
tts_common = { path = "../../../lib/tts_common" }
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ container_common = { path = "../../../lib/container_common" }
|
||||
database_queries = { path = "../../../lib/database_queries" }
|
||||
hashing = { path = "../../../lib/hashing" }
|
||||
jobs_common = { path = "../../../lib/jobs_common" }
|
||||
memory_caching = { path = "../../../lib/memory_caching" }
|
||||
memory_caching = { path = "../../../lib/caching/memory_caching" }
|
||||
tts_common = { path = "../../../lib/tts_common" }
|
||||
|
||||
# Vendored code
|
||||
|
||||
@@ -24,7 +24,7 @@ errors = { path = "../../../lib/errors" }
|
||||
google_drive_common = { path = "../../../lib/clients/google_drive_common" }
|
||||
http_server_common = { path = "../../../lib/http_server_common" }
|
||||
jobs_common = { path = "../../../lib/jobs_common" }
|
||||
memory_caching = { path = "../../../lib/memory_caching" }
|
||||
memory_caching = { path = "../../../lib/caching/memory_caching" }
|
||||
redis_common = { path = "../../../lib/redis_common" }
|
||||
reusable_types = { path = "../../../_types/reusable_types" }
|
||||
tts_common = { path = "../../../lib/tts_common" }
|
||||
|
||||
@@ -30,7 +30,7 @@ google_drive_common = { path = "../../../lib/clients/google_drive_common" }
|
||||
http_server_common = { path = "../../../lib/http_server_common" }
|
||||
jobs_common = { path = "../../../lib/jobs_common" }
|
||||
media = { path = "../../../lib/media" }
|
||||
memory_caching = { path = "../../../lib/memory_caching" }
|
||||
memory_caching = { path = "../../../lib/caching/memory_caching" }
|
||||
redis_common = { path = "../../../lib/redis_common" }
|
||||
reusable_types = { path = "../../../_types/reusable_types" }
|
||||
tokens = { path = "../../../_types/tokens" }
|
||||
|
||||
Reference in new issue
Block a user