arora_behavior/task.rs
1//! Task runs: concurrent, cancellable behaviors an interpreter hosts.
2//!
3//! A *task run* is a long-running unit of behavior started from a [`Call`] and
4//! tracked by a serializable [`TaskHandle`]. It advances with the interpreter's
5//! normal [`tick`](crate::BehaviorInterpreter::tick) — spawning one is
6//! non-blocking — and everything an outside observer needs to follow or stop it
7//! travels as data on the handle, so it can be driven through the value plane
8//! without knowing how the interpreter hosts the run.
9
10use arora_types::call::Call;
11use arora_types::data::Key;
12use uuid::Uuid;
13
14/// Identity of a live task run.
15///
16/// Unique per run. It is also the namespacing root for the run's keys, which
17/// live under `arora/tasks/<module>/<function>/<run_id>/…`.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19pub struct TaskId(pub Uuid);
20
21/// How a run coexists with the runs an interpreter already hosts.
22///
23/// Only [`Concurrent`](Self::Concurrent) is honoured today; the enum is
24/// `#[non_exhaustive]` so conflict-resolution policies that need resource-claims
25/// (preempt, queue, blend, reject) can be added later without a breaking change.
26/// Arbitration, when those land, is the interpreter's — it is the only thing
27/// that sees every run.
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29#[non_exhaustive]
30pub enum RunPolicy {
31 /// Run alongside every other run. Overlapping actuation writes are
32 /// last-write-wins — two runs driving the same output will fight.
33 Concurrent,
34}
35
36/// The serializable contract for one run's lifecycle: everything needed to
37/// follow and stop it, as data.
38///
39/// Returned from [`spawn`](crate::BehaviorInterpreter::spawn). The keys are
40/// allocated by the interpreter under the run's [`id`](Self::id), so concurrent
41/// runs demux. A run's *actuation* writes are deliberately not here — those go
42/// to the shared standard keys, where overlapping runs are last-write-wins.
43#[derive(Debug, Clone, PartialEq)]
44pub struct TaskHandle {
45 /// The run's identity.
46 pub id: TaskId,
47 /// How to stop the run: a [`Call`] the observer issues, which reaches
48 /// [`halt`](crate::BehaviorInterpreter::halt). Carrying it as a `Call` keeps
49 /// "how to stop it" serializable and interpreter-agnostic.
50 pub stop: Call,
51 /// The run's lifecycle status key — a single key an observer watches to
52 /// learn when the run reaches a terminal state and how it ended.
53 pub status: Key,
54 /// Keys carrying the run's progress feedback, updated as it runs.
55 pub feedback: Vec<Key>,
56 /// Keys carrying the run's result, written when it terminates.
57 pub result: Vec<Key>,
58 /// Keys an observer may write to steer a live run (e.g. a moving target).
59 pub update: Vec<Key>,
60}