pub struct ActionServerCore<const GOAL_BUF: usize = nros_node::::executor::action_core::ActionServerCore::{constant#0}, const RESULT_BUF: usize = nros_node::::executor::action_core::ActionServerCore::{constant#1}, const FEEDBACK_BUF: usize = nros_node::::executor::action_core::ActionServerCore::{constant#2}, const MAX_GOALS: usize = 4> { /* private fields */ }Expand description
Type-agnostic action server core handling the raw-bytes protocol.
Manages active goal tracking (GoalId + status), completed result storage in a fixed-size slab, and all CDR framing for the action protocol.
The typed ActionServer wraps this
and adds A::Goal / A::Feedback / A::Result (de)serialization.
Implementations§
Source§impl<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize, const MAX_GOALS: usize> ActionServerCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF, MAX_GOALS>
impl<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize, const MAX_GOALS: usize> ActionServerCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF, MAX_GOALS>
Sourcepub fn from_channels(
send_goal_server: <CffiSession as Session>::ServiceHandle,
cancel_goal_server: <CffiSession as Session>::ServiceHandle,
get_result_server: <CffiSession as Session>::ServiceHandle,
feedback_publisher: <CffiSession as Session>::PublisherHandle,
status_publisher: <CffiSession as Session>::PublisherHandle,
) -> ActionServerCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF, MAX_GOALS>
pub fn from_channels( send_goal_server: <CffiSession as Session>::ServiceHandle, cancel_goal_server: <CffiSession as Session>::ServiceHandle, get_result_server: <CffiSession as Session>::ServiceHandle, feedback_publisher: <CffiSession as Session>::PublisherHandle, status_publisher: <CffiSession as Session>::PublisherHandle, ) -> ActionServerCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF, MAX_GOALS>
Phase 122.3.c.6.b — construct an ActionServerCore from the
5 already-built transport channels. Caller (typically the C
API’s nros_action_server_init_polling) owns wiring the
channels via the session’s create_* methods.
Sourcepub fn try_recv_goal_request(
&mut self,
) -> Result<Option<RawGoalRequest>, NodeError>
pub fn try_recv_goal_request( &mut self, ) -> Result<Option<RawGoalRequest>, NodeError>
Try to receive a goal request from the send_goal service.
Returns the parsed GoalId, sequence number, and data length.
The full CDR data (including GoalId) remains in goal_buffer.
Sourcepub fn goal_buffer(&self) -> &[u8] ⓘ
pub fn goal_buffer(&self) -> &[u8] ⓘ
Get a reference to the goal buffer (valid after try_recv_goal_request).
Sourcepub fn accept_goal(
&mut self,
goal_id: GoalId,
seq: i64,
) -> Result<(), NodeError>
pub fn accept_goal( &mut self, goal_id: GoalId, seq: i64, ) -> Result<(), NodeError>
Accept a goal: records it, sends the acceptance reply, publishes status.
§Ordering
The goal is recorded in active_goals before the reply goes out,
and the recording is rolled back if the reply fails. Issue 0322: this
used to reply first and then let _ = self.active_goals.push(...), so
once MAX_GOALS (default 4) were active, a 5th send_goal was
answered accepted=true and then dropped — no execution, no feedback,
no result, no terminal status. An rclcpp/rclpy client that saw
accepted=true waited on its result future forever.
A full table is now answered truthfully with accepted=false via
Self::reject_goal, which is a contract the client already handles.
Sourcepub fn reject_goal(&mut self, seq: i64) -> Result<(), NodeError>
pub fn reject_goal(&mut self, seq: i64) -> Result<(), NodeError>
Reject a goal: sends the rejection reply.
Sourcepub fn publish_feedback_raw(
&mut self,
goal_id: &GoalId,
feedback_cdr: &[u8],
) -> Result<(), NodeError>
pub fn publish_feedback_raw( &mut self, goal_id: &GoalId, feedback_cdr: &[u8], ) -> Result<(), NodeError>
Publish feedback with raw CDR bytes.
Writes GoalId framing + raw feedback bytes into the feedback buffer and publishes.
Sourcepub fn set_goal_status(&mut self, goal_id: &GoalId, status: GoalStatus)
pub fn set_goal_status(&mut self, goal_id: &GoalId, status: GoalStatus)
Set a goal’s status and publish the updated GoalStatusArray.
Sourcepub fn expire_completed_results(&mut self) -> usize
pub fn expire_completed_results(&mut self) -> usize
Reclaim every completed result whose get_result reply has already been
sent — nano-ros’s analogue of rcl_action_expire_goals(). Returns the
number of entries reclaimed.
Calling this is optional: complete_goal_raw
reclaims on demand, so a server that never calls it still runs forever.
It exists for a server that would rather return the memory eagerly (e.g.
before a long idle period) than at the next completion.
Sourcepub fn completed_result_count(&self) -> usize
pub fn completed_result_count(&self) -> usize
Number of completed results currently retained.
Sourcepub fn result_slab_used(&self) -> usize
pub fn result_slab_used(&self) -> usize
Bytes of the result slab currently held by retained results.
Sourcepub fn has_completed_result(&self, goal_id: &GoalId) -> bool
pub fn has_completed_result(&self, goal_id: &GoalId) -> bool
true while goal_id’s completed result is still retained (i.e. a
get_result for it would be answered from the slab rather than as
Unknown).
Sourcepub fn complete_goal_raw(
&mut self,
goal_id: &GoalId,
status: GoalStatus,
result_cdr: &[u8],
) -> Result<(), NodeError>
pub fn complete_goal_raw( &mut self, goal_id: &GoalId, status: GoalStatus, result_cdr: &[u8], ) -> Result<(), NodeError>
Complete a goal: remove from active, store raw result CDR in slab, publish status.
§Errors
NodeError::BufferTooSmall when result_cdr is larger than
RESULT_BUF and therefore cannot be retained for a later get_result.
Any client already waiting on ~/_action/get_result is still answered
(straight from result_cdr), and the terminal status is still
published — but a later get_result for this goal gets
GoalStatus::Unknown. Raise the server’s RESULT_BUF.
Issue 0796: this returned (), so the pre-fix slab exhaustion — the
server silently dropping every result once the bump allocator hit
RESULT_BUF, and silently stranding every waiting requester with it —
was invisible to the caller. A full slab is no longer a failure at all
(it is reclaimed), and the one remaining failure is reported.
Sourcepub fn register_goal_waker(&self, waker: &Waker)
pub fn register_goal_waker(&self, waker: &Waker)
Phase 122.3.c.6.e — register a Waker that fires when a new
send_goal request arrives. Event-driven action servers
register here in place of polling try_recv_goal_request on
a timer.
Sourcepub fn register_cancel_waker(&self, waker: &Waker)
pub fn register_cancel_waker(&self, waker: &Waker)
Phase 122.3.c.6.e — register a Waker that fires when a
cancel-goal request arrives.
Sourcepub fn register_get_result_waker(&self, waker: &Waker)
pub fn register_get_result_waker(&self, waker: &Waker)
Phase 122.3.c.6.e — register a Waker that fires when a
get_result query arrives.
Sourcepub fn try_recv_cancel_request(
&mut self,
) -> Result<Option<PendingCancelRequest>, NodeError>
pub fn try_recv_cancel_request( &mut self, ) -> Result<Option<PendingCancelRequest>, NodeError>
Phase 122.3.c.6.d — peek a pending cancel-goal request without
generating a reply. Returns the goal_id named in the request,
the matching service sequence number (use it with
send_cancel_reply), and the
goal’s current status (GoalStatus::Unknown if no such
active goal). Returns Ok(None) when no cancel request is
pending.
Used by L1 polling-mode action servers (nros-c / nros-cpp C
FFI) that want to drive cancel-decision policy without
passing a Rust closure across the C ABI. See the matching
send_cancel_reply for the reply
side. The high-level closure-based
try_handle_cancel keeps working
and now delegates to this pair.
Sourcepub fn send_cancel_reply(
&mut self,
sequence_number: i64,
return_code: CancelReturnCode,
accepted: &[GoalId],
) -> Result<(), NodeError>
pub fn send_cancel_reply( &mut self, sequence_number: i64, return_code: CancelReturnCode, accepted: &[GoalId], ) -> Result<(), NodeError>
Phase 122.3.c.6.d — send the reply to a previously-peeked
cancel-goal request. sequence_number must match the value
returned by try_recv_cancel_request.
return_code is the overall RPC status (CancelReturnCode::Ok
= at least one cancel honoured; other variants = whole-request
failure). accepted lists the goals that transition to
Canceling; this function flips their stored status before
publishing the status array.
Issue 0796 — the parameter is a nros_core::CancelReturnCode, not
the per-goal nros_core::CancelResponse a cancel callback returns.
The two were one type and their discriminants overlap with opposite
meanings (Reject/Ok are both 0), so this signature is what stops a
per-goal answer being written into the RPC field.
Sourcepub fn try_handle_cancel(
&mut self,
cancel_handler: impl FnOnce(&GoalId, GoalStatus) -> CancelResponse,
) -> Result<Option<(GoalId, CancelResponse)>, NodeError>
pub fn try_handle_cancel( &mut self, cancel_handler: impl FnOnce(&GoalId, GoalStatus) -> CancelResponse, ) -> Result<Option<(GoalId, CancelResponse)>, NodeError>
Try to handle a cancel_goal request (type-agnostic).
Sourcepub fn try_handle_get_result_raw(
&mut self,
default_result_cdr: &[u8],
) -> Result<Option<GoalId>, NodeError>
pub fn try_handle_get_result_raw( &mut self, default_result_cdr: &[u8], ) -> Result<Option<GoalId>, NodeError>
Try to handle a get_result request using raw bytes.
For completed goals, sends the stored raw result CDR from the slab.
For active/unknown goals, sends the provided default_result_cdr bytes.
default_result_cdr should contain serialized result data (without CDR
header or status byte) — typically A::Result::default() serialized.
Sourcepub fn active_goal_count(&self) -> usize
pub fn active_goal_count(&self) -> usize
Get the number of active goals.
Sourcepub fn active_goals(&self) -> &[RawActiveGoal]
pub fn active_goals(&self) -> &[RawActiveGoal]
Get a reference to all active goals.
Sourcepub fn find_goal_status(&self, goal_id: &GoalId) -> GoalStatus
pub fn find_goal_status(&self, goal_id: &GoalId) -> GoalStatus
Find the status of a goal (active or unknown).
Sourcepub fn publish_status_array(&self) -> Result<(), NodeError>
pub fn publish_status_array(&self) -> Result<(), NodeError>
Publish the current GoalStatusArray on the status topic.