Rapyer
Redis Atomic Pydantic Engine Reactor
An async Redis ORM that provides atomic operations for complex data models
📚 Full Documentation | Installation | Examples | API Reference
What is Rapyer?
Rapyer (Redis Atomic Pydantic Engine Reactor) is a modern async Redis ORM that enables atomic operations on complex data models. Built with Pydantic v2, it provides type-safe Redis interactions while maintaining data consistency and preventing race conditions.
Key Features
🚀 Atomic Operations - Built-in atomic updates for complex Redis data structures
⚡ Async/Await - Full asyncio support for high-performance applications
🔒 Type Safety - Complete type validation using Pydantic v2
🌐 Universal Types - Native optimization for primitives, automatic serialization for complex types
🔄 Race Condition Safe - Lock context managers and pipeline operations
📦 Redis JSON - Efficient storage using Redis JSON with support for nested structures
Installation
pip install rapyer
Requirements:
- Python 3.10+
- Redis server with JSON module
- Pydantic v2
Quick Start
import asyncio
from rapyer.base 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 a user
user = User(name="John", age=30)
await user.asave()
# Atomic operations that prevent race conditions
await user.tags.aappend("python")
await user.tags.aextend(["redis", "pydantic"])
await user.metadata.aupdate(role="developer", level="senior")
# Load user from Redis
loaded_user = await User.aget(user.key)
print(f"User: {loaded_user.name}, Tags: {loaded_user.tags}")
# Atomic operations with locks for complex updates
async with user.alock("update_profile") as locked_user:
locked_user.age += 1
await locked_user.tags.aappend("experienced")
# Changes saved atomically when context exits
if __name__ == "__main__":
asyncio.run(main())
Core Concepts
Atomic Operations
Rapyer ensures data consistency with built-in atomic operations:
# These operations are atomic and race-condition safe
await user.tags.aappend("python") # Add to list
await user.metadata.aupdate(role="dev") # Update dict
Lock Context Manager
For complex multi-field updates:
async with user.alock("transaction") as locked_user:
# Locked actions, only single process can be inside this lock section at a time
call_new_action()
Pipeline Operations
Batch multiple operations for performance:
async with user.apipeline() as pipelined_user:
await pipelined_user.tags.aappend("redis")
await pipelined_user.metadata.aupdate(level="senior")
# Executed as single atomic transaction
Type Support
Rapyer supports all Python types with automatic serialization:
- Native types (
str,int,List,Dict) - Optimized Redis operations - Complex types (
dataclass,Enum,Union) - Automatic pickle serialization - Nested models - Full Redis functionality preserved
from dataclasses import dataclass
from enum import Enum
@dataclass
class Config:
debug: bool = False
class User(AtomicRedisModel):
name: str = "default"
scores: List[int] = []
config: Config = Config() # Auto-serialized
# All types work identically
user = User()
await user.config.set(Config(debug=True)) # Automatic serialization
await user.scores.aappend(95) # Native Redis operation
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 | ✅ 100%+ comprehensive tests with CI | ⚠️ Basic testing with CI | ⚠️ Limited test coverage | ⚠️ Basic test suite |
🏆 What Makes Rapyer Unique
True Atomic Operations Out of the Box
# Rapyer - Atomic by default
await user.tags.aappend("python") # Race-condition safe
await user.metadata.aupdate(role="dev") # Always atomic
# Others - Manual transaction management required
async with redis.apipeline() as pipe: # Manual setup
pipe.multi() # Manual transaction
# ... manual Redis commands # Error-prone
await pipe.execute()
Intelligent Lock Management
# Rapyer - Automatic lock context
async with user.alock("profile_update") as locked_user:
locked_user.balance -= 50
locked_user.transaction_count += 1
# All changes saved atomically on exit
# Others - Manual lock implementation
lock_key = f"lock:{user.key}"
while not await redis.set(lock_key, token, nx=True): # Manual retry logic
await asyncio.sleep(0.1) # Race conditions possible
# ... manual cleanup required
Universal Type System
# Rapyer - Any Python type works identically
class User(AtomicRedisModel):
scores: List[int] = [] # Native Redis operations
config: MyDataClass = MyDataClass() # Auto-serialized
metadata: Dict[str, Any] = {} # Native Redis operations
# All types support the same atomic operations
await user.config.set(new_config) # Automatic serialization
await user.scores.aappend(95) # Native Redis LIST operations
await user.metadata.aupdate(key="val") # Native Redis JSON operations
Pipeline with True Atomicity
# Rapyer - Everything in pipeline is atomic
async with user.apipeline() as pipelined_user:
await pipelined_user.tags.aappend("redis")
await pipelined_user.metadata.aupdate(level="senior")
# Single atomic transaction - either all succeed or all fail
# Others - No built-in pipeline abstraction for ORM operations
Learn More
- 📖 Documentation - Complete guide and API reference
- 🗺️ Roadmap - Future features and development plans
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. Thanks for @Mizaro and @oazmiry this would not have been possible without you.
License
MIT License
Metadata
Release files for rapyer 1.3.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rapyer-1.3.6.tar.gz | 3.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rapyer-1.3.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.3 MB
Release files / rapyer-1.3.6.tar.gz
| Download URL | rapyer-1.3.6.tar.gz |
|---|---|
| Size | 3.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f3c344003c60bd5c1d94f3f01f11dfc24c9df3dca9714097280e4d778eb816b4
|
|
BLAKE2b-256 checksum How to use checksums |
db7374a65b66eb5f64aa38d4e3e3808b1cb3b0d0d7a4bbf9be790436439333e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 17, 2026.
Transparency logRelease files / rapyer-1.3.6-py3-none-any.whl
| Download URL | rapyer-1.3.6-py3-none-any.whl |
|---|---|
| Size | 88.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0a0999266430d4293e3ddf0826be76f771f3cab97bce056c46591d7c303cab4c
|
|
BLAKE2b-256 checksum How to use checksums |
8a6b97030660f496de546319995256c40c58d24a78bd2a4ab44b4dcd018beb8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 17, 2026.
Transparency log