bloomBUILD•SHIP•BLOOM
.md
High Performance

Caching

bloom_cache provides a unified, backend-agnostic server caching layer modeled on djangors-cache for expensive computations, database results, and entire HTTP responses.

Swappable Cache Backends

All backends implement the unified BloomCache interface (get<T>, set<T>, delete, clear, getOrSet<T>) with JSON serialization:

InMemoryCache

Bounded in-memory cache with true O(1) Least-Recently-Used (LRU) eviction and TTL checks.

DatabaseCache

SQL-backed cache storing entries in bloom_cache_entries via PostgreSQL or SQLite.

RedisCache

Distributed caching using package:redis driver with millisecond TTL precision.

lib/cache_example.dart
dart
// lib/cache_example.dart - Caching with BloomCache
import 'package:bloom_cache/bloom_cache.dart';

void main() async {
  // 1. Initialize In-Memory LRU Cache
  final cache = InMemoryCache(maxCapacity: 1000);

  // 2. getOrSet with Cache Stampede Protection
  // Concurrent callers await the same in-flight computation
  final stats = await cache.getOrSet<Map<String, dynamic>>(
    'dashboard:stats',
    () async {
      // Expensive DB query or external calculation
      return {'activeUsers': 420, 'updatedAt': DateTime.now().toIso8601String()};
    },
    ttl: const Duration(minutes: 5),
  );

  print('Active users: ${stats['activeUsers']}');
}

Cache Stampede Prevention (getOrSet)

getOrSet<T> deduplicates concurrent in-flight computations for the same key. When multiple concurrent requests miss the cache simultaneously, the computation function runs exactly once, and all callers receive the resolved result.

HTTP Response Caching Middleware

BloomCacheMiddleware caches complete GET responses. It automatically enforces safety rules:

  • Method Safety: Only GET requests are cached.
  • Cookie Protection: Responses containing Set-Cookie are never cached to prevent session leakage.
  • Dynamic Opt-Out: Handlers can bypass caching via x-bloom-no-cache: true or cache-control: no-store.
bin/server.dart
dart
// Response Caching Middleware
import 'package:bloom_framework/bloom_server.dart';
import 'package:bloom_cache/bloom_cache.dart';

void main() async {
  final router = BloomApiRouter();
  final cache = InMemoryCache(maxCapacity: 5000);

  // Cache GET responses for 5 minutes (auto-bypasses Set-Cookie & non-GETs)
  router.use(BloomCacheMiddleware(
    cache: cache,
    ttl: const Duration(minutes: 5),
    excludePaths: ['/api/auth', '/healthz'],
  ));

  await router.serve(port: 8080);
}