73 lines
3.2 KiB
Markdown
73 lines
3.2 KiB
Markdown
|
|
# Phase 1 actor prototype
|
||
|
|
|
||
|
|
Run the feasibility probes and two-actor demonstration with:
|
||
|
|
|
||
|
|
```sh
|
||
|
|
cargo run -p runa
|
||
|
|
mise run pre-commit
|
||
|
|
```
|
||
|
|
|
||
|
|
The executable loads [counter.rn](../runa-std/actors/counter.rn), spawns two
|
||
|
|
actors sharing one implementation, and sends a structured message. The sender
|
||
|
|
commits state 1 and sends a message that moves the receiver from state 10 to 15.
|
||
|
|
|
||
|
|
## Current contracts
|
||
|
|
|
||
|
|
- `runa-actor` owns actor, mailbox and implementation IDs, structured messages,
|
||
|
|
snapshots, statuses and lifecycle events.
|
||
|
|
- `runa-rune` owns compilation and typed bounded invocation execution.
|
||
|
|
- `runa-runtime` owns implementation registration, queues, private committed
|
||
|
|
state, scheduling, message effects and lifecycle coordination.
|
||
|
|
- `runa` composes the experiment and demonstration.
|
||
|
|
|
||
|
|
An implementation is published once under an ID. Actors reference that exact
|
||
|
|
implementation. IDs and incarnation counters use checked increments.
|
||
|
|
|
||
|
|
Prototype state is an `i64`; messages contain integer `kind` and `value`
|
||
|
|
fields. Rune handlers have this deliberately restricted interface:
|
||
|
|
|
||
|
|
```text
|
||
|
|
handle(state, kind, value) -> (new_state, [(target_actor_id, kind, value), ...])
|
||
|
|
```
|
||
|
|
|
||
|
|
The returned effect vector describes sends; handlers cannot access the runtime
|
||
|
|
or directly mutate committed state. General schema/versioned values and
|
||
|
|
capability-bearing contexts are future work.
|
||
|
|
|
||
|
|
## Scheduling and lifecycle
|
||
|
|
|
||
|
|
`tick(nonzero_budget)` gives each runnable actor one bounded slice in ID order.
|
||
|
|
FIFO queues are bounded, including the reserved message in capacity accounting.
|
||
|
|
A queued message is reserved when its invocation starts. Subsequent messages
|
||
|
|
stay queued, including while the actor awaits. A wake marks an awaiting actor
|
||
|
|
runnable; the caller still needs to drive ticks.
|
||
|
|
|
||
|
|
Successful handlers validate every send target and its aggregate queue
|
||
|
|
capacity before updating state, acknowledging the reserved message, and
|
||
|
|
enqueueing effects. Invalid effects fail the actor without partial sends or a
|
||
|
|
state commit. This all-or-nothing behavior is in-memory only, not a durable
|
||
|
|
transaction.
|
||
|
|
|
||
|
|
Runtime errors retain the last committed state and reserved message, set an
|
||
|
|
observable failed status, and emit a failure event. External sends return errors
|
||
|
|
for unknown, unavailable, or full actors.
|
||
|
|
|
||
|
|
Stopping drops the invocation, retaining committed state, mailbox and reserved
|
||
|
|
message. Restarting a stopped or failed actor preserves IDs, increments its
|
||
|
|
incarnation, and puts its reserved message at the front of the queue. Restart
|
||
|
|
is explicit; there is no automatic poison-message retry or supervision policy.
|
||
|
|
|
||
|
|
## Limits
|
||
|
|
|
||
|
|
This is not yet a full image: no persistent mailboxes, transactional outbox,
|
||
|
|
supervisors, hot upgrades, API server, GUI, or automatic image bootstrap.
|
||
|
|
The example default script is bundled through `include_str!`.
|
||
|
|
Messages are not accepted by stopped/failed actors.
|
||
|
|
|
||
|
|
Native functions must be nonblocking. Dropping a future proves cleanup only
|
||
|
|
for the controlled test operation, not rollback of arbitrary external effects.
|
||
|
|
Instruction slices cannot interrupt a native callback.
|
||
|
|
|
||
|
|
The [execution decision](decisions/0001-worker-local-execution.md) records the
|
||
|
|
scheduling trade-offs. Heap profiling and source-level debugging remain open.
|