eva_common/
actions.rs

1/// Contains the action manager
2use crate::value::Value;
3use crate::{EResult, Error};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use uuid::Uuid;
7
8pub const ACTION_CREATED: u8 = 0b0000_0000; // created by the core
9pub const ACTION_ACCEPTED: u8 = 0b0000_0001; // accepted
10pub const ACTION_PENDING: u8 = 0b0000_0010; // queued by the controller
11pub const ACTION_RUNNING: u8 = 0b0000_1000; // running by the controller
12pub const ACTION_COMPLETED: u8 = 0b0000_1111; // completed successfully
13pub const ACTION_FAILED: u8 = 0b1000_0000; // failed to be completed
14pub const ACTION_CANCELED: u8 = 0b1000_0001; // canceled in queue
15pub const ACTION_TERMINATED: u8 = 0b1000_0010; // terminated while running
16
17pub const ACTION_TOPIC: &str = "ACT/";
18
19pub const DEFAULT_ACTION_PRIORITY: u8 = 100;
20
21#[inline]
22pub fn default_action_priority() -> u8 {
23    DEFAULT_ACTION_PRIORITY
24}
25
26/// Action status enum
27#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Copy, Clone, Hash, PartialOrd)]
28#[repr(u8)]
29#[serde(rename_all = "lowercase")]
30pub enum Status {
31    Created = ACTION_CREATED,
32    Accepted = ACTION_ACCEPTED,
33    Pending = ACTION_PENDING,
34    Running = ACTION_RUNNING,
35    Completed = ACTION_COMPLETED,
36    Failed = ACTION_FAILED,
37    Canceled = ACTION_CANCELED,
38    Terminated = ACTION_TERMINATED,
39}
40
41impl TryFrom<u8> for Status {
42    type Error = Error;
43    fn try_from(code: u8) -> EResult<Self> {
44        match code {
45            ACTION_CREATED => Ok(Status::Created),
46            ACTION_ACCEPTED => Ok(Status::Accepted),
47            ACTION_PENDING => Ok(Status::Pending),
48            ACTION_RUNNING => Ok(Status::Running),
49            ACTION_COMPLETED => Ok(Status::Completed),
50            ACTION_FAILED => Ok(Status::Failed),
51            ACTION_CANCELED => Ok(Status::Canceled),
52            ACTION_TERMINATED => Ok(Status::Terminated),
53            _ => Err(Error::invalid_data(format!(
54                "invalid action code: {}",
55                code
56            ))),
57        }
58    }
59}
60
61/// Params for unit actions
62#[derive(Serialize, Deserialize, Debug, Clone)]
63pub struct UnitParams {
64    pub value: Value,
65}
66
67/// Params for lmacro actions
68#[derive(Serialize, Deserialize, Debug, Default, Clone)]
69pub struct LmacroParams {
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub args: Option<Vec<Value>>,
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub kwargs: Option<HashMap<String, Value>>,
74}
75
76/// Params enum
77#[derive(Serialize, Deserialize, Debug, Clone)]
78#[serde(untagged)]
79pub enum Params {
80    Unit(UnitParams),
81    Lmacro(LmacroParams),
82}
83
84/// Params view enum
85#[derive(Serialize)]
86#[serde(untagged)]
87pub enum ParamsView<'a> {
88    Unit(&'a UnitParams),
89    Lmacro(LmacroParamsView<'a>),
90}
91
92#[derive(Serialize)]
93pub struct LmacroParamsView<'a> {
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub args: Option<Vec<Value>>,
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub kwargs: Option<HashMap<&'a str, Value>>,
98}
99
100impl Params {
101    #[inline]
102    pub fn new_unit(value: Value) -> Self {
103        Self::Unit(UnitParams { value })
104    }
105    #[inline]
106    pub fn new_lmacro(args: Option<Vec<Value>>, kwargs: Option<HashMap<String, Value>>) -> Self {
107        Self::Lmacro(LmacroParams { args, kwargs })
108    }
109    pub fn as_view(&self) -> ParamsView<'_> {
110        match self {
111            Params::Unit(p) => ParamsView::Unit(p),
112            Params::Lmacro(p) => {
113                let args = p
114                    .args
115                    .as_ref()
116                    .map(|args| args.iter().map(|v| v.clone().to_no_bytes()).collect());
117                let kwargs = if let Some(ref kwargs) = p.kwargs {
118                    let mut m: HashMap<&str, Value> = HashMap::new();
119                    for (k, v) in kwargs {
120                        m.insert(k, v.clone().to_no_bytes());
121                    }
122                    Some(m)
123                } else {
124                    None
125                };
126                ParamsView::Lmacro(LmacroParamsView { args, kwargs })
127            }
128        }
129    }
130}
131
132/// Event payload, announced by services when an action changes its state
133#[derive(Serialize, Deserialize, Debug)]
134#[serde(deny_unknown_fields)]
135pub struct ActionEvent {
136    pub uuid: Uuid,
137    pub status: u8,
138    #[serde(skip_serializing_if = "Option::is_none")]
139    pub out: Option<Value>,
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub err: Option<Value>,
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub exitcode: Option<i16>,
144}