Skip to content
awekrx edited this page May 29, 2026 · 1 revision

cache

Import

import { cache } from '@dev-suite/decorators/cache'

Category

  • method

Use Case

Cache expensive method results by input arguments.

Replaces

  • Manual per-method Map + TTL logic
  • Repeated memoization wrappers

Example 1

Without decorator

class ProductService {
  private cache = new Map<string, { value: Product; exp: number }>();

  async getById(id: string) {
    const now = Date.now();
    const hit = this.cache.get(id);
    if (hit && hit.exp > now) return hit.value;

    const value = await this.repo.fetchById(id);
    this.cache.set(id, { value, exp: now + 30_000 });
    return value;
  }
}

With decorator

import { cache } from '@dev-suite/decorators/cache';

class ProductService {
  @cache({ ttlMs: 30_000, keyResolver: ([id]) => String(id) })
  async getById(id: string) {
    return this.repo.fetchById(id);
  }
}

Why better

  • Eliminates inline cache bookkeeping from business methods.
  • TTL and key strategy are explicit at declaration.

Example 2

Without decorator

class FxService {
  private byPair = new Map<string, number>();

  async rate(base: string, quote: string) {
    const key = base + ':' + quote;
    if (this.byPair.has(key)) return this.byPair.get(key)!;
    const value = await this.remote.rate(base, quote);
    this.byPair.set(key, value);
    return value;
  }
}

With decorator

import { cache } from '@dev-suite/decorators/cache';

class FxService {
  @cache({ keyResolver: ([base, quote]) => String(base) + ':' + String(quote) })
  async rate(base: string, quote: string) {
    return this.remote.rate(base, quote);
  }
}

Why better

  • Works for composite keys without hand-written cache code.
  • Behavior stays consistent across services.

Clone this wiki locally