Overview¶
๐ Why Redis?¶
Redis is an in-memory key-value store designed for fast caching, queues, and real-time data processing. It offers high speed, atomic operations, and excellent scalability, making it ideal for low-latency applications.
Performance Benefits
Redis provides microsecond-level latency and can handle millions of operations per second, making it perfect for real-time applications.
โก The Power of Pydantic¶
Pydantic has revolutionized Python data validation and serialization. There are already many libraries that use Pydantic for ORM: Beanie (MongoDB), FastAPI (HTTP server), etc. However, the current packages to support Redis are somewhat lacking.
Type Safety
Pydantic's strength lies in its automatic validation, type safety, and developer-friendly API that makes working with complex data structures intuitive and safe.
๐ฏ Introducing Rapyer¶
Rapyer bridges the gap between Redis's performance and Pydantic's type safety, creating a powerful combination optimized for real-world applications.
๐ง Wide Variety of Field Support¶
Rapyer supports a wide variety of field types and offers users the ability to perform complex atomic actions on these fields:
- Strings - Optimized Redis string storage
- Integers - Native Redis number handling
- Floats - Precise decimal operations
- Booleans - Efficient boolean storage
- Lists - Full atomic list operations
- Dictionaries - Atomic dict updates and lookups
- Sets - Redis set operations with Python interface
- RedisStr - Enhanced string type with IDE autocomplete
- RedisList - List type with atomic operations
- RedisDict - Dictionary type with atomic operations
Custom Types
You can also create your own custom types or decide how to save the data in Redis. Other types are also supported - essentially we support any type that can be serialized to pickle, however, they can be used to perform atomic operations.
โ๏ธ Atomic Operations for Race Condition Prevention¶
Every operation in Rapyer is designed to be atomic and safe in concurrent environments:
# All operations are atomic - no race conditions possible
await user.tags.aappend("python") # Atomic list append
await user.metadata.aupdate(role="dev") # Atomic dict update
user.score += 10
await user.score.asave() # Atomic increment
Concurrency Safe
For complex multi-field operations, Rapyer provides lock context managers and pipeline operations that ensure consistency across multiple changes.
๐ Quick Example¶
import asyncio
from rapyer import AtomicRedisModel
from typing import List, Dict
class User(AtomicRedisModel):
name: str
age: int
tags: List[str] = []
metadata: Dict[str, str] = {}
async def main():
# Create and save
user = User(name="Alice", age=25)
await user.asave()
# Atomic operations
await user.tags.aappend("developer") # (1)!
await user.tags.aextend(["python", "redis"]) # (2)!
await user.metadata.aupdate(team="backend", level="senior") # (3)!
# Load and verify
loaded = await User.aget(user.key)
print(f"User: {loaded.name}, Tags: {loaded.tags}") # (4)!
if __name__ == "__main__":
asyncio.run(main())
- Add a single tag atomically
- Extend with multiple tags in one operation
- Update multiple metadata fields atomically
- Load the complete model from Redis
Core Philosophy
This example demonstrates Rapyer's core philosophy: combine Redis performance with Pydantic safety, all while maintaining atomic operations that prevent data corruption in concurrent applications.
Why Choose Rapyer?¶
Comparison with Other Redis ORMs¶
| Feature | Rapyer | Redis OM | pydantic-redis | orredis |
|---|---|---|---|---|
| ๐ Atomic Operations | โ Built-in for all operations | โ Manual transactions only | โ Manual transactions only | โ Manual transactions only |
| ๐ Lock Context Manager | โ
Automatic with async with model.alock() |
โ Manual implementation required | โ Manual implementation required | โ Manual implementation required |
| โก Pipeline Operations | โ
True atomic batching with model.apipeline() |
โ ๏ธ Basic pipeline support | โ No pipeline support | โ No pipeline support |
| ๐ Universal Type Support | โ Native + automatic serialization for any type | โ ๏ธ HashModel vs JsonModel limitations | โ ๏ธ Limited complex types | โ ๏ธ Limited complex types |
| ๐ Race Condition Safe | โ Built-in prevention with Lua scripts | โ Manual implementation required | โ Manual implementation required | โ Manual implementation required |
| ๐ฆ Redis JSON Native | โ Optimized JSON operations | โ Via JsonModel only | โ Hash-based | โ Hash-based |
| โ๏ธ Pydantic v2 Support | โ Full compatibility | โ Recent support | โ ๏ธ Limited support | โ ๏ธ Basic support |
| ๐ฏ Type Safety | โ Complete validation | โ Good validation | โ Good validation | โ ๏ธ Basic validation |
| โก Performance | โ Optimized operations | โ Good performance | โ Standard | โ Rust-optimized |
| ๐ง Nested Model Support | โ Full Redis functionality preserved | โ ๏ธ Limited nesting | โ Advanced relationships | โ ๏ธ Basic support |
| ๐๏ธ Custom Primary Keys | โ Field annotations | โ ULIDs only | โ Custom fields | โ Custom fields |
| ๐งช Extensive Test Coverage | โ 90%+ comprehensive tests with CI | โ ๏ธ Basic testing with CI | โ ๏ธ Limited test coverage | โ ๏ธ Basic test suite |