%20(1).png)
<div align="center">
<h1>Sprite Engine</h1>
<p><strong>A fault-tolerant actor runtime for Rust. Like React, but for concurrent systems.</strong></p>
[On Crates](https://crates.io/crates/sprite-core)
<p>
<a href="https://www.rust-lang.org"><img src="https://img.shields.io/badge/Rust-2021-orange?style=for-the-badge&logo=rust&logoColor=white" alt="Rust 2021"/></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue?style=for-the-badge&logo=apache" alt="License Apache 2.0"/></a>
<a href="https://github.com/dragprog/sprite-engine"><img src="https://img.shields.io/badge/Build-Passing-brightgreen?style=for-the-badge&logo=github-actions" alt="Build Passing"/></a>
<a href="https://github.com/dragprog/sprite-engine"><img src="https://img.shields.io/badge/Fault_Tolerance-100%25-success?style=for-the-badge" alt="Fault Tolerance 100%"/></a>
<a href="https://github.com/dragprog/sprite-engine"><img src="https://img.shields.io/badge/Recovery-<50ns-violet?style=for-the-badge" alt="Recovery <50ns"/></a>
</p>
</div>
---
## ⚡ What is Sprite?
Sprite is a **Rust library** for building fault-tolerant, concurrent actor systems with a clean, declarative API inspired by React.
Instead of writing complex supervision trees and manual error handling, you write **actor components** — pure setup closures that declare state, message handlers, and children. If an actor panics, Sprite automatically resurrects it in **under 50 nanoseconds** with its state intact.
---
## 🚀 Quick Start
```rust
use sprite_core::{Engine, Message};
fn main() {
let engine = Engine::new();
let counter = engine.spawn("counter", |ctx| {
// Like React's useState — survives crashes
let count = ctx.use_state("count", 0i64);
ctx.on_message(move |msg| {
if msg == "inc" {
count.update(|c| c + 1);
println!("count = {}", count.get());
}
});
});
counter.send(Message::text("inc"));
counter.send(Message::text("inc"));
}
```
---
## 🧩 Core Concepts
| `Engine` | `createRoot` | The runtime that mounts and manages actors |
| `engine.spawn(name, \|ctx\| { ... })` | `<Component />` | Creates an actor from a setup closure |
| `ctx.use_state(key, initial)` | `useState` | Declares typed state that survives crashes |
| `ctx.use_scratch(initial)` | `useRef` | Ephemeral value wiped on recovery |
| `ctx.on_message(\|msg\| { ... })` | `onClick` / event handler | Registers a message handler |
| `ctx.on_panic(\| \| { ... })` | `componentDidCatch` | Runs after each panic recovery |
| `ctx.on_mount(\| \| { ... })` | `useEffect([], ...)` | Runs once on first start |
| `ctx.on_unmount(\| \| { ... })` | cleanup function | Runs on graceful shutdown |
| `ctx.spawn(name, ...)` | child components | Spawns nested actors |
| `ctx.send_to(id, msg)` | props callback | Sends a message to another actor |
| `ctx.send_named(name, msg)` | — | Sends to a named actor |
| `ctx.poll()` | — | Non-blocking message check |
| `ctx.sleep(dur)` | — | Yield without blocking thread |
| `Handle::send(msg)` | `setState` / props | Sends a message to an actor |
| `Handle::send_msg(any)` | — | Send any `IntoMessage` type |
| `Handle::request(msg, timeout)` | `fetch` | Request/response pattern |
---
## 🔥 Fault Tolerance
```
[ Panic in Actor ]
│
▼
catch_unwind catches it (~0.05ms)
│
▼
Arena reset (~1ns)
│
▼
State already intact (0ns — lives in shared store)
│
▼
Setup closure re-runs (~1ms)
│
▼
Actor Fully Restored (< 50ns for recovery core)
```
State created via `use_state` lives in a shared store outside the actor thread, so it **survives panics automatically**. The actor's scratch allocations (via `bumpalo`) are reset, but your data is safe.
---
## 🛡️ Circuit Breaker
If an actor panics more than **10 times in 5 seconds**, Sprite trips a circuit breaker and halts it — preventing infinite crash loops.
```rust
// After 10 recoveries, this actor stops.
});
```
---
## 📦 Installation
```toml
[dependencies]
sprite-core = { git = "https://github.com/dragprog/sprite-engine" }
```
---
## 🏗️ Advanced Examples
### Actor Pool (load balancing)
```rust
use sprite_core::{Engine, Message, Pool};
let engine = Engine::new();
println!("Worker {} processing: {:?}", ctx.id(), task);
});
});
for i in 0..100 {
pool.send(Message::int(i));
}
```
### Broadcast
```rust
engine.broadcast(Message::text("shutdown"));
```
### Named Actors
```rust
});
engine.send_named("logger", Message::text("hello"));
assert_eq!(engine.lookup("logger"), Some(id));
```
### Timer
```rust
use sprite_core::Timer;
use std::time::Duration;
Timer::send_after(handle.tx.clone(), Duration::from_secs(5), Message::text("timeout"));
```
### Builder API
```rust
use sprite_core::{Engine, ActorBuilder};
})
.arena_size(1024 * 128)
.max_recoveries(5)
.recovery_window(Duration::from_secs(10))
.spawn(&engine);
```
---
## 🧪 Running Tests
```bash
git clone https://github.com/dragprog/sprite-engine.git
cd sprite-engine
cargo test --workspace
cargo bench --bench recovery_speed
cargo bench --bench mailbox_throughput
cargo run --example counter
cargo run --example pool
cargo run --example broadcast
```
---
## 📊 Benchmarks
| `recovery_speed` | Panic → full restore |
| `mailbox_throughput` | Messages / second |
---
## 🤝 Contributing
1. Fork the repo (`git checkout -b feature/cool-thing`).
2. Keep the API surface minimal and ergonomic.
3. Ensure tests pass (`cargo test`).
4. Submit a PR with a concise breakdown.
---
## 📄 License
Distributed under the **Apache License 2.0**. See [`LICENSE`](LICENSE) for details.