Skip to content

Conversation

@jordpo
Copy link

@jordpo jordpo commented Oct 20, 2025

Summary

Refactors the cache layer to support multiple interchangeable backend implementations, enabling future support for Redis, filesystem, and cloud-native caching strategies.

Motivation

The current cache implementation is tightly coupled to the quick_cache in-memory LRU cache. This refactoring provides a clean abstraction that allows:

  1. Pluggable backends - Easy addition of new cache types (Redis, filesystem, cloud-native)
  2. Testing flexibility - NoOp cache for benchmarking storage performance
  3. Future extensibility - Well-defined trait interface for community contributions

Changes

New Cache Module (icechunk/src/cache/)

  • StorageCache trait: Object-safe trait defining the cache interface

    • Async operations with boxed futures for dynamic dispatch
    • Weight-based eviction support
    • Concurrent request deduplication
  • EphemeralCache: In-memory LRU cache using quick_cache (default)

    • Maintains all existing behavior and performance characteristics
    • Named "ephemeral" to clearly indicate temporary, in-memory nature
  • NoOpCache: Pass-through cache that performs no caching

    • Useful for debugging, testing, and low-memory environments
    • Replaces previous zero-capacity cache approach
  • CacheBackend enum: Serializable configuration for backend selection

    • Ephemeral (default) - In-memory LRU
    • NoOp - Disables caching

Updated Components

  • CachingConfig: Added backend field (defaults to Ephemeral)

    • Fully backward compatible - existing configs work unchanged
    • Serializable for configuration persistence
  • AssetManager: Refactored to use Arc<dyn StorageCache> trait objects

    • Four specialized caches (snapshot, manifest, transactions, chunks)
    • Cache backend selected at initialization based on configuration
    • Maintained complete API compatibility

Documentation

  • Comprehensive Rust documentation following existing patterns
  • Module-level docs with usage examples
  • Detailed trait and implementation documentation
  • Inline code examples for configuration

Design Decisions

  1. Object Safety: Used boxed futures to enable dynamic dispatch while maintaining async functionality
  2. Default Backend: Ephemeral ensures zero breaking changes - all existing behavior preserved
  3. Error Handling: Proper conversion from boxed errors back to RepositoryError
  4. Backward Compatibility: All existing tests pass without modification

Future Work

This architecture enables easy addition of new backends:

  • Redis cache for distributed environments
  • Filesystem cache for persistent caching across restarts
  • Cloud-native local caches (e.g., AWS DAX, GCP Memorystore)

To add a new backend:

  1. Implement the StorageCache trait
  2. Add a new variant to CacheBackend enum
  3. Update AssetManager::new() to handle the new variant

Testing

✅ All 104 library tests pass, including:

  • Asset manager cache tests
  • Storage integration tests
  • Session and repository tests

No test modifications were required (except adding the backend field to test config structs with default values).

Breaking Changes

None - this is a pure internal refactoring with full backward compatibility.

Checklist

  • Rust code follows existing patterns
  • All tests pass
  • Documentation added following existing style
  • No breaking changes to public API
  • Backward compatible with existing configurations

jordpo and others added 2 commits October 20, 2025 11:33
Refactors the cache layer to support multiple interchangeable backend
implementations (in-memory, filesystem, Redis, etc).

Key changes:
- Add StorageCache trait for pluggable cache backends
- Implement EphemeralCache (default, in-memory LRU) and NoOpCache
- Add CacheBackend enum to CachingConfig for backend selection
- Refactor AssetManager to use trait objects instead of concrete types
- Add comprehensive Rust documentation

Fully backward compatible - default behavior unchanged.
All 104 library tests pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add the missing `backend` field to the `From<&PyCachingConfig>`
implementation. This field was added in the cache backend refactor
but was missing from the Python bindings conversion, causing a
compilation error in the Read the Docs build pipeline.

The backend is set to `Default::default()` which uses
`CacheBackend::Ephemeral`, the default cache backend.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@mpiannucci
Copy link
Contributor

Hi @jordpo We recently made some big changes to the main branch, would you mind re-syncing this?

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.

2 participants