A memory-safe, high-performance Rust port of Redis's Asynchronous Event (AE) loop system.
RAE (Rust Asynchronous Events) is a faithful port of Redis's battle-tested event loop implementation, bringing the same performance and reliability to Rust while leveraging memory safety guarantees and zero-cost abstractions.
The Redis AE event loop is the heart of Redis's high-performance networking, handling millions of concurrent connections with minimal overhead. This Rust implementation maintains API compatibility while eliminating memory safety issues inherent in C.
- 🚀 High Performance - Zero-cost abstractions with performance matching original C implementation
- 🛡️ Memory Safe - Leverages Rust's ownership system to eliminate memory corruption and data races
- 🔄 Cross Platform - Support for Linux (epoll), BSD/macOS (kqueue), and universal (select) backends
- ⚡ Asynchronous - Non-blocking I/O with efficient event dispatching
- 🔧 API Compatible - Drop-in replacement for Redis AE with familiar interface
- 📊 Production Ready - Based on Redis's proven event loop architecture
| Platform | Backend | Status |
|---|---|---|
| Linux | epoll | 🚧 Planned |
| macOS/BSD | kqueue | 🚧 Planned |
| Universal | select | 🚧 Planned |
| Solaris | event ports | 🚧 Planned |
use rae::{EventLoop, FileEvent, EventMask};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create event loop
let mut event_loop = EventLoop::new(1024)?;
// Register file events
event_loop.create_file_event(
fd,
EventMask::READABLE,
|event_loop, fd, client_data, mask| {
// Handle read event
println!("Data ready to read on fd {}", fd);
},
None,
)?;
// Register time events
event_loop.create_time_event(
1000, // milliseconds
|event_loop, id, client_data| {
println!("Timer event fired!");
0 // Don't reschedule
},
None,
None,
)?;
// Run event loop
event_loop.main();
Ok(())
}Add to your Cargo.toml:
[dependencies]
rae = "0.1.0"Or install via cargo:
cargo add raeRAE follows Redis's proven event loop architecture:
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ File Events │ │ Time Events │ │ Platform Layer │
│ │ │ │ │ │
│ • Read/Write │ │ • Timers │ │ • epoll (Linux) │
│ • Error │────┼─ • Scheduling │────┼─ • kqueue (BSD) │
│ • Callbacks │ │ • Callbacks │ │ • select (Unix) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
│
┌────────▼────────┐
│ Event Loop │
│ │
│ • Processing │
│ • Dispatching │
│ • Lifecycle │
└─────────────────┘
- EventLoop: Central coordinator managing all events and dispatching
- FileEvent: Handles I/O events on file descriptors (sockets, pipes, etc.)
- TimeEvent: Manages timer-based events and scheduling
- Platform Backends: OS-specific implementations (epoll, kqueue, select)
RAE is designed for high performance with:
- Minimal Allocations: Reuses memory where possible during event processing
- Efficient Dispatching: O(1) event dispatching for most operations
- Platform Optimization: Uses the most efficient event notification for each OS
- Zero Copy: Avoids unnecessary data copying in hot paths
🚧 Pre-Alpha - Currently in initial development
- Phase 1: Core event loop structures and API
- Phase 2: Platform backend implementations
- Phase 3: Redis test suite port and validation
- Phase 4: Performance optimization and benchmarking
- Phase 5: Production hardening and documentation
See AGENTS.md for detailed implementation plan.
use rae::{EventLoop, EventMask};
use std::net::TcpListener;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080")?;
listener.set_nonblocking(true)?;
let mut event_loop = EventLoop::new(1024)?;
// Accept connections
event_loop.create_file_event(
listener.as_raw_fd(),
EventMask::READABLE,
|el, fd, _, _| {
// Accept and register new client
// ...
},
None,
)?;
event_loop.main();
Ok(())
}use rae::EventLoop;
use std::time::Instant;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut event_loop = EventLoop::new(64)?;
let start = Instant::now();
// Recurring timer every second
event_loop.create_time_event(
1000,
move |el, id, _| {
println!("Tick: {}s elapsed", start.elapsed().as_secs());
1000 // Reschedule in 1000ms
},
None,
None,
)?;
event_loop.main();
Ok(())
}Contributions are welcome! Please see our contribution guidelines.
git clone https://github.com/pnodet/rae.git
cd rae
cargo buildcargo test
cargo test --features integration-testscargo benchLicensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
This project is inspired by and based on the Redis event loop implementation. Redis is licensed under the BSD 3-Clause License.