quick_cache

quick_cache is a lightweight and high performance concurrent cache optimized for low cache overhead. The http-cache-quickcache implementation provides traditional buffered caching capabilities.

Getting Started

The quick_cache backend cache manager is provided by the http-cache-quickcache crate.

cargo add http-cache-quickcache

Basic Usage with Tower

The quickcache manager works excellently with Tower services:

#![allow(unused)]
fn main() {
use tower::{Service, ServiceExt};
use http::{Request, Response, StatusCode};
use http_body_util::Full;
use bytes::Bytes;
use http_cache_quickcache::QuickManager;
use std::convert::Infallible;

// Example Tower service that uses QuickManager for caching
#[derive(Clone)]
struct CachingService {
    cache_manager: QuickManager,
}

impl Service<Request<Full<Bytes>>> for CachingService {
    type Response = Response<Full<Bytes>>;
    type Error = Box<dyn std::error::Error + Send + Sync>;
    type Future = std::pin::Pin<Box<dyn std::future::Future<Output = Result<Self::Response, Self::Error>> + Send>>;

    fn poll_ready(&mut self, _cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), Self::Error>> {
        std::task::Poll::Ready(Ok(()))
    }

    fn call(&mut self, req: Request<Full<Bytes>>) -> Self::Future {
        let manager = self.cache_manager.clone();
        Box::pin(async move {
            // Cache logic using the manager would go here
            let response = Response::builder()
                .status(StatusCode::OK)
                .body(Full::new(Bytes::from("Hello from cached service!")))?;
            Ok(response)
        })
    }
}
}

Working with the manager directly

First construct your manager instance. This example will use the default cache configuration.

#![allow(unused)]
fn main() {
let manager = Arc::new(QuickManager::default());
}

You can also specify other configuration options. This uses the new methods on both QuickManager and quick_cache::sync::Cache to construct a cache with a maximum capacity of 100 items.

#![allow(unused)]
fn main() {
let manager = Arc::new(QuickManager::new(quick_cache::sync::Cache::new(100)));
}

Traditional Cache Operations

You can attempt to retrieve a record from the cache using the get method. This method accepts a &str as the cache key and returns an Result<Option<(HttpResponse, CachePolicy)>, BoxError>.

#![allow(unused)]
fn main() {
let response = manager.get("my-cache-key").await?;
}

You can store a record in the cache using the put method. This method accepts a String as the cache key, a HttpResponse as the response, and a CachePolicy as the policy object. It returns an Result<HttpResponse, BoxError>. The below example constructs the response and policy manually, normally this would be handled by the middleware.

#![allow(unused)]
fn main() {
let url = Url::parse("http://example.com")?;
let response = HttpResponse {
    body: TEST_BODY.to_vec(),
    headers: Default::default(),
    status: 200,
    url: url.clone(),
    version: HttpVersion::Http11,
};
let req = http::Request::get("http://example.com").body(())?;
let res = http::Response::builder()
    .status(200)
    .body(TEST_BODY.to_vec())?;
let policy = CachePolicy::new(&req, &res);
let response = manager.put("my-cache-key".into(), response, policy).await?;
}

You can remove a record from the cache using the delete method. This method accepts a &str as the cache key and returns an Result<(), BoxError>.

#![allow(unused)]
fn main() {
manager.delete("my-cache-key").await?;
}