Files
MetaCrate/docs/grid-agent-session.md
Chili Palmer adf5165033
Some checks failed
CI / rust-skia (Rust only) (push) Has been cancelled
CI / required (push) Has been cancelled
fix: harden OpenSim session readiness
2026-08-21 20:37:16 +02:00

79 lines
4.0 KiB
Markdown

# Grid-session supervision
Live integrated and split modes run through `SessionSupervisor`. Its injected
`GridSessionBackend` makes the lifecycle deterministic under a fake grid while
the `live-grid` adapter reuses `libremetaverse::NetworkManager` for native
login, event-queue readiness, disconnect callbacks, and logout.
The native login does not yield a session until the login response has populated
the existing inventory skeleton and a current simulator/UDP circuit exists.
The adapter then waits for that simulator's event queue before publishing full
readiness. Existing `GridClient` inventory/world managers and its single
movement-update owner remain the composition owners; the adapter never creates
duplicates. Only its generation-scoped readiness/disconnect subscriptions are
recreated, and their RAII guards are dropped before logout.
## States and reasons
| State | Transport connected | Agent ready | Exit condition |
| --- | --- | --- | --- |
| `stopped` | no | no | startup, resume, or force reconnect |
| `connecting` | no | no | login result, operator control, or cancellation |
| `degraded` | yes | no | readiness, disconnect, or operator control |
| `online` | yes | yes | readiness loss, disconnect, or operator control |
| `backoff` | no | no | cancellation-driven timer or operator control |
| `authentication-blocked` | no | no | resume/force reconnect or shutdown |
| `paused` | no | no | resume/force reconnect, logout, or shutdown |
| `shutting-down` | no | no | session logout, audit flush, and joined owner task |
Every transition carries a stable `SessionReason`; raw login responses, server
messages, credentials, capability URLs, and session tokens cannot enter the
failure or observation types. `SessionStatus` reports transport connectivity
and complete readiness separately.
Invalid credentials and invalid local login configuration stop automatic
retry. Transport failures, maintenance, kicks, simulator disconnects, and
server failures retry with exponential backoff. `reconnect.maximum_delay_seconds`
is a hard cap. A server retry hint is a minimum up to that cap. Per-instance
jitter is bounded by `jitter_basis_points`, preventing synchronized reconnects,
and a connection that remains up for `stable_reset_seconds` resets the failure
streak. A connected generation that does not reach full event-queue readiness
within `readiness_timeout_seconds` is logged out and retried instead of
remaining degraded indefinitely.
Backoff defaults are one second initially, 60 seconds maximum, 20 percent
jitter, a 30-second readiness deadline, and a 120-second stable reset window.
All waits use Tokio timers inside `select!` with cancellation/control; there are
no blocking sleeps.
## Generation and work safety
Each attempt receives a monotonically changing generation and cancellation
token. Session-scoped subscriptions, readiness ownership, and workers belong to
the returned `GridSession` and are closed once by its consuming `logout` method.
Late inference/tool results are accepted only when `accepts_result` sees their
exact generation in fully ready state.
While not ready, bounded read-only work may queue. Mutation work—including
nominally idempotent mutation—is rejected, because the supervisor cannot prove
that a previous policy authorization remains valid. Work IDs are deduplicated
across reconnects with a bounded recent-ID set, so reconnect never silently
duplicates an outbound response. Queued reads are released once into the new
generation.
## Shutdown
Shutdown first rejects new work and invalidates the generation token, which
cancels inference, tools, and scheduled consumers sharing it. It then consumes
the active session for one logout attempt, waits within
`timeouts.shutdown_seconds`, calls the backend's bounded audit-flush hook, and
joins the supervisor owner task. A late task is aborted and awaited by the
handle, so no task or socket is detached.
Focused deterministic verification:
```sh
cargo test --locked -p metacrate-grid-agent --lib session_tests
cargo clippy --locked -p metacrate-grid-agent --all-targets -- -D warnings
```