Caché

Es un Middleware que provee funcionalidad de caché.

El middleware de caché puede proporcionar una función de almacenamiento en caché para StatusCode, Headers y Body en Response. Para el contenido que se ha almacenado en caché, la próxima vez que procese la solicitud, el middleware de caché enviará directamente el contenido almacenado en caché en la memoria al cliente.

Tenga en cuenta que este complemento no almacenará en caché la Response cuyo body sea un ResBody::Stream. Si se aplica a una Response de este tipo, la caché no procesará estas solicitudes y no provocará errores.

Características Principales

  • El CacheIssuer proporciona una abstracción sobre las claves de caché asignadas. RequestIssuer es una implementación del mismo que define qué partes de la URL solicitada y la URL solicitada Method. También puedes definir tu propia lógica de generación de claves de caché. La clave de caché no tiene que ser un tipo de cadena, cualquier tipo que satisfaga las restricciones de Hash + Eq + Send + Sync + 'static también pueden ser usados como claves.

  • El CacheStore provee acceso a los datos. MokaStore está incorporado en moka-basado en la implementación del caché. También puedes definir tu propia implementación.

  • El Cache es una estructura que implementa el Handler, y hay un campo skipper dentro de él, que se puede especificar para omitir ciertas solicitudes que no necesitan almacenarse en caché. Por defecto, MethodSkipper pudiera ser usado para omitir todas las solicitudes excepto Method::GET.

    La implementación interna del código es:

    impl<S, I> Cache<S, I> {
      pub fn new(store: S, issuer: I) -> Self {
          let skipper = MethodSkipper::new().skip_all().skip_get(false);
          Cache {
              store,
              issuer,
              skipper: Box::new(skipper),
          }
      }
    }
    

Ejemplo

use std::time::Duration;

use salvo::cache::{Cache, MokaStore, RequestIssuer};
use salvo::prelude::*;
use salvo::writing::Text;
use time::OffsetDateTime;

#[handler]
async fn home() -> Text<&'static str> {
    Text::Html(HOME_HTML)
}
#[handler]
async fn short() -> String {
    format!(
        "Hello World, my birth time is {}",
        OffsetDateTime::now_utc()
    )
}
#[handler]
async fn long() -> String {
    format!(
        "Hello World, my birth time is {}",
        OffsetDateTime::now_utc()
    )
}

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().init();

    let short_cache = Cache::new(
        MokaStore::builder()
            .time_to_live(Duration::from_secs(5))
            .build(),
        RequestIssuer::default(),
    );
    let long_cache = Cache::new(
        MokaStore::builder()
            .time_to_live(Duration::from_secs(60))
            .build(),
        RequestIssuer::default(),
    );
    let router = Router::new()
        .get(home)
        .push(Router::with_path("short").hoop(short_cache).get(short))
        .push(Router::with_path("long").hoop(long_cache).get(long));
    let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}

static HOME_HTML: &str = r#"
<!DOCTYPE html>
<html>
    <head>
        <title>Cache Example</title>
    </head>
    <body>
        <h2>Cache Example</h2>
        <p>
            This examples shows how to use cache middleware. 
        </p>
        <p>
            <a href="/short" target="_blank">Cache 5 seconds</a>
        </p>
        <p>
            <a href="/long" target="_blank">Cache 1 minute</a>
        </p>
    </body>
</html>
"#;
[package]
name = "example-cache-simple"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
salvo = {workspace = true, features = ["cache"] }
tokio = { version = "1", features = ["macros"] }
time = "0.3"
tracing = "0.1"
tracing-subscriber = "0.3"