use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
use async_trait::async_trait;
use crate::storage::{SaStorage, ScanPage, StorageResult};
pub struct CountingStorage {
inner: Arc<dyn SaStorage>,
get_count: AtomicUsize,
set_count: AtomicUsize,
delete_count: AtomicUsize,
}
impl std::fmt::Debug for CountingStorage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("CountingStorage { .. }")
}
}
impl CountingStorage {
pub fn new(inner: Arc<dyn SaStorage>) -> Self {
Self {
inner,
get_count: AtomicUsize::new(0),
set_count: AtomicUsize::new(0),
delete_count: AtomicUsize::new(0),
}
}
pub fn get_count(&self) -> usize {
self.get_count.load(Ordering::Relaxed)
}
pub fn set_count(&self) -> usize {
self.set_count.load(Ordering::Relaxed)
}
pub fn delete_count(&self) -> usize {
self.delete_count.load(Ordering::Relaxed)
}
pub fn reset_counts(&self) {
self.get_count.store(0, Ordering::Relaxed);
self.set_count.store(0, Ordering::Relaxed);
self.delete_count.store(0, Ordering::Relaxed);
}
pub fn inner(&self) -> &Arc<dyn SaStorage> {
&self.inner
}
}
#[async_trait]
impl SaStorage for CountingStorage {
async fn get(&self, key: &str) -> StorageResult<Option<String>> {
self.get_count.fetch_add(1, Ordering::Relaxed);
self.inner.get(key).await
}
async fn set(&self, key: &str, value: &str, ttl: Option<Duration>) -> StorageResult<()> {
self.set_count.fetch_add(1, Ordering::Relaxed);
self.inner.set(key, value, ttl).await
}
async fn delete(&self, key: &str) -> StorageResult<()> {
self.delete_count.fetch_add(1, Ordering::Relaxed);
self.inner.delete(key).await
}
async fn exists(&self, key: &str) -> StorageResult<bool> {
self.inner.exists(key).await
}
async fn expire(&self, key: &str, ttl: Duration) -> StorageResult<()> {
self.inner.expire(key, ttl).await
}
async fn ttl(&self, key: &str) -> StorageResult<Option<Duration>> {
self.inner.ttl(key).await
}
async fn clear(&self) -> StorageResult<()> {
self.inner.clear().await
}
async fn set_if_absent(
&self,
key: &str,
value: &str,
ttl: Option<Duration>,
) -> StorageResult<bool> {
self.inner.set_if_absent(key, value, ttl).await
}
async fn get_del(&self, key: &str) -> StorageResult<Option<String>> {
self.inner.get_del(key).await
}
async fn compare_and_swap(
&self,
key: &str,
expected: Option<&str>,
new_value: &str,
ttl: Option<Duration>,
) -> StorageResult<bool> {
self.inner
.compare_and_swap(key, expected, new_value, ttl)
.await
}
async fn compare_and_delete(&self, key: &str, expected: &str) -> StorageResult<bool> {
self.inner.compare_and_delete(key, expected).await
}
async fn list_push(
&self,
key: &str,
member: &str,
unique: bool,
ttl: Option<Duration>,
) -> StorageResult<usize> {
self.inner.list_push(key, member, unique, ttl).await
}
async fn list_remove(&self, key: &str, member: &str) -> StorageResult<bool> {
self.inner.list_remove(key, member).await
}
async fn list_range(
&self,
key: &str,
start: usize,
limit: Option<usize>,
) -> StorageResult<Vec<String>> {
self.inner.list_range(key, start, limit).await
}
async fn list_len(&self, key: &str) -> StorageResult<usize> {
self.inner.list_len(key).await
}
async fn scan(&self, pattern: &str, cursor: u64, limit: usize) -> StorageResult<ScanPage> {
self.inner.scan(pattern, cursor, limit).await
}
}