use std::collections::VecDeque;
use core_types::{ActionGoalId, RtError, Timestamp};
use crate::message::{
ActionFeedback, ActionResult, ActionSchema, ActionSessionHealth, GoalAck, GoalStatus,
};
mod client;
mod server;
pub use self::client::BasicActionClient;
pub use self::server::BasicActionServer;
pub trait ActionClient<G, F, R>
where
G: Send + 'static,
F: Send + 'static,
R: Send + 'static,
{
fn action_name(&self) -> &str;
fn schema(&self) -> &ActionSchema;
fn send_goal(&mut self, goal: G) -> Result<(ActionGoalId, GoalAck), RtError>;
fn poll_feedback(&mut self, goal_id: ActionGoalId) -> Option<ActionFeedback<F>>;
fn poll_result(&mut self, goal_id: ActionGoalId) -> Option<ActionResult<R>>;
fn cancel(&mut self, goal_id: ActionGoalId) -> Result<(), RtError>;
fn goal_status(&self, goal_id: ActionGoalId) -> Option<GoalStatus>;
fn tick_timeouts(&mut self, _now: Timestamp) -> usize {
0
}
fn goal_health(&self, _goal_id: ActionGoalId) -> Option<ActionSessionHealth> {
None
}
fn active_goal_health(&self) -> Vec<ActionSessionHealth> {
Vec::new()
}
fn close(&mut self) -> Result<(), RtError>;
}
pub trait ActionServer<G, F, R>
where
G: Send + 'static,
F: Send + 'static,
R: Send + 'static,
{
fn action_name(&self) -> &str;
fn schema(&self) -> &ActionSchema;
fn recv_goal(&mut self) -> Result<Option<(ActionGoalId, G)>, RtError>;
fn accept_goal(&mut self, goal_id: ActionGoalId) -> Result<(), RtError>;
fn reject_goal(
&mut self,
goal_id: ActionGoalId,
reason: impl Into<String>,
) -> Result<(), RtError>;
fn publish_feedback(&mut self, goal_id: ActionGoalId, feedback: F) -> Result<(), RtError>;
fn heartbeat(&mut self, goal_id: ActionGoalId) -> Result<(), RtError>;
fn succeed(&mut self, goal_id: ActionGoalId, result: R) -> Result<(), RtError>;
fn fail(&mut self, goal_id: ActionGoalId, reason: impl Into<String>) -> Result<(), RtError>;
fn poll_cancel_request(&mut self) -> Option<ActionGoalId>;
fn confirm_cancel(&mut self, goal_id: ActionGoalId) -> Result<(), RtError>;
fn close(&mut self) -> Result<(), RtError>;
}
pub struct ActionChannel<G, F, R> {
pub goals: std::sync::Mutex<VecDeque<(ActionGoalId, G)>>,
pub acks: std::sync::Mutex<std::collections::HashMap<u64, GoalAck>>,
pub feedbacks: std::sync::Mutex<std::collections::HashMap<u64, VecDeque<ActionFeedback<F>>>>,
pub results: std::sync::Mutex<std::collections::HashMap<u64, ActionResult<R>>>,
pub cancels: std::sync::Mutex<VecDeque<ActionGoalId>>,
pub statuses: std::sync::Mutex<std::collections::HashMap<u64, GoalStatus>>,
pub heartbeats: std::sync::Mutex<std::collections::HashMap<u64, Timestamp>>,
pub feedback_timestamps: std::sync::Mutex<std::collections::HashMap<u64, Timestamp>>,
pub result_timestamps: std::sync::Mutex<std::collections::HashMap<u64, Timestamp>>,
}
impl<G, F, R> ActionChannel<G, F, R> {
pub fn new() -> std::sync::Arc<Self> {
std::sync::Arc::new(Self {
goals: Default::default(),
acks: Default::default(),
feedbacks: Default::default(),
results: Default::default(),
cancels: Default::default(),
statuses: Default::default(),
heartbeats: Default::default(),
feedback_timestamps: Default::default(),
result_timestamps: Default::default(),
})
}
}