You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary:
mesh-admin reports the Rust actor-loop's state, but a Python actor's endpoint work runs detached from that loop -- `PythonActor::handle` hands the message off and returns, so `cell.status()` reads `idle` while Python user code is actively running (the TUI showed `Status: idle` for a busy actor). this adds a general `execution` introspection plane that both runtimes feed, so mesh-admin reports in-flight handler work truthfully without changing dispatch semantics; lifecycle `status` stays a separate plane.
the `execution` block is always present on `NodeProperties::Actor` and the HTTP DTO (count 0 when idle) and carries `active_handler_count` (the full live total across all invocations), `total_handler_names`, `oldest_active_handler`/`oldest_active_since`, and `active_handlers[]` (`{name, active_count, oldest_active_since}`, aggregated by endpoint name, sorted oldest-first, capped with an `active_handlers_truncated` flag). a core-owned `ExecutionRegistry` (a per-cell `DashMap<token, {name, started_at}>` plus an `AtomicU64`) on `InstanceCellState` owns storage and aggregation; `finished` is idempotent. composition is by kind: a cell with the registry installed self-reports (Python), otherwise the snapshot is derived from `ActorStatus::Processing` (Rust, count 0 or 1).
Python actors feed the registry through new `PyInstance._execution_started`/`_execution_finished` hooks that `_Actor.handle` brackets around the user-method call in a `try`/`finally`; the registry is eager-installed at the top of `PythonActor::init` so a live Python actor never falls back to the raw `Processing` path. the TUI renders an `Execution` section when `active_handler_count > 0`.
two operator-facing observability helpers ship alongside the surface (no core/DTO/TUI behavior change): `python/examples/execution_demo.py`, a run-and-watch dining-philosophers workload with real `think`/`eat` endpoints and a central `ForkManager`, so the `execution` surface can be watched live in the TUI without driving stdin -- browse a philosopher for `think`/`eat` turnover, the fork manager for `acquire xN` contention; and `logger.info` flight-recorder lines inside the handler bodies of `execution_workload` (and the demo) so the TUI flight-recorder pane shows recent activity for the observed actors instead of "No events".
Differential Revision: D107192488
Copy file name to clipboardExpand all lines: hyperactor/src/introspect.rs
+158Lines changed: 158 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -434,6 +434,23 @@ declare_attrs! {
434
434
desc:"Per-session reorder-buffer state from OrderedSender. Independent diagnostic from queue_depth; no arithmetic contract -- see IO-3. Absence vs Some({enabled: false}) is meaningful -- see IO-1.".into(),
/// In-flight execution state: the live invocations an actor is
439
+
/// currently handling. A second plane to lifecycle `status` --
440
+
/// `status` describes the Rust actor loop, `execution` answers "what
441
+
/// is this actor doing right now?" even when work runs detached from
442
+
/// the loop (e.g. concurrent Python endpoints).
443
+
///
444
+
/// Always present (count 0 when idle); composed once in
445
+
/// `live_actor_payload` either from the cell's execution registry (for
446
+
/// actors that self-report) or derived from `ActorStatus::Processing`.
447
+
/// `active_handler_count` is the full live total; the `active_handlers`
448
+
/// list is aggregated by name and capped (`active_handlers_truncated`).
449
+
@meta(INTROSPECT = IntrospectAttr{
450
+
name:"execution".into(),
451
+
desc:"In-flight execution: live invocation count, oldest, and per-name aggregates. Second plane to lifecycle status -- answers 'what is this actor handling now?'. Always present (count 0 when idle).".into(),
0 commit comments