Skip to content

Redis Workflow

A practical workflow for using RedisConfig and InMemoryRedisStore in NestForge for cache-oriented and key-value application behavior.

Use this workflow when your application needs:

  • response caching
  • simple key-value storage
  • a store abstraction behind cache policy logic

The current workspace support is centered on:

  • RedisConfig
  • InMemoryRedisStore
  • CacheStore abstractions from nestforge-data

If you want a concrete feature-level example, read Redis-Style Cache Feature.

src/
app_module.rs
main.rs
users/
cache/
mod.rs
users_cache_policy.rs
controllers/
mod.rs
users_controller.rs
dto/
mod.rs
user_dto.rs
services/
mod.rs
users_service.rs
mod.rs

Be explicit about the current state:

  • the workspace exposes Redis-style configuration and an in-memory store adapter
  • the clearest end-to-end workflow today is caching, not a full standalone Redis app transport
  • this path is best when Redis semantics support caching or simple store behavior

Read or implement the feature in this order:

  1. create src/users/cache/users_cache_policy.rs
  2. create src/users/services/users_service.rs
  3. create src/users/controllers/users_controller.rs
  4. wire src/users/mod.rs
  5. wire src/app_module.rs
  6. attach the cache interceptor in src/main.rs

The exact file layout is documented in Redis-Style Cache Feature.

For the current workspace state, the most reliable path is:

  1. use RedisConfig as configuration only
  2. use InMemoryRedisStore as the concrete provider
  3. keep cache behavior in the interceptor and policy
  4. keep controllers free of cache-specific logic

Use this in src/users/cache/users_cache_policy.rs:

#[derive(Default, Clone)]
pub struct UsersCachePolicy;
impl nestforge::CachePolicy for UsersCachePolicy {
type Store = nestforge::InMemoryRedisStore;
}

Use this in src/users/mod.rs:

pub mod cache;
pub mod controllers;
pub mod dto;
pub mod services;
use nestforge::{
register_provider, Container, ControllerDefinition, InMemoryRedisStore, Provider, RedisConfig,
};
use self::{controllers::UsersController, services::UsersService};
pub struct UsersModule;
impl nestforge::ModuleDefinition for UsersModule {
fn register(container: &Container) -> anyhow::Result<()> {
register_provider(
container,
Provider::value(RedisConfig::new("redis://127.0.0.1:6379")),
)?;
register_provider(container, Provider::value(InMemoryRedisStore::default()))?;
register_provider(container, Provider::value(UsersService))?;
Ok(())
}
fn controllers() -> Vec<axum::Router<Container>> {
vec![<UsersController as ControllerDefinition>::router()]
}
}

Use this in src/users/controllers/users_controller.rs:

use axum::Json;
use nestforge::{controller, routes, ApiResult, Inject, List};
use crate::users::{
dto::UserDto,
services::{UsersService, list_users},
};
#[controller("/users")]
pub struct UsersController;
#[routes]
impl UsersController {
#[nestforge::get("/")]
#[nestforge::version("1")]
async fn list(users: Inject<UsersService>) -> ApiResult<List<UserDto>> {
Ok(Json(list_users(users.as_ref())))
}
}

Attach the interceptor in src/main.rs:

mod app_module;
mod users;
use app_module::AppModule;
use nestforge::{CacheInterceptor, NestForgeFactory};
use users::cache::UsersCachePolicy;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
NestForgeFactory::<AppModule>::create()?
.with_global_prefix("api")
.use_interceptor::<CacheInterceptor<UsersCachePolicy>>()
.listen(3000)
.await
}

Direct store usage belongs in a service:

use nestforge::InMemoryRedisStore;
use nestforge_data::CacheStore;
pub async fn remember_users(store: &InMemoryRedisStore, payload: &str) -> anyhow::Result<()> {
store.set("users:list", payload, None).await?;
Ok(())
}
pub async fn read_users(store: &InMemoryRedisStore) -> anyhow::Result<Option<String>> {
Ok(store.get("users:list").await?)
}
  1. the store provider resolves from the container
  2. repeated GET requests are cached
  3. direct key-value store operations work in a service
  4. the controller stays cache-agnostic

InMemoryRedisStore does not currently support TTL behavior. If ttl_seconds is set, the in-memory adapter returns an error instead of simulating expiry.

For the cache-first implementation path, see Caching Workflow.