fix: docs directory cleaning
This commit is contained in:
parent
7f05b03a76
commit
b432ea557d
7 changed files with 0 additions and 189 deletions
|
|
@ -1,74 +0,0 @@
|
|||
# Dead-Node Reprobe — Design & Rationale
|
||||
|
||||
## Problem
|
||||
|
||||
When a network partition heals, SWIM nodes on both sides may have declared each
|
||||
other Dead. The `alive_members()` filter excludes Dead nodes from probing
|
||||
targets, so neither side initiates communication — creating a **permanent split**
|
||||
even after connectivity is restored.
|
||||
|
||||
The existing refutation mechanism (incarnation bump on learning of own death
|
||||
declaration) handles resurrection correctly, but depends on someone *telling*
|
||||
the dead-declared node about its status. With no probes to dead nodes, nobody
|
||||
does.
|
||||
|
||||
## Solution: Independent Dead-Node Reprobe Cycle
|
||||
|
||||
Added a lightweight reprobe mechanism to `SwimProbe` that periodically pings
|
||||
dead nodes. The existing piggyback + refutation mechanism handles the rest:
|
||||
|
||||
1. **Reprober** pings dead node with piggybacked "you are Dead(inc=N)"
|
||||
2. **Target** receives piggyback, sees it's declared Dead → refutes → bumps incarnation
|
||||
3. **Target** replies with Ack carrying piggybacked "I'm Alive(new_inc)"
|
||||
4. **Reprober** applies piggyback → target transitions Dead→Alive
|
||||
|
||||
Key insight: we re-enqueue the death declaration in the dissemination queue
|
||||
before packing the reprobe ping's piggyback. Without this, the original death
|
||||
declaration's transmit budget would be long exhausted, and the piggyback would
|
||||
carry no useful membership info.
|
||||
|
||||
## Design Decisions
|
||||
|
||||
### Why inside SwimProbe (not SwimNode)?
|
||||
|
||||
- SwimProbe owns the tick counter, sequence counter, and member list access
|
||||
- All probe-related logic stays in one place
|
||||
- The reprobe is a simple independent cycle — doesn't interfere with ProbePhase
|
||||
|
||||
### Why no new wire messages?
|
||||
|
||||
- `SwimAction::SendPing` works identically for normal probes and reprobes
|
||||
- The ack from a reprobe targets a different sequence than the current probe
|
||||
cycle, so the probe state machine ignores it — but the piggyback is applied
|
||||
at the SwimNode layer before the probe state machine sees the ack
|
||||
|
||||
### Configuration
|
||||
|
||||
- `dead_reprobe_interval: u64` (default: 50 ticks, ~5× probe_interval)
|
||||
- Set to 0 to disable completely
|
||||
- Existing test configs use 0 to avoid interference with timing
|
||||
|
||||
## Files Changed
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `crates/distribution/src/swim/probe.rs` | `dead_reprobe_interval` in config, `maybe_reprobe_dead()` method |
|
||||
| `crates/distribution/src/swim/member_list.rs` | Added `dead_members()` |
|
||||
| `crates/distribution/src/swim/node.rs` | Re-enqueue death declaration in `translate_probe_actions` |
|
||||
| All `SwimConfig` struct literals | Added `dead_reprobe_interval` field |
|
||||
|
||||
## Edge Cases
|
||||
|
||||
- **Truly dead nodes**: Reprobe ping is lost (no ack), no harm done
|
||||
- **All members dead**: Reprobe cycles through them round-robin
|
||||
- **Concurrent reprobe + normal probe**: Independent, different sequences
|
||||
- **Dissemination budget**: Death re-enqueued fresh each reprobe, not stale
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
1. **Dead node grace period + resurrection timer**: More complex, adds new
|
||||
state tracking alongside suspicion timers. Rejected for simplicity.
|
||||
2. **Periodic re-join via seed nodes**: Requires seed node availability,
|
||||
doesn't work when seed is itself dead-declared. Rejected.
|
||||
3. **Direct liveness inference from Ping reception**: Would require changing
|
||||
`handle_ping` to special-case pings from dead nodes. More invasive.
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
# Wasm Actor
|
||||
|
||||
The `swactor-wasm-actor` crate runs WebAssembly guest code inside a swactor
|
||||
actor. The Wasm instance is sandboxed by [wasmtime](https://wasmtime.dev/).
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─ Runtime ──────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌─ WasmActor ──────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ Store<HostState> -- wasmtime store with outbox │ │
|
||||
│ │ Memory -- guest linear memory │ │
|
||||
│ │ alloc: TypedFunc -- guest allocator │ │
|
||||
│ │ handle: TypedFunc -- guest message handler │ │
|
||||
│ │ │ │
|
||||
│ │ impl ActorInterface for WasmActor │ │
|
||||
│ │ Incoming = ByteMessage │ │
|
||||
│ │ Response = () │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ Native Actors ─────────────────────────────────────────────────┐ │
|
||||
│ │ (can exchange ByteMessage with WasmActors normally) │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Message Flow
|
||||
|
||||
```
|
||||
Host Guest (Wasm)
|
||||
──── ────────────
|
||||
|
||||
ByteMessage arrives
|
||||
│
|
||||
├─1─ call alloc(len) ──────────► bump-allocate, return ptr
|
||||
│
|
||||
├─2─ write bytes at ptr ───────► (memory updated)
|
||||
│
|
||||
├─3─ call handle(ptr, len) ────► process message
|
||||
│ │
|
||||
│ ◄── swactor.send() ────────────┤ (0..N times)
|
||||
│ (buffered in HostState.outbox) │
|
||||
│ │
|
||||
├─4─ drain outbox ◄────────────── handle returns
|
||||
│
|
||||
v
|
||||
ctx.send(dest, ByteMessage) for each outbox entry
|
||||
```
|
||||
|
||||
## Guest Contract
|
||||
|
||||
Guests are standalone `wasm32-unknown-unknown` modules. They export three
|
||||
symbols and may import one:
|
||||
|
||||
| Direction | Module | Symbol | Signature |
|
||||
|-----------|--------|--------|-----------|
|
||||
| **export** | — | `memory` | linear memory |
|
||||
| **export** | — | `alloc` | `(i32) -> i32` |
|
||||
| **export** | — | `handle` | `(i32, i32) -> ()` |
|
||||
| **import** | `swactor` | `send` | `(i32, i32, i32) -> ()` |
|
||||
|
||||
The `send` import takes `(dest_ptr, payload_ptr, payload_len)` where
|
||||
`dest_ptr` points to a 32-byte `ActorAddress` in guest memory.
|
||||
|
||||
## Usage
|
||||
|
||||
```rust
|
||||
use swactor::runtime::{Runtime, RuntimeConfig};
|
||||
use swactor_wasm_actor::{ByteMessage, SharedEngine, WasmActorBuilder};
|
||||
|
||||
// Create a shared engine (once)
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
|
||||
// Build an actor from .wasm bytes
|
||||
let wasm_bytes = std::fs::read("my_guest.wasm").unwrap();
|
||||
let actor = WasmActorBuilder::new(engine, wasm_bytes)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
// Use it like any other actor
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
rt.send_to(addr, ByteMessage(b"hello".to_vec())).unwrap();
|
||||
rt.tick();
|
||||
```
|
||||
|
||||
## Sandboxing
|
||||
|
||||
The `SharedEngine` disables all optional Wasm proposals:
|
||||
|
||||
- Threads — disabled
|
||||
- SIMD / relaxed SIMD — disabled
|
||||
- Reference types — disabled
|
||||
- Multi-value — disabled
|
||||
- Bulk memory — **enabled** (required by most Rust/LLVM toolchains)
|
||||
|
||||
No WASI imports are linked. Guests have no access to the filesystem, network,
|
||||
clock, or random number generator. The only host function available is
|
||||
`swactor.send`.
|
||||
|
||||
## Where Things Live
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `crates/wasm-actor/src/lib.rs` | `ByteMessage` + re-exports |
|
||||
| `crates/wasm-actor/src/engine.rs` | `SharedEngine` — sandboxed wasmtime config |
|
||||
| `crates/wasm-actor/src/builder.rs` | `WasmActorBuilder` — compile, link, instantiate |
|
||||
| `crates/wasm-actor/src/actor.rs` | `WasmActor` — `ActorInterface` impl |
|
||||
| `crates/wasm-actor/src/error.rs` | `WasmActorError` |
|
||||
| `crates/wasm-actor/tests/guests/` | Three test guest crates (echo, double, silent) |
|
||||
| `crates/wasm-actor/tests/wasm_actor.rs` | 7 integration tests |
|
||||
Loading…
Reference in a new issue