88 lines
5.5 KiB
Markdown
88 lines
5.5 KiB
Markdown
|
|
# Research Synthesis — In-Browser Swactor Runtime
|
||
|
|
|
||
|
|
## Ecosystem Landscape
|
||
|
|
|
||
|
|
No established Rust actor framework runs natively in browsers. The closest projects:
|
||
|
|
|
||
|
|
- **Lunatic** — Erlang-inspired Wasm actor runtime using wasmtime (server-side, not browser). Uses preemptive scheduling and work-stealing. Not applicable to browser constraints.
|
||
|
|
- **wasmCloud** — CNCF distributed actor platform. Single-threaded actors, NATS-backed lattice. Cloud/edge focus, no browser target.
|
||
|
|
- **Actix** — Tokio-dependent, network stack doesn't compile for wasm32. Community attempts to port failed due to `net2`/tokio dependencies.
|
||
|
|
|
||
|
|
**Implication**: swactor would be the first Rust actor runtime with true multi-threaded browser execution via wasm-threads. This is a differentiated position.
|
||
|
|
|
||
|
|
## Existing Work in This Codebase
|
||
|
|
|
||
|
|
| Component | Status | Notes |
|
||
|
|
|-----------|--------|-------|
|
||
|
|
| `crates/wasm/` | Basic PoC | Hardcoded Counter/Relay actors, manual tick, u32-only messages |
|
||
|
|
| `no_random` feature | Working | Deterministic address generation without `getrandom` |
|
||
|
|
| `tick()` method | Working | Single-threaded tick for manual driving |
|
||
|
|
| Actor watching | In core | `ExitReason`, `ActorExited`, `on_actor_exit`, `WatchRegistry` |
|
||
|
|
| swactor-std | Complete | StdExtension, naming, groups, monitoring, supervisor |
|
||
|
|
|
||
|
|
## Platform Dependencies Analysis
|
||
|
|
|
||
|
|
### Works as-is with wasm-threads
|
||
|
|
- `crossbeam-queue` (ArrayQueue, SegQueue) — uses `core::sync::atomic`
|
||
|
|
- `std::sync::{Mutex, RwLock}` — stdlib uses futex on wasm with atomics
|
||
|
|
- `std::sync::atomic::*` — maps to wasm atomic instructions
|
||
|
|
- `Arc<T>` — works with atomics
|
||
|
|
- `std::sync::OnceLock` — works with atomics
|
||
|
|
|
||
|
|
### Requires platform abstraction (4 items)
|
||
|
|
1. `std::thread::spawn` → Web Worker via `web-sys::Worker`
|
||
|
|
2. `thread::park_timeout` / `Thread::unpark` → `Atomics.wait` / `Atomics.notify`
|
||
|
|
3. `thread::yield_now` → no-op (or `Atomics.wait(0)` as hint)
|
||
|
|
4. `std::time::Instant` → `web_time::Instant` (drop-in crate)
|
||
|
|
|
||
|
|
## Priority Ranking
|
||
|
|
|
||
|
|
### P0 — Must Have (enables everything else)
|
||
|
|
|
||
|
|
1. **Platform abstraction layer** — cfg-gated replacements for thread spawn, park/unpark, yield, Instant. Core swactor compiles for wasm32 with atomics.
|
||
|
|
2. **Single-worker browser runtime** — Prove the runtime works in a browser. One Web Worker, auto-scheduled tick loop, generic JS API for spawn/send/recv.
|
||
|
|
3. **Multi-worker parallelism** — N Web Workers sharing runtime state via SharedArrayBuffer. Full utilization of browser CPU cores.
|
||
|
|
|
||
|
|
### P1 — Should Have (full actor system)
|
||
|
|
|
||
|
|
4. **Actor watching in browser** — Death notifications, exit reasons. Already in core, just needs to compile and pass wasm tests.
|
||
|
|
5. **swactor-std in browser** — Naming, groups, monitoring extensions. Compile and test for wasm32.
|
||
|
|
6. **Stats and introspection** — Runtime stats accessible from JS. Worker info, actor counts, message throughput.
|
||
|
|
|
||
|
|
### P2 — Important (distributed peer)
|
||
|
|
|
||
|
|
7. **WebSocket transport** — Adapter implementing swactor's transport traits over WebSocket. Browser node joins a distributed cluster.
|
||
|
|
8. **Browser-to-browser transport foundation** — WebRTC DataChannel scaffolding for future STUN/TURN.
|
||
|
|
|
||
|
|
### P3 — Nice to Have (developer experience)
|
||
|
|
|
||
|
|
9. **TypeScript type generation** — Derive TS interfaces from Rust actor message types.
|
||
|
|
10. **Build tooling** — wasm-pack wrapper script, example project template, CI configuration.
|
||
|
|
11. **Browser dev tools** — Actor inspector, message flow visualization, performance profiling.
|
||
|
|
|
||
|
|
### P4 — Future (out of scope for this feature phase)
|
||
|
|
|
||
|
|
12. **STUN/TURN integration** — Full NAT traversal for peer-to-peer browser connections.
|
||
|
|
13. **Hot code reload** — Swap actor implementations without restarting the runtime.
|
||
|
|
14. **Wasm component model** — Migrate from wasm-bindgen to component model when stabilized.
|
||
|
|
|
||
|
|
## Key Design Decisions
|
||
|
|
|
||
|
|
| Decision | Choice | Rationale |
|
||
|
|
|----------|--------|-----------|
|
||
|
|
| Threading model | SharedArrayBuffer + wasm-threads | swactor's shared-memory architecture (Arc, crossbeam queues, atomics) maps directly. postMessage isolation would require a rewrite. |
|
||
|
|
| Scheduling | `setTimeout(0)` tight loop | `requestAnimationFrame` caps at 60Hz. setTimeout(0) gives ~4ms resolution, sufficient for actor ticks. For rendering-coupled actors, RAF can be opt-in. |
|
||
|
|
| Actor definition | Rust only | Keeps the type system intact. JS actors would require dynamic dispatch and lose compile-time guarantees. |
|
||
|
|
| Platform abstraction approach | cfg-gated type aliases + inline functions | Minimal invasion. No trait-based HAL, no new modules. Just swap `std::time::Instant` → `web_time::Instant` etc. |
|
||
|
|
| Browser crate location | New `crates/wasm-browser/` | Clean separation from the existing PoC. The old `crates/wasm/` can be deprecated or kept as a minimal example. |
|
||
|
|
|
||
|
|
## Risk Assessment
|
||
|
|
|
||
|
|
| Risk | Likelihood | Impact | Mitigation |
|
||
|
|
|------|-----------|--------|------------|
|
||
|
|
| crossbeam-queue doesn't compile for wasm32+atomics | Low | High | Test early in Stage 1. Fallback: thin wrapper over `VecDeque` behind cfg. |
|
||
|
|
| COOP/COEP headers break third-party integrations | Medium | Medium | Document clearly. This is the standard trade-off for SharedArrayBuffer apps. |
|
||
|
|
| Nightly Rust + build-std is unstable | Medium | Medium | Pin to a known-good nightly. Revisit when wasm-threads stabilizes. |
|
||
|
|
| Web Worker spawn latency | Low | Low | Spawn workers eagerly at runtime init, not per-actor. |
|
||
|
|
| Browser compatibility gaps | Low | Medium | Target Chrome/Firefox/Safari latest. All support SharedArrayBuffer since 2021. |
|