Skip to main content

Database Cache Driver

The Database Cache Driver stores cache data in your database, providing persistence and the ability to query cache data using your existing database infrastructure.

Features

  • Persistence: Cache survives application restarts
  • Queryable: Use database queries to inspect cache data
  • TTL Support: Automatic expiration handling
  • Namespace Support: Group related cache entries
  • Global Prefix: Avoid key collisions

Configuration

src/config/cache.ts
import { CacheConfigurations } from "@warlock.js/core";
import { CacheModel } from "./models/CacheModel"; // Your cache model

const cacheConfigurations: CacheConfigurations = {
default: "database",
drivers: {
database: DatabaseCacheDriver,
},
options: {
database: {
model: CacheModel,
globalPrefix: "myapp",
ttl: 3600, // 1 hour default
},
},
};

export default cacheConfigurations;

Cache Model

You need to create a model for storing cache data. Here's an example:

src/models/CacheModel.ts
import { Model } from "@warlock.js/cascade";

export class CacheModel extends Model {
/**
* Collection name
*/
public static collection = "cache";

/**
* Schema definition
*/
public static schema = {
key: String,
namespace: String,
data: Mixed,
ttl: Number,
expiresAt: Date,
};
}

Options

OptionTypeDefaultDescription
modelModel ClassRequiredThe model class for storing cache data
globalPrefixstring | FunctionundefinedGlobal prefix for all cache keys
ttlnumberInfinityDefault TTL in seconds

Model Configuration

{
model: CacheModel, // Required: Your cache model class
}

Global Prefix

{
globalPrefix: "myapp", // Static prefix
// OR
globalPrefix: () => `app-${environment()}`, // Dynamic prefix
}

TTL Configuration

{
ttl: 3600, // 1 hour default TTL
// OR
ttl: 60 * 60 * 24, // 24 hours
// OR
ttl: Infinity, // Never expire (default)
}

Usage

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

// Set a value
await cache.set("user:1", { name: "John", email: "john@example.com" }, 3600);

// Get a value
const user = await cache.get("user:1");

// Remove a value
await cache.remove("user:1");

// Clear namespace
await cache.removeNamespace("user");

// Flush all cache
await cache.flush();

Database Schema

The cache driver expects your cache model to have these fields:

FieldTypeDescription
keyStringThe cache key
namespaceStringThe namespace (first part of the key)
dataMixedThe cached data
ttlNumberTime to live in seconds
expiresAtDateWhen the cache expires

Advantages

  • Persistence: Cache survives application restarts
  • Queryable: Use database queries to inspect cache data
  • Consistent: Uses your existing database infrastructure
  • Backup: Cache data is backed up with your database
  • Monitoring: Easy to monitor cache usage through database queries

Disadvantages

  • Slower: Database operations are slower than in-memory or Redis
  • Resource Usage: Uses database connections and storage
  • Complexity: Requires setting up a cache model

When to Use

  • When you need persistence but don't want to set up Redis
  • When you want to query cache data
  • When you want cache data backed up with your database
  • For development environments where simplicity is preferred

Example: Querying Cache Data

import { CacheModel } from "./models/CacheModel";

// Get all expired cache entries
const expired = await CacheModel.where("expiresAt", "<", new Date()).get();

// Get cache entries by namespace
const userCache = await CacheModel.where("namespace", "user").get();

// Get cache statistics
const stats = await CacheModel.aggregate([
{ $group: { _id: "$namespace", count: { $sum: 1 } } }
]);