Actix-Cache framework development moved to the Hitbox repository. Actix-Cache is not supported now.
Actix cache is a proxy actor and infrastructure for asynchronous and clear cache interaction for Actix actor and Actix-web frameworks.
- Async/Sync cache backend support.
- Dogpile effect prevention.
- Stale cache mechanics.
- Automatic cache key generation.
- Detailed Prometheus metrics out of the box.
At this time supported or planned next cache backend implementation:
- Redis backend (actix-cache-redis)
- In-memory backend
- redis - Enabled by default. Add support for redis backend.
- derive - Support for Cacheable trait derive macros.
- metrics - Support for Prometheus metrics.
Dependencies:
[dependencies]
actix-cache = "0.2"
Code:
First of all, you should derive Cacheable trait for your actix Message:
NOTE: Default cache key implementation based on serde_qs crate and have some restrictions.
use actix::prelude::*;
use actix_cache::Cacheable; // With features=["derive"]
use actix_derive::Message;
use serde::{Deserialize, Serialize};
struct Pong;
#[derive(Message, Cacheable, Serialize)]
#[rtype(result = "Result<Pong, ()>")]
struct Ping {
id: i32,
}
Or implement that trait manually:
use actix_cache::{Cacheable, CacheError};
struct Ping { id: i32 }
impl Cacheable for Ping {
fn cache_message_key(&self) -> Result<String, CacheError> {
Ok(format!("{}::{}", self.cache_key_prefix(), self.id))
}
fn cache_key_prefix(&self) -> String { "Ping".to_owned() }
}
Next step is to instantiate CacheActor with default backend:
use actix::prelude::*;
use actix_cache::{CacheError, Cache};
#[actix_rt::main]
async fn main() -> Result<(), CacheError> {
let cache = Cache::new()
.await?
.start();
Ok(())
}
And the last step is using cache in your code (actix-web handler for example). This full example and other examples you can see on github.com
use actix::prelude::*;
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use actix_cache::{Cache, Cacheable};
use serde::Serialize;
struct FibonacciActor;
impl Actor for FibonacciActor { type Context = Context<Self>; }
#[derive(Message, Cacheable, Serialize)]
#[rtype(result = "u64")]
struct GetNumber {
number: u8
}
impl Handler<GetNumber> for FibonacciActor {
type Result = <GetNumber as Message>::Result;
fn handle(&mut self, msg: GetNumber, _ctx: &mut Self::Context) -> Self::Result {
42
}
}
async fn index(
fib: web::Data<Addr<FibonacciActor>>,
cache: web::Data<Addr<Cache>>
) -> impl Responder {
let query = GetNumber { number: 40 };
let number = cache
.send(query.into_cache(&fib))
.await
.unwrap()
.unwrap();
HttpResponse::Ok().body(format!("Generate Fibonacci number {}", number))
}