mod entry;
#[cfg(feature = "memory")]
mod memory_gc;
#[cfg(feature = "redis")]
mod redis_cluster;
pub use entry::StorageEntry;
#[cfg(feature = "memory")]
pub use memory_gc::{GcConfig, GcInterval, MemoryStorage};
#[cfg(feature = "redis")]
pub use redis_cluster::{RedisConfig, RedisStorage};
use std::future::Future;
use std::time::Duration;
use crate::error::Result;
pub trait Storage: Send + Sync + 'static {
fn get(&self, key: &str) -> impl Future<Output = Result<Option<StorageEntry>>> + Send;
fn set(
&self,
key: &str,
entry: StorageEntry,
ttl: Duration,
) -> impl Future<Output = Result<()>> + Send;
fn delete(&self, key: &str) -> impl Future<Output = Result<()>> + Send;
fn increment(
&self,
key: &str,
delta: u64,
window_start: u64,
ttl: Duration,
) -> impl Future<Output = Result<u64>> + Send;
fn execute_atomic<F, T>(
&self,
key: &str,
ttl: Duration,
operation: F,
) -> impl Future<Output = Result<T>> + Send
where
F: FnOnce(Option<StorageEntry>) -> (StorageEntry, T) + Send,
T: Send;
fn compare_and_swap(
&self,
key: &str,
expected: Option<&StorageEntry>,
new: StorageEntry,
ttl: Duration,
) -> impl Future<Output = Result<bool>> + Send;
}
impl<S: Storage + ?Sized> Storage for std::sync::Arc<S> {
async fn get(&self, key: &str) -> Result<Option<StorageEntry>> {
(**self).get(key).await
}
async fn set(&self, key: &str, entry: StorageEntry, ttl: Duration) -> Result<()> {
(**self).set(key, entry, ttl).await
}
async fn delete(&self, key: &str) -> Result<()> {
(**self).delete(key).await
}
async fn increment(
&self,
key: &str,
delta: u64,
window_start: u64,
ttl: Duration,
) -> Result<u64> {
(**self).increment(key, delta, window_start, ttl).await
}
async fn execute_atomic<F, T>(&self, key: &str, ttl: Duration, operation: F) -> Result<T>
where
F: FnOnce(Option<StorageEntry>) -> (StorageEntry, T) + Send,
T: Send,
{
(**self).execute_atomic(key, ttl, operation).await
}
async fn compare_and_swap(
&self,
key: &str,
expected: Option<&StorageEntry>,
new: StorageEntry,
ttl: Duration,
) -> Result<bool> {
(**self).compare_and_swap(key, expected, new, ttl).await
}
}
impl<S: Storage + ?Sized> Storage for Box<S> {
async fn get(&self, key: &str) -> Result<Option<StorageEntry>> {
(**self).get(key).await
}
async fn set(&self, key: &str, entry: StorageEntry, ttl: Duration) -> Result<()> {
(**self).set(key, entry, ttl).await
}
async fn delete(&self, key: &str) -> Result<()> {
(**self).delete(key).await
}
async fn increment(
&self,
key: &str,
delta: u64,
window_start: u64,
ttl: Duration,
) -> Result<u64> {
(**self).increment(key, delta, window_start, ttl).await
}
async fn execute_atomic<F, T>(&self, key: &str, ttl: Duration, operation: F) -> Result<T>
where
F: FnOnce(Option<StorageEntry>) -> (StorageEntry, T) + Send,
T: Send,
{
(**self).execute_atomic(key, ttl, operation).await
}
async fn compare_and_swap(
&self,
key: &str,
expected: Option<&StorageEntry>,
new: StorageEntry,
ttl: Duration,
) -> Result<bool> {
(**self).compare_and_swap(key, expected, new, ttl).await
}
}
pub fn current_timestamp_ms() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis() as u64
}