Skip to content

feat: add Caffeine cache adapter module#220

Open
vazarkevych wants to merge 1 commit into
mainfrom
feat/add-caffeine-cache-adapter
Open

feat: add Caffeine cache adapter module#220
vazarkevych wants to merge 1 commit into
mainfrom
feat/add-caffeine-cache-adapter

Conversation

@vazarkevych

Copy link
Copy Markdown
Collaborator

Add Caffeine cache adapter (growthbook-cache-caffeine)

Summary

Adds a new optional Gradle module, growthbook-cache-caffeine, that provides a Caffeine-backed implementation of the SDK's GbCacheManager. It gives applications a production-ready, high-performance in-process cache for feature payloads — with bounded size, expiry, and optional statistics — without falling back to filesystem persistence.

Design

  • Bounding by size or weight. The cache can be bounded either by entry count (maximumSize, default 1000) or by total payload weight in bytes (maximumWeight). Weight is the recommended bound for the GrowthBook feature cache, since it stores a single large JSON payload per endpoint — so entry-count limits don't meaningfully constrain memory. A Weigher measures each entry by the UTF-8 byte length of its payload; when maximumWeight is set it takes precedence over maximumSize.
  • Expiry. Optional expireAfterWrite and expireAfterAccess durations map onto Caffeine's eviction. Note that the SDK's reads (loadCache, getLastUpdatedMillis) count as accesses, so expireAfterAccess only expires entries that have been fully idle.
  • Storage format. Each entry is a CaffeineCacheEntry holding the payload and an updatedAt (epoch millis) timestamp, recorded from an injectable Clock. getLastUpdatedMillis() is backed by that timestamp, enabling the SDK's freshness-based refresh skipping.
  • Statistics. When enabled via recordStats(true), stats() returns an immutable CaffeineCacheStats snapshot (hits, misses, hit rate, evictions). This type deliberately does not leak Caffeine's CacheStats, so callers (e.g. an SDK diagnostics layer) can read cache health without taking on a Caffeine dependency.
  • Error handling. An absent key is a normal cache miss (null); genuine access failures are wrapped in FeatureCacheException with the offending key for context.
  • Testability. An injectable Ticker allows deterministic expiry tests, and cleanUp() forces pending size/weight eviction on demand (Caffeine evicts asynchronously by default).

Configuration (CaffeineCacheOptions)

  • maximumSize — entry-count bound (default 1000).
  • maximumWeight — total payload-byte bound; takes precedence over maximumSize.
  • expireAfterWrite / expireAfterAccess — optional eviction durations.
  • recordStats — enable statistics recording (default off).
  • clock / ticker — injectable for testing.

Usage

Options options = Options.builder()
        .apiHost("https://cdn.growthbook.io")
        .clientKey("sdk-abc123")
        .cacheMode(CacheMode.CUSTOM)
        .cacheManager(CaffeineGbCacheManager.builder()
                .maximumSize(1000)
                .expireAfterWrite(Duration.ofMinutes(30))
                .buildManager())
        .build();

GrowthBookClient gb = new GrowthBookClient(options);

Documentation

  • Adds a Caffeine cache adapter section to README.md with dependency coordinates and a GrowthBookClient usage example.

Testing

  • Unit tests (CaffeineGbCacheManagerTest) cover save/load, last-updated tracking, cache miss, clear, size- and weight-based eviction, expiry (via injected Ticker), and statistics.

Build / packaging

  • New module registered in settings.gradle.
  • Targets Java 8 (sourceCompatibility/targetCompatibility = 1.8).
  • Depends on com.github.ben-manes.caffeine:caffeine:2.9.3 (as implementation, so it is not leaked onto consumers' compile classpath).
  • Publishes sources and javadoc jars to GitHub Packages, consistent with the existing lib module.

Adds an optional growthbook-cache-caffeine Gradle module providing a
Caffeine-backed GbCacheManager implementation:

- CaffeineGbCacheManager with builder-configurable maximum size,
  expire-after-write TTL and stats recording.
- CaffeineCacheOptions, CaffeineCacheEntry and CaffeineCacheStats
  supporting types.
- README section documenting usage with GrowthBookClient options.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant