### Setup Development Environment Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Install project dependencies using uv. ```bash uv sync --extra dev ``` -------------------------------- ### Install and Start Redis on Ubuntu/Debian Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Instructions for installing and starting the Redis server locally on Ubuntu or Debian-based systems using apt-get. ```bash sudo apt-get update sudo apt-get install redis-server sudo systemctl start redis-server ``` -------------------------------- ### Install and Start Redis on macOS using Homebrew Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Instructions for installing and starting the Redis server locally on macOS using Homebrew. ```bash brew install redis brew services start redis ``` -------------------------------- ### Flask Integration Example Source: https://github.com/dclobato/resilient-cache/blob/master/INSTALLATION_GUIDE.md Commands to run the provided Flask example application. ```bash # Ensure Valkey is running docker run -d -p 6379:6379 valkey/valkey:latest # Run the example uv run python examples/basic_usage.py ``` ```bash curl http://localhost:5000/users/1 curl http://localhost:5000/cache/stats curl http://localhost:5000/health ``` -------------------------------- ### Core Installation Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Install the core resilient-cache package using uv. ```bash uv add resilient-cache ``` -------------------------------- ### Full Installation (Flask + L1 + L2) Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Install the resilient-cache package with the 'full' extra, enabling Flask integration, L1 in-memory cache, and L2 distributed cache. ```bash uv add "resilient-cache[full]" ``` -------------------------------- ### Dependency Installation with uv Source: https://github.com/dclobato/resilient-cache/blob/master/INSTALLATION_GUIDE.md Commands to sync dependencies for various project configurations. ```bash cd resilient-cache ``` ```bash # Core install uv sync # Flask integration uv sync --extra flask # L1 support (cachetools) uv sync --extra l1 # L2 support (Redis/Valkey) uv sync --extra l2 # Full install (Flask + L1 + L2) uv sync --extra full # Development (pytest, mypy, etc) uv sync --extra dev ``` -------------------------------- ### Register Custom Backend at Runtime Source: https://github.com/dclobato/resilient-cache/blob/master/ROADMAP.md Implementation example showing how to define a factory function and register a custom L2 backend. ```python from resilient_cache.plugins import register_l2_backend from my_pkg.backends import MyL2Backend def factory(config, serializer, logger): return MyL2Backend(config, serializer, logger) register_l2_backend("my_l2", factory) ``` -------------------------------- ### Install with Flask Integration Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Install the resilient-cache package with the 'flask' extra for Flask integration. ```bash uv add "resilient-cache[flask]" ``` -------------------------------- ### Install with L2 (Redis/Valkey) Cache Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Install the resilient-cache package with the 'l2' extra to enable the distributed Redis/Valkey cache backend. ```bash uv add "resilient-cache[l2]" ``` -------------------------------- ### Install with L1 (In-Memory) Cache Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Install the resilient-cache package with the 'l1' extra to enable the in-memory cache backend. ```bash uv add "resilient-cache[l1]" ``` -------------------------------- ### List, Get, and Use Serializers Source: https://context7.com/dclobato/resilient-cache/llms.txt Demonstrates listing available serializers, retrieving specific serializer instances (JSON, Pickle), and using them for serialization/deserialization. ```python from resilient_cache import ( CacheSerializer, register_serializer, get_serializer, list_serializers, CacheService, CacheFactoryConfig, ) # List available serializers print(list_serializers()) # ['json', 'pickle'] # Use JSON serializer (safe, human-readable, but limited types) json_serializer = get_serializer("json") data = {"name": "Test", "count": 42} serialized = json_serializer.serialize(data) deserialized = json_serializer.deserialize(serialized) # Use Pickle serializer (supports any Python object) pickle_serializer = get_serializer("pickle") ``` -------------------------------- ### Consuming the Library in Other Projects Source: https://github.com/dclobato/resilient-cache/blob/master/INSTALLATION_GUIDE.md Installation and usage patterns for external projects. ```bash uv init uv add "resilient-cache[flask]" # With L1 + L2 uv add "resilient-cache[full]" ``` ```python from flask import Flask from resilient_cache import FlaskCacheService app = Flask(__name__) cache_service = FlaskCacheService() cache_service.init_app(app) my_cache = cache_service.create_cache( l2_key_prefix="my_module", l2_ttl=3600, l2_enabled=True, l1_enabled=True, l1_maxsize=1000, l1_ttl=60, ) ``` -------------------------------- ### Conventional Commit Examples Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Various examples of conventional commit messages. ```bash feat(parser): add array parsing support fix(ui): fix button alignment docs: update README with usage instructions refactor: improve data processing performance chore: update project dependencies feat!: send email on user registration BREAKING CHANGE: an email service is now required ``` -------------------------------- ### Cache Promotion Example Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Demonstrates how cache promotion works: an L2 hit automatically promotes the data to L1 for faster subsequent access. ```python value = cache.get("key") # L2 hit promotes to L1 value = cache.get("key") # L1 hit (< 1ms) ``` -------------------------------- ### Create Generated Images Cache Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Example setup for caching generated images, specifying a 'pickle' serializer and appropriate TTLs for both cache levels. ```python image_cache = cache_service.create_cache( l2_key_prefix="images", l2_ttl=604800, l2_enabled=True, l1_enabled=True, l1_maxsize=2000, l1_ttl=1800, serializer="pickle", ) ``` -------------------------------- ### Basic Cache Operations: Set, Get, Delete Source: https://context7.com/dclobato/resilient-cache/llms.txt Demonstrates fundamental cache interactions including write-through set, L1/L2 get with promotion, atomic set_if_not_exist, and delete operations. Ensure L1 and L2 are enabled for full functionality. ```python from resilient_cache import CacheService, CacheFactoryConfig config = CacheFactoryConfig(l2_host="localhost", l2_port=6379) cache_service = CacheService(config) cache = cache_service.create_cache( l2_key_prefix="myapp", l2_ttl=3600, l2_enabled=True, l1_enabled=True, l1_maxsize=100, l1_ttl=60, ) # SET - Write-through to L1 and L2 cache.set("session:abc123", { "user_id": 42, "created_at": "2024-01-15T10:30:00Z", "permissions": ["read", "write"] }) # GET - Searches L1, then L2 (with automatic promotion to L1) session = cache.get("session:abc123") if session is None: print("Cache miss - session not found") else: print(f"Session found for user {session['user_id']}") # Subsequent get will hit L1 (< 1ms latency) session = cache.get("session:abc123") # SET_IF_NOT_EXIST - Only sets if key doesn't exist (atomic in L2) cache.set_if_not_exist("lock:resource_1", {"locked_by": "worker_1"}) # DELETE - Removes from L2 first, then L1 cache.delete("session:abc123") # IS_ON_CACHE - Check existence without retrieving value if cache.is_on_cache("session:def456"): print("Session exists in cache") ``` -------------------------------- ### Start Valkey using Docker Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Run a Valkey (Redis-compatible) instance in a Docker container for integration testing. Ensure the container is stopped and removed when no longer needed. ```bash # Start Valkey (Redis-compatible) docker run -d -p 6379:6379 --name valkey valkey/valkey:latest # Run integration tests make test-integration # Stop Valkey when done docker stop valkey docker rm valkey ``` -------------------------------- ### Makefile Windows Installation Commands Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Commands to use with Makefile.windows for installing development dependencies, running tests, and checking the project on Windows systems. ```bash make -f Makefile.windows install-dev make -f Makefile.windows test make -f Makefile.windows check ``` -------------------------------- ### Non-Flask Cache Usage Source: https://github.com/dclobato/resilient-cache/blob/master/INSTALLATION_GUIDE.md Example of initializing and using the cache service directly. ```python from resilient_cache import CacheFactoryConfig, CacheService config = CacheFactoryConfig( l2_host="localhost", l2_port=6379, ) cache_service = CacheService(config) cache = cache_service.create_cache( l2_key_prefix="test", l2_ttl=300, l2_enabled=True, l1_enabled=True, l1_maxsize=100, l1_ttl=30, ) cache.set("key", "value") print(cache.get("key")) print(cache.get_stats()) ``` ```bash uv run python test_local.py ``` -------------------------------- ### Commit Message Example Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Example of a standard commit message following the project's style. ```text Add cache warming feature Implement cache warming to preload frequently accessed data during application startup. This reduces initial latency for users. ``` -------------------------------- ### Create Session Cache Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Example configuration for a session cache with specific L1 and L2 settings, including prefixes and TTLs. ```python session_cache = cache_service.create_cache( l2_key_prefix="session", l2_ttl=1800, l2_enabled=True, l1_enabled=True, l1_maxsize=500, l1_ttl=300, ) ``` -------------------------------- ### GitHub Actions Workflow for Integration Tests Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Example GitHub Actions workflow configuration to run integration tests. It sets up Valkey as a service and runs tests with specified environment variables. ```yaml jobs: test: runs-on: ubuntu-latest services: valkey: image: valkey/valkey:latest ports: - 6379:6379 steps: - uses: actions/checkout@v3 - name: Run tests env: VALKEY_HOST: localhost VALKEY_PORT: 6379 VALKEY_DB: 0 run: make test-all ``` -------------------------------- ### Implement Integration Test in Python Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Example of an integration test using CacheFactory to interact with a real Valkey/Redis instance. ```python import os from resilient_cache import CacheFactory, CacheFactoryConfig def test_redis_integration(): config = CacheFactoryConfig( l2_host=os.getenv("VALKEY_HOST", "localhost"), l2_port=int(os.getenv("VALKEY_PORT", "6379")), l2_db=int(os.getenv("VALKEY_DB", "0")), ) factory = CacheFactory(config) cache = factory.create_cache( l2_key_prefix="test", l2_ttl=60, l2_enabled=True, ) # Test operations cache.set("key", "value") assert cache.get("key") == "value" # Cleanup cache.clear() ``` -------------------------------- ### Creating and Using a Custom Cache Instance Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Create a custom cache instance with specific L1 and L2 configurations. This example demonstrates setting TTL, max size for L1, and enabling both cache levels. It also shows how to use the cache within a Flask route to fetch and store user data. ```python # Create L1 + L2 cache cache_service = get_cache_service() cache = cache_service.create_cache( l2_key_prefix="users", l2_ttl=3600, # 1 hour in L2 l2_enabled=True, l1_enabled=True, l1_maxsize=1000, # up to 1000 items in L1 l1_ttl=60, # 1 minute in L1 ) # Use the cache @app.route('/user/') def get_user(user_id): cache_key = f"user_{user_id}" user = cache.get(cache_key) if user is None: user = User.query.get(user_id) cache.set(cache_key, user) return user ``` -------------------------------- ### Manage Docker Compose Services Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Commands to start, run tests, and stop services defined in a docker-compose.yml file. Assumes a docker-compose.yml is present in the project root. ```bash # Start services docker-compose up -d # Run tests make test-integration # Stop services docker-compose down ``` -------------------------------- ### Selective Invalidation Example Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Shows how to selectively invalidate cache entries, specifically for user data after an update. ```python def update_user(user_id, new_data): user = User.query.get(user_id) user.update(new_data) db.session.commit() cache.delete(f"user_{user_id}") ``` -------------------------------- ### Basic Cache Operations Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Perform fundamental cache interactions like getting, setting, deleting, clearing, and checking for key existence. ```python value = cache.get("my_key") cache.set("my_key", {"data": "value"}) cache.delete("my_key") stats = cache.clear() exists = cache.is_on_cache("my_key") ``` -------------------------------- ### Unit Test Example: JSON Serialization Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md A Python unit test demonstrating the serialization and deserialization of data using a JsonSerializer. This test should be placed in the `tests/unit/` directory. ```python def test_serializer_json(): serializer = JsonSerializer() data = {"key": "value"} serialized = serializer.serialize(data) assert serializer.deserialize(serialized) == data ``` -------------------------------- ### Override Default Valkey/Redis Connection (Linux/macOS) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Set environment variables to customize Valkey/Redis connection details for integration tests. This example sets a custom host, port, and database. ```bash VALKEY_HOST=redis.example.com VALKEY_PORT=6380 VALKEY_DB=1 make test-integration ``` -------------------------------- ### Skeleton for a New L1 Cache Backend Source: https://github.com/dclobato/resilient-cache/blob/master/BACKEND_GUIDE.md Implement the CacheBackend interface for a new L1 cache. Requires defining methods for get, set, delete, and other cache operations. ```python from typing import Any, List, Optional from resilient_cache.backends.base import CacheBackend from resilient_cache.config import L1Config class MyL1Backend(CacheBackend): def __init__(self, config: L1Config): self.config = config def get(self, key: str) -> Any: ... def set(self, key: str, value: Any, ttl: Optional[int] = None) -> None: ... def set_if_not_exist(self, key: str, value: Any, ttl: Optional[int] = None) -> None: ... def delete(self, key: str) -> None: ... def clear(self) -> int: ... def exists(self, key: str) -> bool: ... def get_ttl(self, key: str) -> Optional[int]: ... def list_keys(self, prefix: Optional[str] = None) -> List[str]: ... def get_size(self) -> int: ... def get_stats(self) -> dict: ... ``` -------------------------------- ### Maintain Serializer Consistency Source: https://github.com/dclobato/resilient-cache/blob/master/src/resilient_cache/SERIALIZERS.md Ensure the same serializer is used for both setting and getting data to prevent deserialization failures. ```python # ❌ Errado - serializers diferentes cache1 = factory.create_cache(..., serializer="json") cache2 = factory.create_cache(..., serializer="pickle") cache1.set("key", value) cache2.get("key") # Vai falhar! # ✅ Correto - mesmo serializer cache1 = factory.create_cache(..., serializer="json") cache2 = factory.create_cache(..., serializer="json") ``` -------------------------------- ### Override Default Valkey/Redis Connection (Windows PowerShell) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Set environment variables in PowerShell to customize Valkey/Redis connection details for integration tests on Windows. This example sets a custom host, port, and database. ```powershell $env:VALKEY_HOST='redis.example.com' $env:VALKEY_PORT='6380' $env:VALKEY_DB='1' make -f Makefile.windows test-integration ``` -------------------------------- ### Advanced Cache Operations Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Access advanced cache functionalities including retrieving time-to-live, listing all keys, listing keys with a prefix, and getting cache statistics. ```python ttl = cache.get_ttl("my_key") keys = cache.list_keys() user_keys = cache.list_keys(prefix="user_") stats = cache.get_stats() ``` -------------------------------- ### Clone Repository Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Initial steps to clone the repository and navigate to the project directory. ```bash git clone https://github.com/your-user/resilient-cache.git cd resilient-cache ``` -------------------------------- ### Run All Tests (Linux/macOS) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Execute both unit and integration tests. Integration tests require a Valkey/Redis instance. ```bash make test-all ``` -------------------------------- ### Run Integration Tests (Windows) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Execute integration tests on Windows using the Windows Makefile. Requires a running Valkey/Redis instance. ```bash make -f Makefile.windows test-integration ``` -------------------------------- ### Initialize and use CacheService Source: https://context7.com/dclobato/resilient-cache/llms.txt Configures a framework-agnostic cache service with L1/L2 settings and circuit breaker parameters. ```python from resilient_cache import CacheService, CacheFactoryConfig # Initialize cache service with Redis/Valkey configuration config = CacheFactoryConfig( l2_host="localhost", l2_port=6379, l2_db=0, l2_password=None, serializer="pickle", circuit_breaker_enabled=True, circuit_breaker_threshold=5, circuit_breaker_timeout=60, ) cache_service = CacheService(config) # Create a cache for user data with L1 + L2 user_cache = cache_service.create_cache( l2_key_prefix="users", l2_ttl=3600, # 1 hour in L2 l2_enabled=True, l1_enabled=True, l1_maxsize=1000, # up to 1000 items in L1 l1_ttl=60, # 1 minute in L1 ) # Basic cache operations user_cache.set("user:1", {"id": 1, "name": "John Doe", "email": "john@example.com"}) user = user_cache.get("user:1") # Returns cached data or None print(f"Retrieved user: {user}") # Check cache statistics stats = cache_service.get_stats() print(f"Dependencies: {stats['dependencies']}") # Output: {'cachetools': True, 'redis': True} ``` -------------------------------- ### Project Versioning and Publishing Source: https://github.com/dclobato/resilient-cache/blob/master/INSTALLATION_GUIDE.md Steps for updating versions, tagging releases, and publishing to PyPI. ```python __version__ = "1.1.0" ``` ```bash git add . git commit -m "Release v1.1.0" git tag v1.1.0 git push origin main --tags ``` ```bash uv build uv publish ``` ```bash # In another environment uv init uv add "resilient-cache[flask]" # Test uv run python -c "from resilient_cache import FlaskCacheService; print('OK')" ``` -------------------------------- ### Run All Tests (Windows) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Execute both unit and integration tests on Windows using the Windows Makefile. Integration tests require a Valkey/Redis instance. ```bash make -f Makefile.windows test-all ``` -------------------------------- ### Run Integration Tests (Linux/macOS) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Execute integration tests which require a running Valkey/Redis instance. Default connection details are localhost:6379. ```bash make test-integration ``` -------------------------------- ### Run Unit Tests (Windows) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Execute unit tests on Windows using the Windows Makefile. This command does not require external services. ```bash make -f Makefile.windows test make -f Makefile.windows test-unit ``` -------------------------------- ### Framework-Agnostic Cache Service Configuration Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Configure and initialize a framework-agnostic cache service. Specify L2 connection details like host, port, and database. ```python from resilient_cache import CacheFactoryConfig, CacheService config = CacheFactoryConfig( l2_host="localhost", l2_port=6379, l2_db=0, ) cache_service = CacheService(config) ``` -------------------------------- ### Run Integration Test Coverage (Linux/macOS) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Generate code coverage reports for integration tests. Requires a running Valkey/Redis instance. ```bash make test-cov-integration ``` -------------------------------- ### Run Unit Tests (Linux/macOS) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Execute unit tests without external dependencies. This is the default test command. ```bash make test make test-unit ``` -------------------------------- ### Project Structure Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Overview of the repository file layout. ```text resilient-cache/ ├── src/ │ └── resilient_cache/ │ ├── __init__.py │ ├── app_cache.py │ ├── cache_service.py │ ├── cache_factory.py │ ├── two_level_cache.py │ ├── circuit_breaker.py │ ├── exceptions.py │ ├── config/ │ └── backends/ ├── tests/ │ ├── unit/ │ └── integration/ ├── examples/ └── docs/ ``` -------------------------------- ### Run Integration Test Coverage (Windows) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Generate code coverage reports for integration tests on Windows using the Windows Makefile. Requires a Valkey/Redis instance. ```bash make -f Makefile.windows test-cov-integration ``` -------------------------------- ### Run All Test Coverage (Linux/macOS) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Generate code coverage reports for all tests (unit and integration). Integration tests require a Valkey/Redis instance. ```bash make test-cov-all ``` -------------------------------- ### CacheFactoryConfig Initialization Source: https://context7.com/dclobato/resilient-cache/llms.txt Shows how to initialize CacheFactoryConfig with L2 connection details and custom logging. This configuration sets global defaults for cache creation. ```python from resilient_cache import CacheFactoryConfig, CacheService import logging # Create custom logger logger = logging.getLogger("myapp.cache") logger.setLevel(logging.DEBUG) ``` -------------------------------- ### Full CacheFactoryConfig Options Source: https://context7.com/dclobato/resilient-cache/llms.txt Configure L1/L2 backends, connection settings, serialization, and circuit breaker parameters for the cache service. ```python config = CacheFactoryConfig( # L2 (Redis/Valkey) connection settings l2_backend="redis", # "redis" or "valkey" l2_host="redis.example.com", l2_port=6379, l2_db=0, l2_password="secret123", l2_connect_timeout=5, # Connection timeout in seconds l2_socket_timeout=5, # Socket timeout in seconds # L1 (in-memory) settings l1_backend="ttl", # "ttl" (TTLCache) or "lru" (LRUCache) # Serialization serializer="pickle", # "pickle" or "json" # Circuit breaker settings circuit_breaker_enabled=True, circuit_breaker_threshold=5, # Failures before opening circuit circuit_breaker_timeout=60, # Seconds before attempting reset # Optional custom logger logger=logger, ) cache_service = CacheService(config) ``` -------------------------------- ### Run All Test Coverage (Windows) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Generate code coverage reports for all tests on Windows using the Windows Makefile. Integration tests require a Valkey/Redis instance. ```bash make -f Makefile.windows test-cov-all ``` -------------------------------- ### Direct ResilientTwoLevelCache Instantiation Source: https://context7.com/dclobato/resilient-cache/llms.txt Shows how to directly instantiate and configure ResilientTwoLevelCache with L1, L2, and circuit breaker settings. Note that CacheService is the recommended approach for managing backend factories. ```python from resilient_cache import ResilientTwoLevelCache from resilient_cache.config import ( CacheConfig, L1Config, L2Config, CircuitBreakerConfig, ) # Configure L1 (in-memory cache) l1_config = L1Config( enabled=True, maxsize=1000, ttl=60, backend="ttl", ) # Configure L2 (distributed cache) l2_config = L2Config( enabled=True, key_prefix="direct", ttl=3600, backend="redis", host="localhost", port=6379, db=0, password=None, connect_timeout=5, socket_timeout=5, ) # Configure circuit breaker cb_config = CircuitBreakerConfig( enabled=True, threshold=5, timeout=60, ) # Create complete cache config # Note: In practice, use CacheService which handles backend factories cache_config = CacheConfig( l1=l1_config, l2=l2_config, circuit_breaker=cb_config, serializer="pickle", ) # CacheService is the recommended way to create caches # as it properly initializes backend factories from resilient_cache import CacheService, CacheFactoryConfig factory_config = CacheFactoryConfig( l2_host="localhost", l2_port=6379, ) cache_service = CacheService(factory_config) # create_cache returns a ResilientTwoLevelCache instance cache = cache_service.create_cache( l2_key_prefix="direct", l2_ttl=3600, l2_enabled=True, l1_enabled=True, l1_maxsize=1000, l1_ttl=60, ) # ResilientTwoLevelCache implements AppCache interface print(repr(cache)) # ``` -------------------------------- ### Running Tests and Quality Checks Source: https://github.com/dclobato/resilient-cache/blob/master/INSTALLATION_GUIDE.md Commands for executing test suites and code quality automation. ```bash # Basic tests uv run pytest # Coverage uv run pytest --cov=resilient_cache --cov-report=html # Or use the Makefile uv run make test uv run make test-cov ``` ```bash # Formatting uv run make format # Linting uv run make lint # Type checking uv run make type-check # All checks uv run make check ``` -------------------------------- ### Basic Flask Cache Service Configuration Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Initialize a Flask application and configure the cache service using Flask's app.config. Ensure Redis/Valkey connection details are set in the app configuration. ```python from flask import Flask from resilient_cache import FlaskCacheService app = Flask(__name__) # Redis/Valkey configuration app.config.update({ 'CACHE_REDIS_HOST': 'localhost', 'CACHE_REDIS_PORT': 6379, 'CACHE_REDIS_DB': 0, }) # Initialize cache service cache_service = FlaskCacheService() cache_service.init_app(app) ``` -------------------------------- ### Run Unit Test Coverage (Windows) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Generate code coverage reports for unit tests on Windows using the Windows Makefile. ```bash make -f Makefile.windows test-cov ``` -------------------------------- ### Run Project Checks Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Commands to execute tests, coverage reports, and linting tools. ```bash uv run pytest uv run pytest --cov=resilient_cache --cov-report=html uv run black src/ tests/ uv run isort src/ tests/ uv run mypy src/ ``` -------------------------------- ### Run Unit Test Coverage (Linux/macOS) Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Generate code coverage reports specifically for unit tests. Results are shown in the terminal and an HTML report is generated. ```bash make test-cov ``` -------------------------------- ### Register and Use Custom Serializer Source: https://context7.com/dclobato/resilient-cache/llms.txt Implement a custom serializer (e.g., MessagePack), register it by name, and then use it in CacheFactoryConfig either by name or by passing an instance. ```python # Create custom serializer (e.g., for MessagePack) class MsgPackSerializer(CacheSerializer): def serialize(self, value): import msgpack return msgpack.packb(value, use_bin_type=True) def deserialize(self, data): import msgpack return msgpack.unpackb(data, raw=False) # Register custom serializer register_serializer("msgpack", MsgPackSerializer) print(list_serializers()) # ['json', 'msgpack', 'pickle'] # Use custom serializer in cache configuration config = CacheFactoryConfig( l2_host="localhost", serializer="msgpack", # Use registered name ) # Or pass serializer instance directly config = CacheFactoryConfig( l2_host="localhost", serializer=MsgPackSerializer(), # Pass instance ) cache_service = CacheService(config) ``` -------------------------------- ### Project Directory Structure Source: https://github.com/dclobato/resilient-cache/blob/master/INSTALLATION_GUIDE.md Overview of the resilient-cache project layout. ```text resilient-cache/ ├── src/ │ └── resilient_cache/ # Package source code │ ├── __init__.py # Public exports │ ├── app_cache.py # Abstract cache interface │ ├── cache_service.py # Core service (framework-agnostic) │ ├── flask_integration.py # Optional Flask integration │ ├── cache_factory.py # Cache factory │ ├── two_level_cache.py # L1+L2 implementation │ ├── circuit_breaker.py # Circuit breaker pattern │ ├── exceptions.py # Custom exceptions │ ├── config/ # Configuration dataclasses │ └── backends/ # L1/L2 backends ├── tests/ │ ├── conftest.py # Pytest fixtures │ ├── unit/ # Unit tests │ └── integration/ # Integration tests ├── examples/ # Usage examples ├── pyproject.toml # Project configuration ├── README.md # Main documentation ├── LICENSE # MIT license ├── CHANGELOG.md # Release history ├── CONTRIBUTING.md # Contributing guide ├── Makefile # Task automation (Linux/macOS) └── Makefile.windows # Task automation (Windows) ``` -------------------------------- ### Environment Configuration Keys for Resilient Cache Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Defines environment keys for configuring L2 (Redis/Valkey) connection, circuit breaker behavior, serialization, and L1/L2 backends. These can be set directly or via environment variables. ```python # L2 (Redis/Valkey) CACHE_REDIS_HOST = "localhost" CACHE_REDIS_PORT = 6379 CACHE_REDIS_DB = 0 CACHE_REDIS_PASSWORD = None CACHE_REDIS_CONNECT_TIMEOUT = 5 CACHE_REDIS_SOCKET_TIMEOUT = 5 # Circuit Breaker CACHE_CIRCUIT_BREAKER_ENABLED = True CACHE_CIRCUIT_BREAKER_THRESHOLD = 5 CACHE_CIRCUIT_BREAKER_TIMEOUT = 60 # Serialization CACHE_SERIALIZER = "pickle" # registered name (e.g. "pickle", "json") # L1 backend (default: TTLCache) CACHE_L1_BACKEND = "ttl" # "ttl" or "lru" # L2 backend (default: Valkey/Redis) CACHE_L2_BACKEND = "redis" # "redis" or "valkey" ``` -------------------------------- ### Configure Authentication for Integration Tests Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Set the password environment variable before running integration tests if the backend requires authentication. ```bash # Add to your config or export VALKEY_PASSWORD=your-password make test-integration ``` -------------------------------- ### Create CacheFactoryConfig from Flask Config Source: https://context7.com/dclobato/resilient-cache/llms.txt Initialize CacheFactoryConfig using a dictionary structured like Flask-Caching configuration. ```python flask_config = { "CACHE_REDIS_HOST": "localhost", "CACHE_REDIS_PORT": 6379, "CACHE_REDIS_DB": 0, "CACHE_REDIS_PASSWORD": None, "CACHE_REDIS_CONNECT_TIMEOUT": 5, "CACHE_REDIS_SOCKET_TIMEOUT": 5, "CACHE_L1_BACKEND": "ttl", "CACHE_L2_BACKEND": "redis", "CACHE_SERIALIZER": "pickle", "CACHE_CIRCUIT_BREAKER_ENABLED": True, "CACHE_CIRCUIT_BREAKER_THRESHOLD": 5, "CACHE_CIRCUIT_BREAKER_TIMEOUT": 60, } factory_config = CacheFactoryConfig.from_flask_config(flask_config) ``` -------------------------------- ### Commit Changes Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Commands to stage and commit changes to the repository. ```bash git add . git commit -m "Clear change description" ``` -------------------------------- ### Sort Imports with isort Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Sorts Python imports using 'isort' via 'uv run isort src/'. ```bash uv run isort src/ ``` -------------------------------- ### Docker Compose Configuration for Valkey Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Define a docker-compose.yml file to manage Valkey service for integration tests. This configuration specifies the image, port mapping, and memory settings. ```yaml version: '3.8' services: valkey: image: valkey/valkey:latest ports: - "6379:6379" environment: - VALKEY_MAXMEMORY=128mb - VALKEY_MAXMEMORY_POLICY=allkeys-lru ``` -------------------------------- ### Define Plugin Registry API Source: https://github.com/dclobato/resilient-cache/blob/master/ROADMAP.md Interface definitions for registering custom L1 and L2 cache backends and listing available plugins. ```python # resilient_cache/plugins.py def register_l1_backend(name: str, factory: Callable[[L1Config, Logger], CacheBackend]) -> None: ... def register_l2_backend(name: str, factory: Callable[[L2Config, str, Logger], CacheBackend]) -> None: ... def list_backends() -> dict: # {"l1": [...], "l2": [...]} ``` -------------------------------- ### List Available Serializers Source: https://github.com/dclobato/resilient-cache/blob/master/src/resilient_cache/SERIALIZERS.md Use list_serializers to verify which serializers are currently registered and available. ```python from resilient_cache import list_serializers print(list_serializers()) # Ver quais estão disponíveis ``` -------------------------------- ### Create Feature Branch Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Command to create a new branch for feature development. ```bash git checkout -b feature/my-feature ``` -------------------------------- ### Format Code with Black Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Formats Python code using 'black' via 'uv run black src/'. ```bash uv run black src/ ``` -------------------------------- ### Instantiate Cache with Custom Serializer Source: https://github.com/dclobato/resilient-cache/blob/master/src/resilient_cache/SERIALIZERS.md Pass a custom serializer instance directly to the cache factory without needing to register it. ```python cache = factory.create_cache( l2_key_prefix="myapp", l2_ttl=3600, l2_enabled=True, serializer=MySerializer(compression_level=9) # Instância customizada ) ``` -------------------------------- ### Run Tests with Pytest Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Executes the test suite using 'uv run pytest'. ```bash uv run pytest ``` -------------------------------- ### Handling Cache Errors Source: https://context7.com/dclobato/resilient-cache/llms.txt Illustrates how to catch and handle various exceptions raised by Resilient Cache, including configuration, connection, serialization, and circuit breaker errors. ```python from resilient_cache import ( CacheService, CacheFactoryConfig, CacheError, CacheConnectionError, CacheSerializationError, CacheConfigurationError, ) from resilient_cache.exceptions import CircuitBreakerOpenError # Handle configuration errors try: config = CacheFactoryConfig( l2_host="invalid host!", # Invalid hostname l2_port=99999, # Invalid port ) except ValueError as e: print(f"Configuration error: {e}") # Handle cache operation errors config = CacheFactoryConfig(l2_host="localhost", l2_port=6379) cache_service = CacheService(config) cache = cache_service.create_cache( l2_key_prefix="errors", l2_ttl=3600, l2_enabled=True, l1_enabled=True, l1_maxsize=100, l1_ttl=60, ) try: # Operations that might fail cache.set("key", {"data": "value"}) value = cache.get("key") except CacheConnectionError as e: # L2 connection failed - cache continues with L1 only print(f"Connection error: {e.message}") print(f"Backend: {e.backend}") print(f"Original error: {e.original_error}") except CacheSerializationError as e: # Failed to serialize/deserialize value print(f"Serialization error: {e.message}") print(f"Key: {e.key}") print(f"Serializer: {e.serializer}") except CircuitBreakerOpenError as e: # Circuit breaker is open - L2 operations blocked print(f"Circuit breaker open: {e.message}") print(f"Failure count: {e.failure_count}") except CacheError as e: # Base exception for all cache errors print(f"Cache error: {e.message}") print(f"Details: {e.details}") ``` -------------------------------- ### Integrate New L1 Backend into Cache Factory Source: https://github.com/dclobato/resilient-cache/blob/master/BACKEND_GUIDE.md Modify the CacheFactory to recognize and instantiate a new L1 backend by its configured name. ```python if config.backend == "my_l1": from .backends.my_l1_backend import MyL1Backend return MyL1Backend(config) ``` -------------------------------- ### Monitor Key Cache Metrics Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Retrieve and analyze key cache metrics, such as L1 usage and L2 circuit breaker state, to identify potential issues. ```python stats = cache.get_stats() l1_usage = stats['l1']['size'] / stats['l1']['maxsize'] * 100 if l1_usage > 90: print("Warning: L1 cache nearly full") cb_state = stats['l2']['circuit_breaker']['state'] if cb_state != 'closed': print(f"Warning: Circuit breaker state is {cb_state}") ``` -------------------------------- ### Implement __repr__ for Serializers Source: https://github.com/dclobato/resilient-cache/blob/master/src/resilient_cache/SERIALIZERS.md Define a __repr__ method to improve readability in logs and debugging output. ```python def __repr__(self) -> str: return "MySerializer()" ``` -------------------------------- ### Run Tests with Coverage Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Runs tests with coverage enabled and generates an HTML report using 'uv run pytest --cov=resilient_cache --cov-report=html'. ```bash uv run pytest --cov=resilient_cache --cov-report=html ``` -------------------------------- ### Push Changes Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Command to push the feature branch to the remote repository. ```bash git push origin feature/my-feature ``` -------------------------------- ### Integrate New L2 Backend into Cache Factory Source: https://github.com/dclobato/resilient-cache/blob/master/BACKEND_GUIDE.md Update the CacheFactory to support a new L2 backend, including passing necessary arguments like serializer and logger. ```python if config.backend == "my_l2": from .backends.my_l2_backend import MyL2Backend return MyL2Backend(config, serializer, self.logger) ``` -------------------------------- ### Perform Type Checks Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Runs static type checking using 'mypy' via 'uv run mypy src/'. ```bash uv run mypy src/ ``` -------------------------------- ### Conventional Commit Format Source: https://github.com/dclobato/resilient-cache/blob/master/CONTRIBUTING.md Template for writing conventional commits. ```text (): [optional longer description] [optional BREAKING CHANGE: describe the breaking change] ``` -------------------------------- ### Write-Through Cache Strategy Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Implement the write-through strategy where data is written to both L1 and L2 caches simultaneously. ```python cache.set("key", "value") ``` -------------------------------- ### Configure Circuit Breaker via CacheFactoryConfig Source: https://context7.com/dclobato/resilient-cache/llms.txt Enable and configure the circuit breaker pattern within CacheFactoryConfig to protect against L2 backend failures. This includes setting failure thresholds and reset timeouts. ```python from resilient_cache import CacheService, CacheFactoryConfig from resilient_cache.circuit_breaker import CircuitBreaker from resilient_cache.config import CircuitBreakerConfig # Configure circuit breaker via CacheFactoryConfig config = CacheFactoryConfig( l2_host="localhost", l2_port=6379, circuit_breaker_enabled=True, circuit_breaker_threshold=5, # Open after 5 consecutive failures circuit_breaker_timeout=60, # Try to close after 60 seconds ) cache_service = CacheService(config) cache = cache_service.create_cache( l2_key_prefix="protected", l2_ttl=3600, l2_enabled=True, l1_enabled=True, l1_maxsize=100, l1_ttl=60, ) # Cache operations are automatically protected # When L2 fails, circuit breaker tracks failures cache.set("key", "value") # If L2 fails, records failure value = cache.get("key") # Still works via L1 fallback ``` -------------------------------- ### Create Expensive Computation Cache Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Configuration for caching the results of expensive computations, with longer L2 TTL and specific L1/L2 enablement. ```python computation_cache = cache_service.create_cache( l2_key_prefix="computation", l2_ttl=86400, l2_enabled=True, l1_enabled=True, l1_maxsize=100, l1_ttl=3600, ) ``` -------------------------------- ### Manually Flush Redis Database Source: https://github.com/dclobato/resilient-cache/blob/master/tests/README.md Use redis-cli to clear the database if integration tests fail to clean up properly. ```bash redis-cli -n 0 FLUSHDB ``` -------------------------------- ### Direct Circuit Breaker Usage Source: https://context7.com/dclobato/resilient-cache/llms.txt Demonstrates direct usage of the CircuitBreaker class for protecting functions. This is useful for advanced scenarios where automatic integration via CacheService is not desired. ```python from resilient_cache import CircuitBreaker, CircuitBreakerConfig cb_config = CircuitBreakerConfig( enabled=True, threshold=3, timeout=30, ) breaker = CircuitBreaker(cb_config) # Use as decorator @breaker.protected def risky_redis_operation(): # This function is protected by circuit breaker return redis_client.get("key") # Manual state management breaker.record_success() # Record successful operation breaker.record_failure() # Record failed operation breaker.reset() # Manually reset to closed state ``` -------------------------------- ### Cache Statistics and Monitoring Source: https://context7.com/dclobato/resilient-cache/llms.txt Retrieves detailed cache statistics including L1/L2 status, circuit breaker state, and key TTLs. Useful for building health checks and monitoring dashboards. Requires L2 connectivity for accurate L2 stats. ```python from resilient_cache import CacheService, CacheFactoryConfig config = CacheFactoryConfig(l2_host="localhost", l2_port=6379) cache_service = CacheService(config) cache = cache_service.create_cache( l2_key_prefix="monitoring", l2_ttl=3600, l2_enabled=True, l1_enabled=True, l1_maxsize=1000, l1_ttl=60, ) # Get detailed cache statistics stats = cache.get_stats() # Example stats structure: # { # "enabled": True, # "l1": { # "enabled": True, # "size": 42, # "maxsize": 1000, # "ttl": 60, # "backend": "ttl" # }, # "l2": { # "enabled": True, # "ttl": 3600, # "key_prefix": "monitoring", # "host": "localhost", # "port": 6379 # }, # "circuit_breaker": { # "enabled": True, # "state": "closed", # "failure_count": 0, # "threshold": 5, # "timeout": 60 # } # } # Monitor L1 capacity usage l1_usage = stats["l1"]["size"] / stats["l1"]["maxsize"] * 100 if l1_usage > 90: print(f"WARNING: L1 cache is {l1_usage:.1f}% full") # Check circuit breaker state cb_state = stats["circuit_breaker"]["state"] if cb_state == "open": print("ALERT: Circuit breaker is OPEN - L2 unavailable") elif cb_state == "half_open": print("INFO: Circuit breaker testing L2 connectivity") # Get remaining TTL for a specific key ttl = cache.get_ttl("important_key") if ttl is not None and ttl < 300: print(f"Key expires in {ttl} seconds - consider refreshing") # List all keys with optional prefix filter all_keys = cache.list_keys() user_keys = cache.list_keys(prefix="user_") print(f"Total keys: {len(all_keys)}, User keys: {len(user_keys)}") ``` -------------------------------- ### Integrate Resilient Cache with Flask Source: https://context7.com/dclobato/resilient-cache/llms.txt Uses FlaskCacheService to manage cache configuration via app.config and provides health check endpoints. ```python from flask import Flask, jsonify from resilient_cache import FlaskCacheService, get_cache_service app = Flask(__name__) # Configure via Flask config app.config.update({ "CACHE_REDIS_HOST": "localhost", "CACHE_REDIS_PORT": 6379, "CACHE_REDIS_DB": 0, "CACHE_REDIS_PASSWORD": None, "CACHE_SERIALIZER": "pickle", "CACHE_CIRCUIT_BREAKER_ENABLED": True, "CACHE_CIRCUIT_BREAKER_THRESHOLD": 5, "CACHE_CIRCUIT_BREAKER_TIMEOUT": 60, }) # Initialize cache service with Flask app cache_service = FlaskCacheService() cache_service.init_app(app) # Create cache for products product_cache = cache_service.create_cache( l2_key_prefix="products", l2_ttl=1800, l2_enabled=True, l1_enabled=True, l1_maxsize=500, l1_ttl=120, ) @app.route("/products/") def get_product(product_id: str): cache_key = f"product_{product_id}" product = product_cache.get(cache_key) if product is not None: return jsonify({"product": product, "source": "cache"}) # Cache miss - fetch from database product = {"id": product_id, "name": "Sample Product", "price": 29.99} product_cache.set(cache_key, product) return jsonify({"product": product, "source": "database"}) @app.route("/health") def health_check(): # Access cache service from Flask extensions service = get_cache_service() stats = product_cache.get_stats() cb_state = stats.get("circuit_breaker", {}).get("state", "unknown") if cb_state == "open": return jsonify({"status": "degraded", "reason": "L2 unavailable"}), 503 return jsonify({"status": "healthy", "circuit_breaker": cb_state}) ``` -------------------------------- ### Raise ValueError with Descriptive Messages Source: https://github.com/dclobato/resilient-cache/blob/master/src/resilient_cache/SERIALIZERS.md Wrap serialization logic in a try-except block to provide clear error context when serialization fails. ```python def serialize(self, value: Any) -> bytes: try: return my_serialize(value) except Exception as e: raise ValueError(f"Erro ao serializar com MySerializer: {e}") from e ``` -------------------------------- ### Cache Health Check Endpoint Source: https://github.com/dclobato/resilient-cache/blob/master/README.md Implement a health check endpoint for the cache. Returns a degraded status if the L2 circuit breaker is open. ```python @app.route('/health/cache') def cache_health(): stats = cache.get_stats() if stats['l2']['circuit_breaker']['state'] == 'open': return {"status": "degraded", "reason": "L2 unavailable"}, 503 return {"status": "healthy", "stats": stats}, 200 ``` -------------------------------- ### Cache Clear Operations Source: https://context7.com/dclobato/resilient-cache/llms.txt Removes all entries from both L1 and L2 caches and returns statistics on the number of items removed. Useful for cache invalidation during deployments or data migrations. ```python from resilient_cache import CacheService, CacheFactoryConfig config = CacheFactoryConfig(l2_host="localhost", l2_port=6379) cache_service = CacheService(config) cache = cache_service.create_cache( l2_key_prefix="clearable", l2_ttl=3600, l2_enabled=True, l1_enabled=True, l1_maxsize=500, l1_ttl=60, ) # Populate some cache entries for i in range(100): cache.set(f"item:{i}", {"value": i * 10}) # Clear all cache and get removal statistics clear_stats = cache.clear() # Example clear_stats structure: # { # "l1_items_removed": 100, # "l2_items_removed": 100, # "timestamp": 1705312200.123456 # } print(f"Cleared {clear_stats['l1_items_removed']} items from L1") print(f"Cleared {clear_stats['l2_items_removed']} items from L2") ```