diff --git a/README.md b/README.md index f32f4eb0..d2759e05 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ This monorepo contains two libraries: ## Documentation -- [Full Documentation](https://strawgate.github.io/py-key-value/) -- [Getting Started Guide](https://strawgate.github.io/py-key-value/getting-started/) -- [Wrappers Guide](https://strawgate.github.io/py-key-value/wrappers/) -- [Adapters Guide](https://strawgate.github.io/py-key-value/adapters/) -- [API Reference](https://strawgate.github.io/py-key-value/api/protocols/) +- [Full Documentation](https://strawgate.com/py-key-value/) +- [Getting Started Guide](https://strawgate.com/py-key-value/getting-started/) +- [Wrappers Guide](https://strawgate.com/py-key-value/wrappers/) +- [Adapters Guide](https://strawgate.com/py-key-value/adapters/) +- [API Reference](https://strawgate.com/py-key-value/api/protocols/) ## Why use this library? @@ -184,81 +184,34 @@ ttl_many(keys: list[str], collection: str | None = None) -> list[tuple[dict[str, ### Stores -The library provides a variety of stores that implement the protocol. +The library provides multiple store implementations organized into three +categories: -A ✅ means a store is available, a ☑️ under async means a store is available -but the underlying implementation is synchronous. A ✖️ means a store is -not available. +- **Local stores**: In-memory and disk-based storage (Memory, Disk, RocksDB, etc.) +- **Secret stores**: Secure OS-level storage for sensitive data (Keyring, Vault) +- **Distributed stores**: Network-based storage for multi-node apps (Redis, + DynamoDB, MongoDB, etc.) -Stability is a measure of the likelihood that the way data is stored will change -in a backwards incompatible way. +Each store has a **stability rating** indicating likelihood of +backwards-incompatible changes. Stable stores (Redis, Valkey, Disk, Keyring) +are recommended for long-term storage. -- A stable store is one we do not intend to change in a backwards incompatible way. -- A preview store is one that is unlikely to change in a backwards incompatible way. -- An unstable store is one that is likely to change in a backwards incompatible way. - -If you are using py-key-value-aio for caching, stability may not be a concern for -you. If you are using py-key-value-aio for long-term storage, stability is a -concern and you should consider using a stable store. - -#### Local stores - -Local stores are stored in memory or on disk, local to the application. - -| Local Stores | Stability | Async | Sync | Example | -|------------------|:---------:|:-----:|:----:|:-------| -| Memory | N/A | ✅ | ✅ | `MemoryStore()` | -| Disk | Stable | ☑️ | ✅ | `DiskStore(directory="./cache")` | -| Disk (Per-Collection) | Stable | ☑️ | ✅ | `MultiDiskStore(directory="./cache")` | -| Null (test) | N/A | ✅ | ✅ | `NullStore()` | -| RocksDB | Unstable | ☑️ | ✅ | `RocksDBStore(path="./rocksdb")` | -| Simple (test) | N/A | ✅ | ✅ | `SimpleStore()` | -| Windows Registry | Unstable | ☑️ | ✅ | `WindowsRegistryStore(hive="HKEY_CURRENT_USER", registry_path="Software\\py-key-value")` | - -#### Local - Secret stores - -Secret stores are stores that are used to store sensitive data, typically in -an Operating System's secret store. - -| Secret Stores | Stability | Async | Sync | Example | -|---------------|:---------:|:-----:|:----:|:-------| -| Keyring | Stable | ✅ | ✅ | `KeyringStore(service_name="py-key-value")` | -| Vault | Unstable | ✅ | ✅ | `VaultStore(url="http://localhost:8200", token="your-token")` | - -Note: The Windows Keyring has strict limits on the length of values which may -cause issues with large values. - -#### Distributed stores - -Distributed stores are stores that are used to store data in a distributed -system, for access across multiple application nodes. - -| Distributed Stores | Stability | Async | Sync | Example | -|------------------|:---------:|:-----:|:----:|:-------| -| DynamoDB | Unstable | ✅ | ✖️ | `DynamoDBStore(table_name="kv-store", region_name="us-east-1")` | -| Elasticsearch | Unstable | ✅ | ✅ | `ElasticsearchStore(url="https://localhost:9200", api_key="your-api-key", index="kv-store")` | -| Memcached | Unstable | ✅ | ✖️ | `MemcachedStore(host="127.0.0.1", port=11211")` | -| MongoDB | Unstable | ✅ | ✅ | `MongoDBStore(url="mongodb://localhost:27017/test")` | -| Redis | Stable | ✅ | ✅ | `RedisStore(url="redis://localhost:6379/0")` | -| Valkey | Stable | ✅ | ✅ | `ValkeyStore(host="localhost", port=6379)` | +**[📚 View all stores, installation guides, and examples →](https://strawgate.com/py-key-value/stores/)** ### Adapters -Adapters "wrap" any protocol-compliant store but do not themselves implement -the protocol. +Adapters provide specialized interfaces for working with stores. Unlike wrappers, +they don't implement the protocol but instead offer alternative APIs for specific +use cases: -They simplify your applications interactions with stores and provide additional -functionality. While your application will accept an instance that implements -the protocol, your application code might be simplified by using an adapter. +- **DataclassAdapter**: Type-safe dataclass storage with automatic validation +- **PydanticAdapter**: Type-safe Pydantic model storage with serialization +- **RaiseOnMissingAdapter**: Raise exceptions instead of returning None for + missing keys -| Adapter | Description | Example | -|---------|:------------|:------------------| -| DataclassAdapter | Type-safe storage/retrieval of dataclass models with transparent serialization/deserialization. | `DataclassAdapter(key_value=memory_store, dataclass_type=User)` | -| PydanticAdapter | Type-safe storage/retrieval of Pydantic models with transparent serialization/deserialization. | `PydanticAdapter(key_value=memory_store, pydantic_model=User)` | -| RaiseOnMissingAdapter | Optional raise-on-missing behavior for `get`, `get_many`, `ttl`, and `ttl_many`. | `RaiseOnMissingAdapter(key_value=memory_store)` | +**[📚 View all adapters with examples →](https://strawgate.com/py-key-value/adapters/)** -For example, the PydanticAdapter allows you to store and retrieve Pydantic -models with transparent serialization/deserialization: +**Quick example** - PydanticAdapter for type-safe storage: ```python import asyncio @@ -298,33 +251,21 @@ asyncio.run(example()) ### Wrappers -The library provides a wrapper pattern for adding functionality to a store. -Wrappers themselves implement the protocol meaning that you can wrap any store -with any wrapper, and chain wrappers together as needed. - -The following wrappers are available: - -| Wrapper | Description | Example | -|---------|---------------|-----| -| CollectionRoutingWrapper | Route operations to different stores based on a collection name. | `CollectionRoutingWrapper(collection_map={"sessions": redis_store, "users": dynamo_store}, default_store=memory_store)` | -| CompressionWrapper | Compress values before storing and decompress on retrieval. | `CompressionWrapper(key_value=memory_store, min_size_to_compress=0)` | -| DefaultValueWrapper | Return a default value when key is missing. | `DefaultValueWrapper(key_value=memory_store, default_value={})` | -| FernetEncryptionWrapper | Encrypt values before storing and decrypt on retrieval. | `FernetEncryptionWrapper(key_value=memory_store, source_material="your-source-material", salt="your-salt")` | -| FallbackWrapper | Fallback to a secondary store when the primary store fails. | `FallbackWrapper(primary_key_value=memory_store, fallback_key_value=memory_store)` | -| LimitSizeWrapper | Limit the size of entries stored in the cache. | `LimitSizeWrapper(key_value=memory_store, max_size=1024, raise_on_too_large=True)` | -| LoggingWrapper | Log the operations performed on the store. | `LoggingWrapper(key_value=memory_store, log_level=logging.INFO, structured_logs=True)` | -| PassthroughCacheWrapper | Wrap two stores to provide a read-through cache. | `PassthroughCacheWrapper(primary_key_value=memory_store, cache_key_value=memory_store)` | -| PrefixCollectionsWrapper | Prefix all collections with a given prefix. | `PrefixCollectionsWrapper(key_value=memory_store, prefix="users")` | -| PrefixKeysWrapper | Prefix all keys with a given prefix. | `PrefixKeysWrapper(key_value=memory_store, prefix="users")` | -| ReadOnlyWrapper | Prevent all write operations on the underlying store. | `ReadOnlyWrapper(key_value=memory_store, raise_on_write=True)` | -| RetryWrapper | Retry failed operations with exponential backoff. | `RetryWrapper(key_value=memory_store, max_retries=3, initial_delay=0.1, max_delay=10.0, exponential_base=2.0)` | -| RoutingWrapper | Route operations to different stores based on a routing function. | `RoutingWrapper(routing_function=lambda collection: redis_store if collection == "sessions" else dynamo_store, default_store=memory_store)` | -| SingleCollectionWrapper | Wrap a store to only use a single collection. | `SingleCollectionWrapper(key_value=memory_store, single_collection="users")` | -| StatisticsWrapper | Track operation statistics for the store. | `StatisticsWrapper(key_value=memory_store)` | -| TimeoutWrapper | Add timeout protection to store operations. | `TimeoutWrapper(key_value=redis_store, timeout=5.0)` | -| TTLClampWrapper | Clamp the TTL to a given range. | `TTLClampWrapper(key_value=memory_store, min_ttl=60, max_ttl=3600)` | - -Wrappers can be stacked on top of each other to create more complex functionality. +Wrappers add functionality to stores while implementing the protocol themselves, +allowing them to be stacked and used anywhere a store is expected. Available +wrappers include: + +- **Performance**: Compression, Caching (Passthrough), Statistics, Timeout +- **Security**: Encryption (Fernet), ReadOnly +- **Reliability**: Retry, Fallback +- **Routing**: CollectionRouting, Routing, SingleCollection +- **Organization**: PrefixKeys, PrefixCollections +- **Constraints**: LimitSize, TTLClamp, DefaultValue +- **Observability**: Logging, Statistics + +**[📚 View all wrappers with examples →](https://strawgate.com/py-key-value/wrappers/)** + +Wrappers can be stacked for complex functionality: ```python # Create a retriable redis store with timeout protection that is monitored, @@ -412,8 +353,8 @@ library. ## Project links -- Async README: `key-value/key-value-aio/README.md` -- Sync README: `key-value/key-value-sync/README.md` +- [Full Documentation](https://strawgate.com/py-key-value/) +- [API Reference](https://strawgate.com/py-key-value/api/protocols/) Contributions welcome but may not be accepted. File an issue before submitting a pull request. If you do not get agreement on your proposal before making a diff --git a/docs/adapters.md b/docs/adapters.md index 58127685..a99cce15 100644 --- a/docs/adapters.md +++ b/docs/adapters.md @@ -4,6 +4,14 @@ Adapters provide specialized interfaces for working with key-value stores. Unlik wrappers, adapters don't implement the `AsyncKeyValue` protocol - instead, they provide alternative APIs tailored for specific use cases. +## Available Adapters + +| Adapter | Description | +|---------|-------------| +| [DataclassAdapter](#dataclassadapter) | Type-safe storage/retrieval of dataclass models with transparent serialization | +| [PydanticAdapter](#pydanticadapter) | Type-safe storage/retrieval of Pydantic models with transparent serialization | +| [RaiseOnMissingAdapter](#raiseonmissingadapter) | Optional raise-on-missing behavior for get operations | + ## Adapters vs Wrappers **Wrappers:** @@ -20,7 +28,52 @@ provide alternative APIs tailored for specific use cases. - Add type safety and specialized behavior - Transform how you interact with the store -## Available Adapters +## Adapter Details + +### DataclassAdapter + +The `DataclassAdapter` provides type-safe storage and retrieval of Python +dataclass models. It automatically handles serialization and validation using +Pydantic for validation. + +#### Use Cases + +- Type-safe data storage with dataclasses +- Automatic validation on retrieval +- Working with Python's native dataclass decorator +- Ensuring data integrity + +#### Basic Example + +```python +from dataclasses import dataclass +from key_value.aio.stores.memory import MemoryStore +from key_value.aio.adapters.dataclass import DataclassAdapter + +@dataclass +class User: + name: str + email: str + age: int + +# Create adapter +adapter = DataclassAdapter( + key_value=MemoryStore(), + dataclass_type=User +) + +# Store a user (type-safe) +user = User(name="Alice", email="alice@example.com", age=30) +await adapter.put(key="user:123", value=user, collection="users") + +# Retrieve and get a validated model +retrieved_user = await adapter.get(key="user:123", collection="users") +if retrieved_user: + print(retrieved_user.name) # Type-safe: "Alice" + print(retrieved_user.email) # Type-safe: "alice@example.com" +``` + +--- ### PydanticAdapter diff --git a/docs/stores.md b/docs/stores.md new file mode 100644 index 00000000..f4d49a6a --- /dev/null +++ b/docs/stores.md @@ -0,0 +1,621 @@ +# Stores + +Stores are the core implementations of the `AsyncKeyValue` protocol. They provide +the actual storage backend for your key-value data. + +## Store Categories + +Stores are organized into three categories based on their storage location and +use case: + +- **Local Stores**: In-memory or on-disk storage local to the application +- **Secret Stores**: Secure storage for sensitive data in OS secret stores +- **Distributed Stores**: Network-based storage for multi-node applications + +## Stability Levels + +Each store has a stability rating that indicates the likelihood of +backwards-incompatible changes to how data is stored: + +- **Stable**: No planned backwards-incompatible changes +- **Preview**: Unlikely to change in backwards-incompatible ways +- **Unstable**: May change in backwards-incompatible ways +- **N/A**: Not applicable (e.g., in-memory stores) + +If you're using py-key-value for caching, stability may not matter. For +long-term storage, prefer stable stores. + +## Local Stores + +Local stores are stored in memory or on disk, local to the application. + +| Store | Stability | Async | Sync | Description | +|-------|:---------:|:-----:|:----:|:------------| +| Memory | N/A | ✅ | ✅ | Fast in-memory storage for development and caching | +| Disk | Stable | ☑️ | ✅ | Persistent file-based storage in a single file | +| Disk (Per-Collection) | Stable | ☑️ | ✅ | Persistent storage with separate files per collection | +| Null (test) | N/A | ✅ | ✅ | No-op store for testing without side effects | +| RocksDB | Unstable | ☑️ | ✅ | High-performance embedded database | +| Simple (test) | N/A | ✅ | ✅ | Simple in-memory store for testing | +| Windows Registry | Unstable | ☑️ | ✅ | Windows Registry-based storage | + +**Legend:** + +- ✅ = Fully async implementation available +- ☑️ = Available but uses synchronous underlying implementation +- ✖️ = Not available + +### MemoryStore + +Fast in-memory storage ideal for development, testing, and caching. + +```python +from key_value.aio.stores.memory import MemoryStore + +store = MemoryStore() +``` + +**Installation:** + +```bash +pip install py-key-value-aio[memory] +``` + +**Use Cases:** + +- Development and testing +- Fast caching +- Session storage +- Temporary data + +**Characteristics:** + +- No persistence (data lost on restart) +- Extremely fast +- No external dependencies +- Thread-safe + +--- + +### DiskStore + +Persistent file-based storage using a single JSON file. + +```python +from key_value.aio.stores.disk import DiskStore + +store = DiskStore(directory="./cache") +``` + +**Installation:** + +```bash +pip install py-key-value-aio[disk] +``` + +**Use Cases:** + +- Local caching with persistence +- Development environments +- Single-node applications +- Small datasets + +**Characteristics:** + +- Persists across restarts +- Simple file format (JSON) +- Suitable for small to medium datasets +- All data in one file + +--- + +### MultiDiskStore + +Persistent storage with separate files per collection. + +```python +from key_value.aio.stores.multi_disk import MultiDiskStore + +store = MultiDiskStore(directory="./cache") +``` + +**Installation:** + +```bash +pip install py-key-value-aio[disk] +``` + +**Use Cases:** + +- Organizing data by collection +- Better performance with many collections +- Easier to manage individual collections + +**Characteristics:** + +- One file per collection +- Better suited for many collections +- Easier collection management +- JSON-based storage + +--- + +### RocksDBStore + +High-performance embedded database using RocksDB. + +```python +from key_value.aio.stores.rocksdb import RocksDBStore + +store = RocksDBStore(path="./rocksdb") +``` + +**Installation:** + +```bash +pip install py-key-value-aio[rocksdb] +``` + +**Use Cases:** + +- High-throughput applications +- Large datasets +- Performance-critical applications + +**Characteristics:** + +- Very fast reads and writes +- Efficient storage +- Requires native dependencies +- Stable storage format: **Unstable** + +--- + +### WindowsRegistryStore + +Storage using the Windows Registry. + +```python +from key_value.aio.stores.registry import WindowsRegistryStore + +store = WindowsRegistryStore( + hive="HKEY_CURRENT_USER", + registry_path="Software\\py-key-value" +) +``` + +**Installation:** + +```bash +pip install py-key-value-aio[registry] +``` + +**Use Cases:** + +- Windows-specific applications +- System configuration storage +- Integration with Windows settings + +**Characteristics:** + +- Windows-only +- Persists in registry +- Subject to registry limitations +- Stable storage format: **Unstable** + +--- + +### NullStore + +No-op store that discards all data. Useful for testing. + +```python +from key_value.aio.stores.null import NullStore + +store = NullStore() +``` + +**Use Cases:** + +- Testing without side effects +- Disabling storage temporarily +- Performance baseline testing + +--- + +### SimpleStore + +Simple in-memory store for testing. + +```python +from key_value.aio.stores.simple import SimpleStore + +store = SimpleStore() +``` + +**Use Cases:** + +- Basic testing +- Minimal implementation reference + +--- + +## Secret Stores + +Secret stores provide secure storage for sensitive data, typically using +operating system secret management facilities. + +| Store | Stability | Async | Sync | Description | +|-------|:---------:|:-----:|:----:|:------------| +| Keyring | Stable | ✅ | ✅ | OS-level secure storage (Keychain, Credential Manager, etc.) | +| Vault | Unstable | ✅ | ✅ | HashiCorp Vault integration for enterprise secrets | + +### KeyringStore + +Secure storage using the operating system's keyring (macOS Keychain, Windows +Credential Manager, Linux Secret Service). + +```python +from key_value.aio.stores.keyring import KeyringStore + +store = KeyringStore(service_name="py-key-value") +``` + +**Installation:** + +```bash +pip install py-key-value-aio[keyring] +``` + +**Use Cases:** + +- Storing API keys and tokens +- User credentials +- Sensitive configuration +- Encrypted local storage + +**Characteristics:** + +- OS-level encryption +- Secure by default +- Cross-platform +- **Windows limitation**: Strict value length limits + +**Important:** Windows Keyring has strict limits on value length which may +cause issues with large values. + +--- + +### VaultStore + +Integration with HashiCorp Vault for enterprise secret management. + +```python +from key_value.aio.stores.vault import VaultStore + +store = VaultStore( + url="http://localhost:8200", + token="your-token" +) +``` + +**Installation:** + +```bash +pip install py-key-value-aio[vault] +``` + +**Use Cases:** + +- Enterprise secret management +- Multi-environment deployments +- Centralized secret rotation +- Audit logging + +**Characteristics:** + +- Enterprise-grade security +- Centralized management +- Audit logging +- Stable storage format: **Unstable** + +--- + +## Distributed Stores + +Distributed stores provide network-based storage for multi-node applications. + +| Store | Stability | Async | Sync | Description | +|-------|:---------:|:-----:|:----:|:------------| +| DynamoDB | Unstable | ✅ | ✖️ | AWS DynamoDB key-value storage | +| Elasticsearch | Unstable | ✅ | ✅ | Full-text search with key-value capabilities | +| Memcached | Unstable | ✅ | ✖️ | High-performance distributed memory cache | +| MongoDB | Unstable | ✅ | ✅ | Document database used as key-value store | +| Redis | Stable | ✅ | ✅ | Popular in-memory data structure store | +| Valkey | Stable | ✅ | ✅ | Open-source Redis fork | + +### RedisStore + +High-performance in-memory store using Redis. + +```python +from key_value.aio.stores.redis import RedisStore + +store = RedisStore(url="redis://localhost:6379/0") +``` + +**Installation:** + +```bash +pip install py-key-value-aio[redis] +``` + +**Use Cases:** + +- Distributed caching +- Session storage +- Real-time applications +- High-throughput systems + +**Characteristics:** + +- Very fast (in-memory) +- Production-ready +- Rich feature set +- Horizontal scaling support +- **Stable storage format** + +--- + +### ValkeyStore + +Open-source Redis fork with similar performance characteristics. + +```python +from key_value.aio.stores.valkey import ValkeyStore + +store = ValkeyStore(host="localhost", port=6379) +``` + +**Installation:** + +```bash +pip install py-key-value-aio[valkey] +``` + +**Use Cases:** + +- Same as Redis +- Open-source preference +- Redis API compatibility + +**Characteristics:** + +- Redis-compatible +- Open-source governance +- Production-ready +- **Stable storage format** + +--- + +### DynamoDBStore + +AWS DynamoDB integration for serverless and cloud-native applications. + +```python +from key_value.aio.stores.dynamodb import DynamoDBStore + +store = DynamoDBStore( + table_name="kv-store", + region_name="us-east-1" +) +``` + +**Installation:** + +```bash +pip install py-key-value-aio[dynamodb] +``` + +**Use Cases:** + +- AWS-native applications +- Serverless architectures +- Global distribution +- Managed infrastructure + +**Characteristics:** + +- Fully managed +- Auto-scaling +- Global tables +- Pay-per-use pricing +- Stable storage format: **Unstable** + +--- + +### ElasticsearchStore + +Full-text search engine used as a key-value store. + +```python +from key_value.aio.stores.elasticsearch import ElasticsearchStore + +store = ElasticsearchStore( + url="https://localhost:9200", + api_key="your-api-key", + index="kv-store" +) +``` + +**Installation:** + +```bash +pip install py-key-value-aio[elasticsearch] +``` + +**Use Cases:** + +- Applications already using Elasticsearch +- Need for search capabilities +- Analytics and logging + +**Characteristics:** + +- Search capabilities +- Distributed by default +- Rich querying +- Stable storage format: **Unstable** + +--- + +### MongoDBStore + +Document database used as a key-value store. + +```python +from key_value.aio.stores.mongodb import MongoDBStore + +store = MongoDBStore(url="mongodb://localhost:27017/test") +``` + +**Installation:** + +```bash +pip install py-key-value-aio[mongodb] +``` + +**Use Cases:** + +- Applications already using MongoDB +- Document-oriented data +- Flexible schemas + +**Characteristics:** + +- Document storage +- Rich querying +- Horizontal scaling +- Stable storage format: **Unstable** + +--- + +### MemcachedStore + +High-performance distributed memory caching system. + +```python +from key_value.aio.stores.memcached import MemcachedStore + +store = MemcachedStore(host="127.0.0.1", port=11211) +``` + +**Installation:** + +```bash +pip install py-key-value-aio[memcached] +``` + +**Use Cases:** + +- Distributed caching +- Session storage +- High-throughput caching + +**Characteristics:** + +- Very fast +- Simple protocol +- Distributed by design +- No persistence +- Stable storage format: **Unstable** + +--- + +## Choosing a Store + +### Development + +**Recommended:** `MemoryStore` or `DiskStore` + +- Fast iteration +- No setup required +- Easy debugging + +```python +# Development +from key_value.aio.stores.memory import MemoryStore +store = MemoryStore() +``` + +### Production Caching + +**Recommended:** `RedisStore` or `ValkeyStore` + +- High performance +- Distributed +- Production-ready +- Stable storage format + +```python +# Production caching +from key_value.aio.stores.redis import RedisStore +store = RedisStore(url="redis://localhost:6379/0") +``` + +### Long-Term Storage + +**Recommended:** Stores with **Stable** stability rating + +- `RedisStore` +- `ValkeyStore` +- `DiskStore` +- `MultiDiskStore` +- `KeyringStore` + +Avoid unstable stores for data you can't afford to lose or migrate. + +### Sensitive Data + +**Recommended:** `KeyringStore` or `VaultStore` + +- OS-level encryption +- Secure by default +- Audit logging (Vault) + +```python +# Sensitive data +from key_value.aio.stores.keyring import KeyringStore +store = KeyringStore(service_name="my-app") +``` + +### Serverless/Cloud + +**Recommended:** `DynamoDBStore` (AWS) + +- Fully managed +- Auto-scaling +- No servers to maintain + +```python +# AWS Lambda +from key_value.aio.stores.dynamodb import DynamoDBStore +store = DynamoDBStore(table_name="kv-store", region_name="us-east-1") +``` + +## Store Compatibility + +All stores implement the same protocol, making it easy to switch: + +```python +# Development +store = MemoryStore() + +# Production +store = RedisStore(url="redis://localhost:6379/0") + +# Your code works with both! +await store.put(key="user:123", value={"name": "Alice"}, collection="users") +``` + +See the [API Reference](api/stores.md) for complete store documentation. diff --git a/docs/wrappers.md b/docs/wrappers.md index 141d1895..ee595c63 100644 --- a/docs/wrappers.md +++ b/docs/wrappers.md @@ -4,6 +4,25 @@ Wrappers are a powerful feature of py-key-value that allow you to add functionality to any key-value store. Wrappers implement the `AsyncKeyValue` protocol, so they can be used anywhere a store can be used. +## Available Wrappers + +| Wrapper | Description | +|---------|-------------| +| [CompressionWrapper](#compressionwrapper) | Compress values before storing and decompress on retrieval | +| [FernetEncryptionWrapper](#fernetencryptionwrapper) | Encrypt values before storing and decrypt on retrieval | +| [FallbackWrapper](#fallbackwrapper) | Fallback to a secondary store when the primary store fails | +| [LimitSizeWrapper](#limitsizewrapper) | Limit the size of entries stored in the cache | +| [LoggingWrapper](#loggingwrapper) | Log the operations performed on the store | +| [PassthroughCacheWrapper](#passthroughcachewrapper) | Wrap two stores to provide a read-through cache | +| [PrefixCollectionsWrapper](#prefixcollectionswrapper) | Prefix all collections with a given prefix | +| [PrefixKeysWrapper](#prefixkeyswrapper) | Prefix all keys with a given prefix | +| [ReadOnlyWrapper](#readonlywrapper) | Prevent all write operations on the underlying store | +| [RetryWrapper](#retrywrapper) | Retry failed operations with exponential backoff | +| [SingleCollectionWrapper](#singlecollectionwrapper) | Wrap a store to only use a single collection | +| [TTLClampWrapper](#ttlclampwrapper) | Clamp the TTL to a given range | +| [StatisticsWrapper](#statisticswrapper) | Track operation statistics for the store | +| [TimeoutWrapper](#timeoutwrapper) | Add timeout protection to store operations | + ## What Are Wrappers? Wrappers follow the decorator pattern - they wrap around a key-value store and @@ -32,7 +51,7 @@ Wrappers execute in the order they are stacked: - **Writes** (put, delete): Outer wrapper → Inner wrapper → Store - **Reads** (get, ttl): Store → Inner wrapper → Outer wrapper -## Available Wrappers +## Wrapper Details ### CompressionWrapper diff --git a/mkdocs.yml b/mkdocs.yml index c3ea4d9c..13726dae 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -67,6 +67,7 @@ markdown_extensions: nav: - Home: index.md - Getting Started: getting-started.md + - Stores: stores.md - Wrappers: wrappers.md - Adapters: adapters.md - API Reference: