← All tasksNode.js · Middle

A cache with time to live (TTL)

Write createTtlCache({ ttlMs, now }) with get, set(key, value, ttl?), has, delete and size. An entry lives ttl milliseconds (ttlMs by default) from its last set; once now() >= expiresAt it has expired.

Expired entries are not returned and are removed when accessed, and size() counts only live ones. has must work for values 0, null or "" too. Time comes from now(), so the cache can be tested without waiting.

Tests (5)

  1. let t = 0;
    const cache = createTtlCache({ ttlMs: 1000, now: () => t });
    cache.set('a', 1);
    expect(cache.get('a')).toBe(1);
    t = 999;
    expect(cache.get('a')).toBe(1);
    t = 1000;
    expect(cache.get('a')).toBe(undefined);
  2. let t = 0;
    const cache = createTtlCache({ ttlMs: 1000, now: () => t });
    cache.set('short', 'x', 100);
    cache.set('long', 'y');
    t = 500;
    expect(cache.has('short')).toBe(false);
    expect(cache.has('long')).toBe(true);
  3. let t = 0;
    const cache = createTtlCache({ ttlMs: 1000, now: () => t });
    cache.set('a', 1);
    t = 800;
    cache.set('a', 2);
    t = 1500;
    expect(cache.get('a')).toBe(2);
  4. let t = 0;
    const cache = createTtlCache({ ttlMs: 100, now: () => t });
    cache.set('a', 1); cache.set('b', 2); cache.set('c', 3, 1000);
    expect(cache.size()).toBe(3);
    t = 200;
    expect(cache.size()).toBe(1);
  5. let t = 0;
    const cache = createTtlCache({ ttlMs: 1000, now: () => t });
    cache.set('zero', 0);
    cache.set('empty', null);
    expect(cache.has('zero')).toBe(true);
    expect(cache.has('empty')).toBe(true);
    expect(cache.has('missing')).toBe(false);
    expect(cache.delete('zero')).toBe(true);
    expect(cache.has('zero')).toBe(false);