Skip to main content

Cache Manager

The cache manager is the main interface for working with cache in your application. It manages drivers, handles configuration, and provides a unified API for all cache operations.

import { cache } from "@warlock.js/cache";

What is the Cache Manager?

The cache manager acts as a proxy to your cache drivers. It:

  • Manages multiple drivers and allows switching between them
  • Provides a consistent API regardless of which driver you're using
  • Handles configuration and initialization
  • Implements all Cache Driver methods

Setup

Before using the cache, configure and initialize it:

src/main.ts
import { cache } from "@warlock.js/cache";
import cacheConfigurations from "./config/cache";

// Set configurations
cache.setCacheConfigurations(cacheConfigurations);

// Initialize (connects to the default driver)
await cache.init();
Important

@warlock.js/cache requires manual setup. Unlike the Warlock framework where initialization is automatic, you must call setCacheConfigurations() and init() before using any cache operations.

danger

Always initialize at application startup. Using cache methods before init() will throw errors.

Basic Operations

The cache manager provides core cache operations that work with all drivers. All examples use the CACHE_FOR enum for TTL values to make code more readable.

Set

Store a value in cache:

import { cache, CACHE_FOR } from "@warlock.js/cache";

// Use dot notation for keys
await cache.set("user.1", { name: "John" }, CACHE_FOR.ONE_HOUR);
await cache.set("posts.123.comments", comments, CACHE_FOR.HALF_HOUR);

If TTL is omitted, the driver's default TTL is used, or the value is stored forever.

Get

Retrieve a value:

const user = await cache.get("user.1"); // Returns null if not found

Remove

Delete a specific key:

await cache.remove("user.1");

Flush

Clear the entire cache:

await cache.flush();

Has

Check if a key exists without fetching:

const exists = await cache.has("user.1");
tip

Use has() instead of get() !== null when you only need to check existence.

Pull

Get and remove in one operation:

const job = await cache.pull("job.queue.next");

Forever

Store without expiration:

await cache.forever("app.config", { version: "1.0.0" });
// Manually remove when needed
await cache.remove("app.config");

Remember (Get or Compute)

The remember() method gets a value from cache, or if it doesn't exist, executes a callback to generate it, caches the result, and returns it. It also prevents cache stampedes - if multiple requests try to generate the same value simultaneously, only the first one executes the callback.

import { cache, CACHE_FOR } from "@warlock.js/cache";

// Get from cache, or compute and cache if missing
const posts = await cache.remember("posts.popular", CACHE_FOR.ONE_HOUR, async () => {
return await db.query("SELECT * FROM posts ORDER BY views DESC LIMIT 10");
});

set() vs remember()

MethodWhen to UseBehavior
set()When you already have the valueSimply stores the value in cache
remember()When value needs to be computed on cache missGets from cache OR executes callback to generate, then caches

Use set() when:

const user = await db.users.findById(1);
await cache.set("user.1", user, CACHE_FOR.ONE_HOUR); // You have the value

Use remember() when:

// Let the cache handle getting/computing for you
const user = await cache.remember("user.1", CACHE_FOR.ONE_HOUR, async () => {
return await db.users.findById(1); // Only called if cache miss
});
tip

Always use remember() for expensive operations (database queries, API calls, computations) to prevent cache stampedes. See Cache Stampede Prevention for details.

Driver Management

Get Current Driver

const currentDriver = cache.currentDriver;

If no driver is active, the cache manager uses NullCacheDriver as fallback.

Switch Default Driver

Change the active driver:

await cache.use("redis");

The use() method is async because it loads the driver if not already loaded.

Get Specific Driver

Get a driver instance without changing the default:

const redisDriver = await cache.driver("redis");
const memoryDriver = await cache.driver("memory");

// Use specific driver directly
await redisDriver.set("key", "value");
await memoryDriver.set("temp", 123);

Register Custom Driver

Add drivers at runtime:

import { CustomCacheDriver } from "./CustomCacheDriver";

cache.registerDriver("custom", CustomCacheDriver);
await cache.use("custom");

Driver Options

Get Current Options

const options = cache.options;

Update Options

import { CACHE_FOR } from "@warlock.js/cache";

cache.setOptions({
globalPrefix: "newprefix",
ttl: CACHE_FOR.ONE_HOUR * 2, // 2 hours
});

Global Prefix

All built-in drivers support a globalPrefix option to avoid key conflicts, especially with shared storage like Redis. Think of it like a database name—it separates your keys from other applications.

Set it in your configuration or update at runtime with setOptions().

Namespaces

Namespaces help organize cache keys hierarchically using dot notation. See the dedicated Namespaces documentation for a complete guide on using namespaces effectively.

// Basic namespace usage
await cache.set("users.1", userData);
await cache.set("users.list", usersList);

// Remove all keys in a namespace
await cache.removeNamespace("users");

Advanced Features

The cache manager provides powerful features for complex caching scenarios. Each has dedicated documentation:

Cache Keys

Always use dot notation strings for keys:

  • "user.1"

  • "posts.123.comments"

  • "app.config.settings"

  • { id: 1 } (objects not recommended)

  • "user:1" (colons not recommended)

Recommended

Dot notation makes keys predictable, readable, and easier to debug. If you need to generate keys from complex data, see parseCacheKey utility.

Disconnect

Disconnect from the current driver:

await cache.disconnect();

Troubleshooting

  • Driver not found? Make sure it's listed in your config's drivers property.
  • Cache not working? Check your driver options and ensure init() was called.
  • Switching drivers has no effect? Use await cache.use("driverName") and ensure the driver is properly configured.
  • Methods throwing errors? Ensure you've called init() before using cache operations.