ppoppo-infra 0.1.0

Backend-agnostic infrastructure traits for caching, queuing, and messaging
Documentation
//! Backend-agnostic cache trait.

use async_trait::async_trait;

use crate::Result;

/// Key-value cache with TTL support.
///
/// Uses `serde_json::Value` at the boundary for dyn-compatibility.
/// See [`CacheExt`](crate::CacheExt) for typed convenience methods.
#[async_trait]
pub trait Cache: Send + Sync {
    /// Set a value with optional TTL in seconds.
    async fn set(
        &self,
        key: &str,
        value: &serde_json::Value,
        ttl_seconds: Option<i32>,
    ) -> Result<()>;

    /// Get a value if it exists and is not expired.
    async fn get(&self, key: &str) -> Result<Option<serde_json::Value>>;

    /// Delete a key. Returns true if key existed.
    async fn del(&self, key: &str) -> Result<bool>;

    /// Check if a key exists and is not expired.
    async fn exists(&self, key: &str) -> Result<bool>;

    /// Get remaining TTL in seconds.
    ///
    /// Returns `Ok(Some(seconds))` if TTL is set, `Ok(None)` if no TTL,
    /// or `Err(NotFound)` if key doesn't exist.
    async fn ttl(&self, key: &str) -> Result<Option<i32>>;

    /// Set multiple keys atomically.
    ///
    /// Each entry is (key, value, ttl_seconds).
    async fn mset(
        &self,
        entries: &[(&str, serde_json::Value, Option<i32>)],
    ) -> Result<usize>;

    /// Get multiple keys atomically.
    ///
    /// Returns (key, Option<value>) pairs preserving input order.
    async fn mget(&self, keys: &[&str]) -> Result<Vec<(String, Option<serde_json::Value>)>>;

    /// Delete multiple keys atomically. Returns count of deleted keys.
    async fn mdel(&self, keys: &[&str]) -> Result<usize>;

    /// Find keys matching a pattern (backend-specific syntax).
    async fn keys(&self, pattern: &str, limit: i32) -> Result<Vec<String>>;

    // cleanup()은 trait에 포함하지 않는다.
    // PG는 만료 행 수동 DELETE 필요 (PgCache::cleanup()),
    // KVRocks는 EXPIRE 명령으로 TTL 자동 만료.
    // 인프라 관심사를 domain 계약에서 분리하기 위함.
}