pub struct TurnActivityTracker {
block_id: String,
inner: Mutex<TurnActivityTrackerInner>,
publisher: Mutex<Option<Arc<dyn Fn(&TurnLedger) + Send + Sync>>>,
publish_order: Mutex<()>,
clock: Box<dyn Fn() -> u64 + Send + Sync>,
}Expand description
Per-block turn-activity tracker.
Fields§
§block_id: String§inner: Mutex<TurnActivityTrackerInner>§publisher: Mutex<Option<Arc<dyn Fn(&TurnLedger) + Send + Sync>>>§publish_order: Mutex<()>Taken before inner is released and held through the publish, so
ledgers go out in seq order. The broker keeps the last one for
replay, so an older one published last would be what a new subscriber
gets (#4492). Lock order: inner → publish_order.
clock: Box<dyn Fn() -> u64 + Send + Sync>Implementations§
Source§impl TurnActivityTracker
impl TurnActivityTracker
pub fn new(block_id: String) -> Self
Sourcepub fn for_block(block_id: String, broker: Option<&Arc<Broker>>) -> Self
pub fn for_block(block_id: String, broker: Option<&Arc<Broker>>) -> Self
A tracker that publishes its turn ledger on broker, when there is one.
fn with_clock( block_id: String, clock: Box<dyn Fn() -> u64 + Send + Sync>, ) -> Self
Sourcepub fn set_ledger_publisher(
&self,
publisher: Arc<dyn Fn(&TurnLedger) + Send + Sync>,
)
pub fn set_ledger_publisher( &self, publisher: Arc<dyn Fn(&TurnLedger) + Send + Sync>, )
Where ledger changes go (the agentturn event). Set once by the
controller that owns this tracker, when it has a broker.
Sourcefn publish_in_order(
&self,
inner: MutexGuard<'_, TurnActivityTrackerInner>,
before: Option<TurnLedger>,
after: Option<TurnLedger>,
)
fn publish_in_order( &self, inner: MutexGuard<'_, TurnActivityTrackerInner>, before: Option<TurnLedger>, after: Option<TurnLedger>, )
Release inner and publish the ledger if it changed, in seq order,
logging the change as a [turn] line (muxlog’s answer to “why did
my timer reset”: turn-model spec §7).
Sourcefn publish_if_changed(
&self,
before: Option<TurnLedger>,
after: Option<TurnLedger>,
)
fn publish_if_changed( &self, before: Option<TurnLedger>, after: Option<TurnLedger>, )
Send the ledger to the publisher, if it changed. Called after the tracker’s lock is released.
Sourcepub fn set_active_turn(&self, active: bool)
pub fn set_active_turn(&self, active: bool)
Called when a new turn starts (subprocess spawned).
Sourcepub fn mark_turn_active_returning_was_active(&self) -> bool
pub fn mark_turn_active_returning_was_active(&self) -> bool
Atomically marks a turn active and reports whether one was already in
flight (the pre-call value) — a single lock acquisition, unlike
calling is_active_turn() then set_active_turn(true) separately.
That two-step form is a check-then-act race: send_message (user
input) and send_user_message (muxbus delivery) can run concurrently
on the same block, and both reading false before either writes
true lets both decide to spawn a watchdog — the exact duplicate the
“only re-arm when resuming from idle” logic exists to prevent.
Sourcepub fn mark_turn_active_from(&self, input: Option<TurnInput>) -> bool
pub fn mark_turn_active_from(&self, input: Option<TurnInput>) -> bool
Self::mark_turn_active_returning_was_active, saying who delivered
the input (turn provenance, SPEC_AGENT_SELF_QUIT §6.3):
- starting a turn records
inputas what started it — or, unlabelled, whatever was queued for it (else unknown); - into a running turn, non-user input — or unlabelled input, which can’t be proven to be the user — taints it.
Sourcepub fn note_cli_task_notification(&self, summary: Option<&str>)
pub fn note_cli_task_notification(&self, summary: Option<&str>)
The CLI reported a finished background task (system/task_notification).
It tells the model in a pass it starts itself: at once if it is idle,
straight after the running pass otherwise.
Sourcepub fn mark_turn_active_from_cli(&self) -> bool
pub fn mark_turn_active_from_cli(&self) -> bool
The CLI began a pass with no input from srv (system/init while idle).
Marked active only when something explains it (a task notification, or
input that reached it during the last pass), so a stray line can never
leave the agent reported busy with nothing to end it.
Returns whether the pass was marked (the caller then publishes status
and re-arms the heartbeat).
Sourcepub fn end_pass(&self, stats: Option<PassStats>)
pub fn end_pass(&self, stats: Option<PassStats>)
The CLI’s result: the running pass is over. Its figures (when the
frame carries them) go to the turn it belonged to in the same step as
the idle flip, so input that arrives right after can’t take them.
Sourcepub fn hint_join(&self, turn_id: u64)
pub fn hint_join(&self, turn_id: u64)
A message the pane held while turn turn_id ran is about to be sent
through a controller whose pass start carries no input (ACP, App Server,
one-shot subprocess): the pass it starts joins that turn, as
TurnInput::joins_turn does for the persistent controller (§4.3, J3).
Sourcepub fn clear_join_hint(&self)
pub fn clear_join_hint(&self)
Drop a join hint whose dispatch failed: no pass will consume it, and a later message must not.
Sourcepub fn set_exited(&self, exit_code: i32)
pub fn set_exited(&self, exit_code: i32)
Called when the subprocess exits.
Sourcepub fn is_active_turn(&self) -> bool
pub fn is_active_turn(&self) -> bool
Whether there’s an active turn in progress.
Sourcepub fn hint_next_turn(&self, input: TurnInput)
pub fn hint_next_turn(&self, input: TurnInput)
A message queued now will start a later turn (it waits for the process to spawn). Two queued before that turn starts: the second, if not the user’s, taints it.
Sourcepub fn hint_next_turn_unlabelled(&self)
pub fn hint_next_turn_unlabelled(&self)
An unlabelled message queued for the next turn: it can’t be proven to be the user, so a turn already labelled by an earlier queued message is tainted. (Queued first, it leaves the turn unknown anyway.)
Sourcepub fn mark_turn_active_for_queued(&self) -> bool
pub fn mark_turn_active_for_queued(&self) -> bool
The turn is active because messages already accounted for are being delivered — the queue drained after a spawn, a retry flush. Not new input: an idle tracker starts the turn with whatever was queued for it, and a running turn is left as it is (ReAgent P1 on #3789 — the plain unlabelled mark tainted every freshly spawned user turn).
Sourcepub fn provenance(&self) -> Option<TurnProvenance>
pub fn provenance(&self) -> Option<TurnProvenance>
What started the turn in flight, if one is and it was reported.
Auto Trait Implementations§
impl !Freeze for TurnActivityTracker
impl !RefUnwindSafe for TurnActivityTracker
impl !UnwindSafe for TurnActivityTracker
impl Send for TurnActivityTracker
impl Sync for TurnActivityTracker
impl Unpin for TurnActivityTracker
impl UnsafeUnpin for TurnActivityTracker
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more