diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9093b6..9567aee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,8 +2,22 @@ name: CI on: push: branches: [develop] + paths-ignore: + - '**.md' + - 'docs/**' + - 'tutorials/**' + - 'examples/**/README.md' + - 'LICENSE' + - '.gitignore' pull_request: branches: [develop, main] + paths-ignore: + - '**.md' + - 'docs/**' + - 'tutorials/**' + - 'examples/**/README.md' + - 'LICENSE' + - '.gitignore' workflow_dispatch: inputs: triggered-by: @@ -13,10 +27,5 @@ on: jobs: build: uses: fireflyframework/.github/.github/workflows/java-ci.yml@main - permissions: - packages: read - contents: read - actions: write with: java-version: '25' - secrets: inherit diff --git a/README.md b/README.md index bd5eb83..60ea8d7 100644 --- a/README.md +++ b/README.md @@ -1,764 +1,119 @@ -# Firefly Common Cache Library - -[![CI](https://github.com/fireflyframework/fireflyframework-cache/actions/workflows/ci.yml/badge.svg)](https://github.com/fireflyframework/fireflyframework-cache/actions/workflows/ci.yml) +# Firefly Framework - Cache -[![Java](https://img.shields.io/badge/Java-25-orange.svg)](https://www.oracle.com/java/) -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.2-green.svg)](https://spring.io/projects/spring-boot) +[![CI](https://github.com/fireflyframework/fireflyframework-cache/actions/workflows/ci.yml/badge.svg)](https://github.com/fireflyframework/fireflyframework-cache/actions/workflows/ci.yml) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) +[![Java](https://img.shields.io/badge/Java-21%2B-orange.svg)](https://openjdk.org) +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.x-green.svg)](https://spring.io/projects/spring-boot) -A unified, hexagonal caching library with pluggable providers (Caffeine, Redis, Hazelcast, JCache/JSR‑107) and optional Smart L1+L2 (Caffeine + distributed) caching, exposing a reactive API and clean, isolated multi‑cache support. +> Unified multi-provider caching library with Caffeine, Redis, Hazelcast, and JCache support for Spring Boot applications. --- -## πŸ“‹ Table of Contents +## Table of Contents -- [Features](#-features) -- [Quick Start](#-quick-start) - - [1. Add Dependency](#1-add-dependency) - - [2. Enable Caching](#2-enable-caching) - - [3. Configure Properties](#3-configure-properties) -- [Usage](#-usage) - - [Programmatic API](#programmatic-api) - - [Declarative Annotations](#declarative-annotations) - - [Cache-Specific Operations](#cache-specific-operations) -- [Multiple Cache Managers](#-multiple-cache-managers) - - [Why Multiple Caches](#why-multiple-caches) - - [Using CacheManagerFactory](#using-cachemanagerfactory) - - [Example: Multiple Caches in Webhooks](#example-multiple-caches-in-webhooks) - - [Enhanced Logging](#enhanced-logging) -- [Architecture](#-architecture) - - [Hexagonal Architecture](#hexagonal-architecture) - - [Key Components](#key-components) -- [Configuration](#-configuration) - - [Cache Types](#cache-types) - - [Caffeine Configuration](#caffeine-configuration) - - [Redis Configuration](#redis-configuration) - - [Smart (L1+L2) Configuration](#-smart-l1l2-cache) -- [Monitoring](#-monitoring) - - [Health Checks](#health-checks) - - [Metrics](#metrics) - - [Statistics API](#statistics-api) -- [Testing](#-testing) -- [Migration Guide](#-migration-guide) -- [Best Practices](#-best-practices) -- [Troubleshooting](#-troubleshooting) -- [Documentation](#-documentation) -- [Contributing](#-contributing) -- [License](#-license) +- [Overview](#overview) +- [Features](#features) +- [Requirements](#requirements) +- [Installation](#installation) +- [Quick Start](#quick-start) +- [Configuration](#configuration) +- [Documentation](#documentation) +- [Contributing](#contributing) +- [License](#license) ---- +## Overview -## ✨ Features +Firefly Framework Cache provides a standardized caching abstraction that supports multiple cache providers through a unified API. It features Spring Boot auto-configuration for seamless integration, custom annotations for declarative caching, and a smart cache adapter that can automatically select the optimal provider. -- **Zero Configuration**: Works out of the box with Spring Boot auto-configuration -- **Optional Dependencies**: Redis is completely optional - use Caffeine-only or add Redis when needed ([see guide](docs/OPTIONAL_DEPENDENCIES.md)) -- **Multiple Independent Caches**: Create multiple isolated cache managers with different configurations in the same application -- **Hexagonal Architecture**: Clean separation between business logic and infrastructure ([see architecture](docs/ARCHITECTURE.md)) -- **Multiple Cache Providers**: Caffeine (in-memory), Redis (distributed), Hazelcast (distributed in-memory grid), JCache/JSR‑107 (Ehcache/Infinispan) -- **Smart L1+L2 Cache**: Automatic two-level cache (L1 Caffeine + L2 distributed) with write‑through and optional backfill -- **Provider SPI**: Pluggable providers via ServiceLoader (Redis/Hazelcast/JCache/Caffeine) -- **Reactive API**: Non-blocking operations using Project Reactor -- **Auto-Configuration**: Automatic Spring Boot configuration with sensible defaults -- **Enhanced Logging**: Detailed cache creation tracking with provider information and caller detection -- **Proper Bean Matching**: Fixed architecture ensures `@ConditionalOnBean` works correctly -- **Health Monitoring**: Built-in health checks and metrics -- **Flexible Serialization**: JSON serialization with Jackson support -- **Declarative Caching**: Annotation-based caching support (programmatic API recommended) -- **TTL Support**: Time-to-live configuration for cache entries -- **Statistics**: Comprehensive cache statistics and monitoring +The library implements a provider-agnostic architecture with SPI-based provider discovery, supporting Caffeine for local caching, Redis for distributed caching, Hazelcast for clustered caching, and JCache (JSR-107) for standards compliance. It includes health indicators, serialization support, and comprehensive cache statistics. -## πŸš€ Quick Start +The `FireflyCacheManager` orchestrates cache operations across providers, while `CacheSelectionStrategy` allows automatic or manual provider selection based on cache characteristics. -### 1. Add Dependency +## Features -**For Caffeine-only (in-memory caching):** -```xml - - org.fireflyframework - fireflyframework-cache - 1.0.0-SNAPSHOT - -``` +- Multi-provider support: Caffeine, Redis, Hazelcast, JCache +- Custom annotations: `@Cacheable`, `@CachePut`, `@CacheEvict`, `@Caching`, `@EnableCaching` +- Smart cache adapter with automatic provider selection +- SPI-based provider discovery and factory pattern +- JSON cache serialization with pluggable serializers +- Cache health indicators for Spring Boot Actuator +- Cache statistics and metrics collection +- Spring Boot auto-configuration (`CacheAutoConfiguration`, `RedisCacheAutoConfiguration`) +- Configurable via `CacheProperties` with application.yml support + +## Requirements + +- Java 21+ +- Spring Boot 3.x +- Maven 3.9+ +- Redis (optional, for distributed caching) + +## Installation -**For Caffeine + Redis (distributed caching):** ```xml org.fireflyframework fireflyframework-cache - 1.0.0-SNAPSHOT - - - - - org.springframework.boot - spring-boot-starter-data-redis - - - io.lettuce - lettuce-core + 26.01.01 ``` -**That's it!** The library auto-configures with sensible defaults. No additional configuration required. - -> πŸ’‘ **Note:** Redis is completely optional. The library works perfectly with just Caffeine (in-memory cache). See [Optional Dependencies](docs/OPTIONAL_DEPENDENCIES.md) for details. - -### 2. (Optional) Configure Properties - -Customize the cache behavior via `application.yml`: - -```yaml -firefly: - cache: - enabled: true - # AUTO prefers REDIS > HAZELCAST > JCACHE > CAFFEINE - default-cache-type: AUTO - metrics-enabled: true - health-enabled: true - - # Smart L1+L2 (L1 Caffeine + L2 distributed) - smart: - enabled: true - backfill-l1-on-read: true - - # Caffeine configuration (L1 and/or standalone) - caffeine: - cache-name: default - enabled: true - key-prefix: "firefly:cache" # Prefix for all cache keys - maximum-size: 1000 - expire-after-write: PT1H - record-stats: true - - # Redis configuration (L2) - redis: - cache-name: default - enabled: true - host: localhost - port: 6379 - database: 0 - key-prefix: "firefly:cache" -``` - -Optional providers: -- Hazelcast: add `spring-boot-starter-hazelcast` (or a `HazelcastInstance` bean); set `default-cache-type: HAZELCAST` or `AUTO`. -- JCache: provide a `javax.cache.CacheManager` or `jakarta.cache.CacheManager` (e.g., Ehcache/Infinispan); set `default-cache-type: JCACHE` or `AUTO`. - -## πŸ’» Usage - -### Programmatic API (Recommended) - -The `FireflyCacheManager` implements the `CacheAdapter` interface directly, providing a simple and intuitive API: +## Quick Start ```java -@Service -public class UserService { - - @Autowired - private FireflyCacheManager cacheManager; - - public Mono getUser(String userId) { - // Simple, direct API - no need to select cache - return cacheManager.get(userId, User.class) - .flatMap(cached -> { - if (cached.isPresent()) { - return Mono.just(cached.get()); - } - return loadUserFromDatabase(userId) - .flatMap(user -> cacheManager.put(userId, user, Duration.ofMinutes(30)) - .thenReturn(user)); - }); - } +import org.fireflyframework.cache.annotation.Cacheable; +import org.fireflyframework.cache.annotation.CacheEvict; - public Mono invalidateUser(String userId) { - return cacheManager.evict(userId).then(); - } - - public Mono clearAllUsers() { - return cacheManager.clear(); - } - - private Mono loadUserFromDatabase(String userId) { - // Implementation details - return Mono.empty(); - } -} -``` - -### Declarative Annotations - -> **Note**: Annotation support (@Cacheable, @CacheEvict, @CachePut) is defined but aspect implementation is not yet complete. Use the programmatic API for production use. - -```java @Service public class ProductService { - @Cacheable(value = "products", key = "#productId", ttl = "PT2H") - public Mono getProduct(String productId) { - return productRepository.findById(productId); + @Cacheable(cacheName = "products", key = "#id") + public Mono findById(String id) { + return productRepository.findById(id); } - @CacheEvict(value = "products", key = "#product.id") - public Mono updateProduct(Product product) { - return productRepository.save(product); - } - - @CachePut(value = "products", key = "#result.id") - public Mono createProduct(Product product) { - return productRepository.save(product); - } -} -``` - -### Advanced Cache Operations - -```java -@Component -public class CacheOperations { - - @Autowired - private FireflyCacheManager cacheManager; - - public void performOperations() { - // Basic operations - cacheManager.put("key1", "value1").subscribe(); - cacheManager.get("key1").subscribe(value -> log.info("Value: {}", value)); - - // With TTL - cacheManager.put("key2", "value2", Duration.ofMinutes(10)).subscribe(); - - // Conditional put (only if key doesn't exist) - cacheManager.putIfAbsent("key3", "value3", Duration.ofMinutes(10)) - .doOnNext(wasInserted -> { - if (wasInserted) { - log.info("Value was inserted"); - } else { - log.info("Key already existed"); - } - }) - .subscribe(); - - // Check existence - cacheManager.exists("key1") - .doOnNext(exists -> log.info("Key exists: {}", exists)) - .subscribe(); - - // Evict a key - cacheManager.evict("key1") - .doOnNext(removed -> log.info("Key removed: {}", removed)) - .subscribe(); - - // Clear entire cache - cacheManager.clear() - .doOnSuccess(v -> log.info("Cache cleared")) - .subscribe(); - } -} -``` - -## πŸ”€ Multiple Cache Managers - -### Why Multiple Caches? - -In complex microservices, you often need **multiple independent caches** with different configurations: - -- **HTTP Idempotency Cache**: Short TTL (24 hours), stores request deduplication data -- **Webhook Event Cache**: Long TTL (7 days), tracks processed events -- **Business Rules Cache**: Medium TTL (4 hours), caches configuration data -- **Default Application Cache**: General purpose caching - -**Problem**: Using a single cache manager causes **key collisions** and **configuration conflicts**. - -**Solution**: `CacheManagerFactory` creates **isolated cache managers**, each with: -- βœ… Independent key prefixes (no collisions) -- βœ… Different TTLs per use case -- βœ… Separate provider configurations (Redis vs Caffeine) -- βœ… Isolated failure domains - -### Using CacheManagerFactory - -The `CacheManagerFactory` is automatically configured and available for injection: - -```java -@Configuration -public class MyCacheConfiguration { - - @Bean("businessRulesCacheManager") - public FireflyCacheManager businessRulesCacheManager( - CacheManagerFactory factory) { - - return factory.createCacheManager( - "business-rules", // Cache name - CacheType.REDIS, // Preferred type - "firefly:business:rules", // Key prefix (isolated namespace) - Duration.ofHours(4), // TTL - "Business Rules Cache - Caches product rules and configurations", - "MyApplication.MyCacheConfiguration" // Caller (optional) - ); - } - - @Bean - public MyService myService( - @Qualifier("businessRulesCacheManager") FireflyCacheManager cacheManager) { - return new MyService(cacheManager); + @CacheEvict(cacheName = "products", key = "#id") + public Mono evict(String id) { + return Mono.empty(); } } ``` -### Example: Multiple Caches in Webhooks - -The `common-platform-webhooks-mgmt` microservice demonstrates using multiple isolated caches: - -``` -Webhook Microservice -β”œβ”€β”€ httpIdempotencyCacheManager -β”‚ β”œβ”€β”€ Provider: Redis (primary) β†’ Caffeine (fallback) -β”‚ β”œβ”€β”€ Prefix: "firefly:http:idempotency" -β”‚ β”œβ”€β”€ TTL: 24 hours -β”‚ β”œβ”€β”€ Purpose: Prevent duplicate HTTP requests -β”‚ └── Auto-configured by fireflyframework-web -β”‚ -β”œβ”€β”€ webhookIdempotencyCacheManager -β”‚ β”œβ”€β”€ Provider: Redis (primary) β†’ Caffeine (fallback) -β”‚ β”œβ”€β”€ Prefix: "firefly:webhooks:idempotency" -β”‚ β”œβ”€β”€ TTL: 7 days -β”‚ β”œβ”€β”€ Purpose: Track processed webhook events -β”‚ └── Auto-configured by webhooks-processor -β”‚ -└── defaultCacheManager (@Primary) - β”œβ”€β”€ Provider: Caffeine or Redis - β”œβ”€β”€ Prefix: "firefly:cache:default" - β”œβ”€β”€ TTL: 1 hour - └── Purpose: General application caching -``` - -**Keys in Redis** (no collisions): -``` -firefly:http:idempotency::idempotency:POST:/api/webhooks:abc123 -firefly:webhooks:idempotency:webhook:processing:550e8400-e29b-41d4-a716-446655440000 -firefly:webhooks:idempotency:webhook:processed:550e8400-e29b-41d4-a716-446655440000 -firefly:cache:default:user:session:xyz789 -``` - -### Enhanced Logging - -The library provides **detailed logging** when creating cache managers: - -``` -╔═══════════════════════════════════════════════════════════════════════════ -β•‘ CREATING NEW CACHE MANAGER -╠═══════════════════════════════════════════════════════════════════════════ -β•‘ Cache Name : webhook-idempotency -β•‘ Description : Webhook Event Idempotency Cache - Ensures webhook events are processed exactly once (TTL: 7 days) -β•‘ Requested By : webhooks-processor.WebhookIdempotencyAutoConfiguration -β•‘ Preferred Type : REDIS -β•‘ Key Prefix : firefly:webhooks:idempotency -β•‘ Default TTL : PT168H -β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• -β–Ά Creating Redis cache as PRIMARY provider... - βœ“ Redis cache created successfully -β–Ά Creating Caffeine cache as FALLBACK provider... - βœ“ Caffeine fallback created successfully - -╔═══════════════════════════════════════════════════════════════════════════ -β•‘ CACHE MANAGER CREATED SUCCESSFULLY -╠═══════════════════════════════════════════════════════════════════════════ -β•‘ Primary Provider : REDIS (webhook-idempotency) -β•‘ Fallback Provider: CAFFEINE (webhook-idempotency) -β•‘ Ready for use by : webhooks-processor.WebhookIdempotencyAutoConfiguration -β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• -``` - -**Benefits of enhanced logging:** -- πŸ” **Tracking**: Know exactly who requested each cache -- πŸ“ **Documentation**: Description explains purpose -- πŸ› **Debugging**: Identify misconfigured caches quickly -- πŸ”§ **Provider Info**: See which provider (Redis/Caffeine) is being used -- ⚠️ **Warnings**: Immediate feedback when Redis is unavailable - -## 🧠 Smart (L1+L2) Cache - -- When a distributed provider is available and Caffeine is enabled, the factory creates a SmartCache (L1 Caffeine + L2 provider) automatically (write‑through strategy). -- Reads hit L1; on L1 miss, the value is read from L2 and optionally backfilled into L1; writes update both layers. -- Benefits: low latency, fewer network calls, consistent keys, and safe isolation per cache name/prefix. - -## πŸ—οΈ Architecture - -### Overview - -The library follows **hexagonal architecture** principles with a simplified design where `FireflyCacheManager` **IS** the cache itself, not a manager of multiple caches. - -#### Key Design Principles - -1. **Single Cache Instance**: One cache configuration per application (not multiple registered caches) -2. **Direct API**: `FireflyCacheManager` implements `CacheAdapter` directly for simple usage -3. **Automatic Fallback / Smart L1+L2**: Built-in support for primary/fallback and optional SMART L1+L2 composition -4. **Consistent Key Format**: All providers use `keyPrefix:cacheName:key` format - -#### Architecture Diagram - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Application Layer β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ FireflyCacheManager (implements β”‚ β”‚ -β”‚ β”‚ CacheAdapter) β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β€’ Direct cache operations (get, put, evict, etc.) β”‚ β”‚ -β”‚ β”‚ β€’ Automatic fallback support β”‚ β”‚ -β”‚ β”‚ β€’ Health monitoring & statistics β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β–Ό β–Ό β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ CacheAdapter (Port) β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β–Ό β–Ό β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Caffeine β”‚ β”‚ Redis β”‚ β”‚ NoOp β”‚ -β”‚ Adapter β”‚ β”‚ Adapter β”‚ β”‚ Adapter β”‚ -β”‚ (In-Memory) β”‚ β”‚(Distributed) β”‚ β”‚ (Fallback) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -### Key Components - -#### Public API -- **FireflyCacheManager**: Main cache interface - implements `CacheAdapter` directly - - Provides all cache operations (get, put, evict, clear, etc.) - - Supports automatic fallback (e.g., Redis β†’ Caffeine) - - Single instance per application - -#### Internal Components (Ports & Adapters) -- **CacheAdapter**: Port interface defining reactive cache operations -- **CaffeineCacheAdapter**: High-performance in-memory cache implementation -- **RedisCacheAdapter**: Distributed cache implementation (optional) -- **CacheSerializer**: JSON serialization with Jackson -- **Health & Metrics**: Built-in monitoring and observability - -#### Key Format -Both Caffeine and Redis use consistent key formatting: -- Format: `keyPrefix:cacheName:key` -- Example: `firefly:cache:default:user:123` -- Configurable via `key-prefix` property - -## βš™οΈ Configuration - -### Cache Types - -- `CAFFEINE`: High-performance in-memory cache (always available) -- `REDIS`: Distributed cache with persistence (requires Redis dependencies) -- `AUTO`: Automatically selects Redis if available, otherwise Caffeine - -### Caffeine Configuration +## Configuration ```yaml firefly: cache: + provider: caffeine # caffeine, redis, hazelcast, jcache caffeine: - cache-name: default # Name of the cache - enabled: true # Enable/disable Caffeine - key-prefix: "firefly:cache" # Prefix for all keys (format: prefix:cacheName:key) - maximum-size: 10000 # Maximum number of entries - expire-after-write: PT1H # Expire after write duration - expire-after-access: PT30M # Expire after access duration - refresh-after-write: PT45M # Refresh after write duration - record-stats: true # Enable statistics - weak-keys: false # Use weak references for keys - weak-values: false # Use weak references for values - soft-values: false # Use soft references for values -``` - -### Redis Configuration - -```yaml -firefly: - cache: + maximum-size: 10000 + expire-after-write: 5m redis: - cache-name: default # Name of the cache - enabled: true # Enable/disable Redis - host: localhost # Redis server host - port: 6379 # Redis server port - database: 0 # Redis database number - password: secret # Optional password - username: user # Optional username (Redis 6+) - connection-timeout: PT10S # Connection timeout - command-timeout: PT5S # Command timeout - key-prefix: "firefly:cache" # Prefix for all keys (format: prefix:cacheName:key) - default-ttl: PT30M # Optional default TTL for entries - ssl: false # Enable SSL/TLS - max-pool-size: 8 # Maximum connection pool size - min-pool-size: 0 # Minimum connection pool size -``` - -## πŸ“Š Monitoring - -### Health Checks - -The library provides health indicators for Spring Boot Actuator: - -```bash -# Check cache health -GET /actuator/health/cache - -# Response -{ - "status": "UP", - "details": { - "totalCaches": 2, - "healthyCaches": 2, - "unhealthyCaches": 0, - "caches": { - "default": { - "type": "caffeine", - "status": "UP", - "available": true, - "configured": true, - "responseTimeMs": 2 - } - } - } -} -``` - -### Metrics - -Cache metrics are exposed for monitoring: - -- Request count -- Hit/miss ratios -- Cache size -- Response times -- Error rates - -### Statistics API - -```java -// Get statistics for all caches -cacheManager.getStats() - .doOnNext(stats -> { - log.info("Cache: {} - Hits: {}, Misses: {}, Hit Rate: {}%", - stats.getCacheName(), - stats.getHitCount(), - stats.getMissCount(), - stats.getHitRate()); - }) - .subscribe(); -``` - -## πŸ§ͺ Testing - -### Test Configuration - -```yaml -# application-test.yml -firefly: - cache: - enabled: true - default-cache-type: caffeine # Use Caffeine for tests - caffeine: - default: - maximum-size: 100 - expire-after-write: PT1M -``` - -### Integration Tests - -```java -@SpringBootTest -@TestPropertySource(locations = "classpath:application-test.yml") -class CacheIntegrationTest { - - @Autowired - private FireflyCacheManager cacheManager; - - @Test - void shouldCacheAndRetrieveValues() { - StepVerifier.create(cacheManager.put("key1", "value1")) - .verifyComplete(); - - StepVerifier.create(cacheManager.get("key1")) - .assertNext(result -> { - assertThat(result).isPresent(); - assertThat(result.get()).isEqualTo("value1"); - }) - .verifyComplete(); - } -} -``` - -## πŸ”„ Migration Guide - -### Using FireflyCacheManager in Other Libraries - -The library is designed to be used as a dependency in other Firefly libraries (e.g., `fireflyframework-cqrs`). - -#### Correct Bean Matching - -```java -import org.fireflyframework.cache.manager.FireflyCacheManager; - -@Configuration -public class MyConfiguration { - - @Bean - @ConditionalOnBean(FireflyCacheManager.class) - public MyService myService(FireflyCacheManager cacheManager) { - return new MyService(cacheManager); - } -} -``` - -#### Using the Cache - -```java -@Service -public class MyService { - - private final FireflyCacheManager cacheManager; - - public MyService(FireflyCacheManager cacheManager) { - this.cacheManager = cacheManager; - } - - public Mono getUser(String userId) { - // Direct API - no need to select cache - return cacheManager.get(userId, User.class) - .flatMap(cached -> { - if (cached.isPresent()) { - return Mono.just(cached.get()); - } - return loadUser(userId) - .flatMap(user -> cacheManager.put(userId, user) - .thenReturn(user)); - }); - } -} -``` - -### Configuration Migration - -**Old (multiple caches - no longer supported):** -```yaml -firefly: - cache: - default-cache-name: my-cache - caffeine: - default: - maximum-size: 1000 - cache1: - maximum-size: 500 -``` - -**New (single cache):** -```yaml -firefly: - cache: - default-cache-type: REDIS # or CAFFEINE or AUTO - caffeine: - cache-name: default - key-prefix: "firefly:cache" - maximum-size: 1000 + host: localhost + port: 6379 + ttl: 10m ``` -### From Spring Cache - -If you're migrating from Spring's `@Cacheable`: - -1. Replace Spring cache annotations with programmatic API (recommended) -2. Update configuration from `spring.cache.*` to `firefly.cache.*` -3. Use reactive return types (`Mono`/`Flux`) - -### Performance Considerations - -- **Caffeine**: Best for high-frequency, low-latency access patterns -- **Redis**: Better for distributed applications and large datasets -- **Serialization**: JSON is human-readable but may be slower than binary formats -- **TTL**: Use appropriate TTL values to balance freshness and performance - -## πŸ’‘ Best Practices - -1. **Choose the right cache type**: - - Use Caffeine for local, high-speed caching - - Use Redis for distributed caching and persistence - - Use AUTO for automatic selection - -2. **Set appropriate TTL values**: - - Short TTL for frequently changing data - - Long TTL for stable reference data - -3. **Monitor cache performance**: - - Watch hit/miss ratios - - Monitor memory usage - - Track response times - -4. **Handle cache failures gracefully**: - - Always provide fallback mechanisms - - Log cache errors appropriately - - Consider circuit breaker patterns - -5. **Use meaningful cache keys**: - - Include version information when needed - - Use consistent naming conventions - - Avoid key collisions +## Documentation -## πŸ”§ Troubleshooting +Additional documentation is available in the [docs/](docs/) directory: -### Common Issues +- [Quickstart](docs/QUICKSTART.md) +- [Architecture](docs/ARCHITECTURE.md) +- [Configuration](docs/CONFIGURATION.md) +- [Api Reference](docs/API_REFERENCE.md) +- [Auto Configuration](docs/AUTO_CONFIGURATION.md) +- [Examples](docs/EXAMPLES.md) +- [Monitoring](docs/MONITORING.md) +- [Optional Dependencies](docs/OPTIONAL_DEPENDENCIES.md) +- [Testing](docs/TESTING.md) -1. **Cache not working**: - - Verify `@EnableCaching` is present - - Check configuration properties - - Ensure cache adapters are available on classpath +## Contributing -2. **Redis connection issues**: - - Verify Redis server is running - - Check network connectivity - - Validate credentials +Contributions are welcome. Please read the [CONTRIBUTING.md](CONTRIBUTING.md) guide for details on our code of conduct, development process, and how to submit pull requests. -3. **Serialization errors**: - - Ensure objects are serializable - - Check Jackson configuration - - Consider custom serializers for complex types +## License -4. **Memory issues**: - - Adjust maximum cache size - - Set appropriate TTL values - - Monitor cache statistics - -### Enable Debug Logging - -```yaml -logging: - level: - org.fireflyframework.cache: DEBUG -``` - -## πŸ“š Documentation - -For more detailed information, please refer to the documentation in the `docs/` folder: - -- **[Quick Start Guide](docs/QUICKSTART.md)** - Get started quickly with step-by-step instructions -- **[Optional Dependencies](docs/OPTIONAL_DEPENDENCIES.md)** - Redis is optional - learn how it works ⭐ -- **[Auto-Configuration Guide](docs/AUTO_CONFIGURATION.md)** - Spring Boot auto-configuration details -- **[Architecture Guide](docs/ARCHITECTURE.md)** - Understand the hexagonal architecture and design patterns -- **[Configuration Reference](docs/CONFIGURATION.md)** - Complete configuration options and examples -- **[API Reference](docs/API_REFERENCE.md)** - Detailed API documentation -- **[Examples](docs/EXAMPLES.md)** - Practical examples and use cases -- **[Monitoring Guide](docs/MONITORING.md)** - Metrics, health checks, and observability -- **[Testing Guide](docs/TESTING.md)** - How to test code using the cache library - -## 🀝 Contributing - -Contributions are welcome! Please see our contributing guidelines and code of conduct. - -## πŸ“„ License +Copyright 2024-2026 Firefly Software Solutions Inc. Licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for details. - ---- - -**Made with ❀️ by the Firefly Team** \ No newline at end of file