#[cfg(feature = "l1-moka")]
use super::CacheOps;
#[cfg(feature = "l1-moka")]
use crate::backend::l1::L1Backend;
#[cfg(feature = "l1-moka")]
use crate::error::Result;
#[cfg(feature = "l1-moka")]
use async_trait::async_trait;
#[cfg(feature = "l1-moka")]
use std::sync::Arc;
#[cfg(feature = "l1-moka")]
use tracing::instrument;
#[cfg(feature = "l1-moka")]
use crate::serialization::SerializerEnum;
#[cfg(feature = "l1-moka")]
use crate::metrics::GLOBAL_METRICS;
#[cfg(feature = "l1-moka")]
pub struct L1Client {
service_name: String,
l1: Arc<L1Backend>,
serializer: SerializerEnum,
}
#[cfg(feature = "l1-moka")]
impl L1Client {
pub fn new(service_name: String, l1: Arc<L1Backend>, serializer: SerializerEnum) -> Self {
Self {
service_name,
l1,
serializer,
}
}
}
#[cfg(feature = "l1-moka")]
#[async_trait]
impl CacheOps for L1Client {
fn serializer(&self) -> &SerializerEnum {
&self.serializer
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn into_any_arc(self: Arc<Self>) -> Arc<dyn std::any::Any + Send + Sync> {
self
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn get_bytes(&self, key: &str) -> Result<Option<Vec<u8>>> {
GLOBAL_METRICS.record_request(&self.service_name, "L1", "get", "attempt");
if let Some((bytes, _)) = self.l1.get_with_metadata(key).await? {
GLOBAL_METRICS.record_request(&self.service_name, "L1", "get", "hit");
return Ok(Some(bytes));
}
GLOBAL_METRICS.record_request(&self.service_name, "L1", "get", "miss");
Ok(None)
}
#[instrument(skip(self, value), level = "debug", fields(service = %self.service_name))]
async fn set_bytes(&self, key: &str, value: Vec<u8>, ttl: Option<u64>) -> Result<()> {
let start = std::time::Instant::now();
self.l1.set_bytes(key, value, ttl).await?;
let duration = start.elapsed().as_secs_f64();
GLOBAL_METRICS.record_duration(&self.service_name, "L1", "set", duration);
Ok(())
}
#[instrument(skip(self, value), level = "debug", fields(service = %self.service_name))]
async fn set_l1_bytes(&self, key: &str, value: Vec<u8>, ttl: Option<u64>) -> Result<()> {
self.set_bytes(key, value, ttl).await
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn get_l1_bytes(&self, key: &str) -> Result<Option<Vec<u8>>> {
self.get_bytes(key).await
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn get_l2_bytes(&self, _key: &str) -> Result<Option<Vec<u8>>> {
Ok(None)
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn delete(&self, key: &str) -> Result<()> {
self.l1.delete(key).await
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn clear_l1(&self) -> Result<()> {
self.l1.clear()?;
GLOBAL_METRICS.record_request(&self.service_name, "L1", "clear", "success");
Ok(())
}
}
#[cfg(feature = "l1-moka")]
#[cfg(feature = "ttl-control")]
#[async_trait::async_trait]
impl crate::client::ttl_control::TtlControl for L1Client {
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn get_l1_ttl(&self, key: &str) -> Result<Option<u64>> {
self.l1.ttl(key).await
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn get_l2_ttl(&self, _key: &str) -> Result<Option<u64>> {
Ok(None)
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn get_ttl(&self, key: &str) -> Result<Option<u64>> {
self.get_l1_ttl(key).await
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn refresh_l1_ttl(&self, key: &str, ttl: u64) -> Result<bool> {
self.l1.refresh_ttl(key, ttl).await
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn refresh_l2_ttl(&self, _key: &str, _ttl: u64) -> Result<bool> {
Ok(false)
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn refresh_ttl(&self, key: &str, ttl: u64) -> Result<bool> {
self.refresh_l1_ttl(key, ttl).await
}
#[instrument(skip(self), level = "debug", fields(service = %self.service_name))]
async fn touch(&self, key: &str) -> Result<bool> {
Ok(false)
}
}