Skip to main content

action_core/
message.rs

1use core_types::Timestamp;
2
3/// Immediate acknowledgement returned to the client after a goal is sent.
4///
5/// One of the key differences between Action and Service: before a goal is
6/// actually accepted for execution, the server first returns a `GoalAck`
7/// indicating whether it is willing to handle the goal.
8/// A rejected goal never enters execution and produces no feedback or result.
9#[derive(Clone, Debug, Eq, PartialEq)]
10pub struct GoalAck {
11    /// Whether the server accepted this goal.
12    pub accepted: bool,
13    /// Optional rejection reason or additional message.
14    pub reason: Option<String>,
15}
16
17/// Current execution status of a goal (polled by the client, updated by the server).
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
19pub enum GoalStatus {
20    /// Accepted by the server; not yet executing.
21    Accepted,
22    /// Currently executing.
23    Executing,
24    /// Cancel requested; server is processing the cancellation.
25    Canceling,
26    /// Execution completed successfully.
27    Succeeded,
28    /// Execution failed.
29    Failed,
30    /// Execution was canceled.
31    Canceled,
32    /// Goal was rejected by the server before execution began.
33    Rejected,
34}
35
36impl GoalStatus {
37    /// Returns `true` if this status is a terminal state (no further transitions possible).
38    pub fn is_terminal(self) -> bool {
39        matches!(
40            self,
41            GoalStatus::Succeeded
42                | GoalStatus::Failed
43                | GoalStatus::Canceled
44                | GoalStatus::Rejected
45        )
46    }
47}
48
49/// Intermediate progress published by the server during goal execution.
50///
51/// Feedback is keyed by `ActionGoalId` so the client can distinguish updates
52/// from concurrent goals. Delivery is best-effort; the client must not assume
53/// every item is received. Only the final `ActionResult` is delivered exactly once.
54#[derive(Clone, Debug, Eq, PartialEq)]
55pub struct ActionFeedback<F> {
56    /// Timestamp when this feedback was produced.
57    pub timestamp: Timestamp,
58    /// Application-defined feedback payload.
59    pub value: F,
60}
61
62/// Terminal result returned when a goal finishes (Succeeded / Failed / Canceled).
63///
64/// Regardless of the outcome, `ActionResult` is delivered exactly once.
65/// After the client receives it, the goal's lifecycle is complete.
66#[derive(Clone, Debug, Eq, PartialEq)]
67pub struct ActionResult<R> {
68    /// Terminal status of the goal.
69    pub status: GoalStatus,
70    /// Result payload; `None` when canceled or rejected.
71    pub value: Option<R>,
72    /// Failure reason; present when `status == GoalStatus::Failed`.
73    pub error: Option<String>,
74}
75
76/// Liveness classification for an action goal session.
77#[derive(Clone, Copy, Debug, Eq, PartialEq)]
78pub enum ActionLiveness {
79    /// The goal is progressing and heartbeat is within timeout budget.
80    Active,
81    /// The goal is not timed out yet but heartbeat age exceeds the stalled threshold.
82    Stalled,
83    /// The goal exceeded heartbeat timeout budget.
84    TimedOut,
85    /// Terminal goals are considered completed.
86    Completed,
87    /// Insufficient data to classify liveness.
88    Unknown,
89}
90
91/// Health snapshot for a specific action goal.
92#[derive(Clone, Debug, Eq, PartialEq)]
93pub struct ActionSessionHealth {
94    pub goal_id: core_types::ActionGoalId,
95    pub status: GoalStatus,
96    pub liveness: ActionLiveness,
97    pub heartbeat_timeout_nanos: Option<u128>,
98    pub stalled_threshold_nanos: Option<u128>,
99    pub last_heartbeat_at_unix_nanos: Option<u128>,
100    pub last_feedback_at_unix_nanos: Option<u128>,
101    pub last_result_at_unix_nanos: Option<u128>,
102}
103
104/// Schema descriptor for an action, covering the goal, feedback, and result message types.
105#[derive(Clone, Debug, Eq, PartialEq)]
106pub struct ActionSchema {
107    pub goal: data_model::SchemaDescriptor,
108    pub feedback: data_model::SchemaDescriptor,
109    pub result: data_model::SchemaDescriptor,
110}