cmvr-es/cmvr-es/service/action/include/action_queue_executor.h
xtkuang f4be2ffaaa feat(safety): unify device admission and recovery
Add the DeviceManager-owned safety coordinator, shared sensor/control policies, command ledger, service guards, generalized StopAll, and RecoverSafetyState. Preserve device-side hardware checks and AUBO hardware E-stop release reconciliation while keeping software E-stop independently latched.
2026-08-17 08:34:44 +08:00

103 lines
3.8 KiB
C++

#ifndef CMVR_ES_ACTION_QUEUE_EXECUTOR_H
#define CMVR_ES_ACTION_QUEUE_EXECUTOR_H
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include "cmvr/api/system_command.pb.h"
#include "manager/safety/include/safety_types.h"
namespace cmvr::device {
class DeviceManager;
}
namespace cmvr::service {
// Owns the process-local FIFO used by SystemService ActionQueue requests.
// The executor intentionally has no grpc::ServerContext dependency: once a
// request is accepted, loss of the platform connection must not cancel device
// motion on the edge.
class ActionQueueExecutor final {
public:
static constexpr std::size_t kDefaultMaxAcceptedActionIds =
256U * 1024U;
enum class WaitResult {
Terminal,
CanceledBeforeAdmission,
CanceledAfterAdmission,
};
// Identifies one participant in a StopAll round. Multiple concurrent
// StopAll callers join the same round; ActionQueue admission resumes only
// after every ticket in that round has been completed successfully.
struct StopAllTicket {
std::uint64_t generation{0};
std::uint64_t ticket_id{0};
bool active_action_stop_confirmed{false};
bool valid() const noexcept
{
return generation != 0U && ticket_id != 0U;
}
};
explicit ActionQueueExecutor(
device::DeviceManager& device_manager,
std::size_t max_accepted_action_ids =
kDefaultMaxAcceptedActionIds);
~ActionQueueExecutor();
ActionQueueExecutor(const ActionQueueExecutor&) = delete;
ActionQueueExecutor& operator=(const ActionQueueExecutor&) = delete;
// Validates, idempotently enqueues, and waits for the terminal result.
// Protocol and execution outcomes are represented in Feedback.
WaitResult submitAndWait(
const api::ActionQueueCommand_Request& request,
api::ActionQueueCommand_Feedback& feedback,
const std::function<bool()>& waiter_canceled = {},
safety::CommandActor actor = {});
// Starts (or joins) a temporary StopAll round. New action IDs are rejected
// and queued/active actions are canceled. By default the executor also
// requests a typed stop for the active action. SystemService delegates that
// stop to its whole-machine sweep so one slow Action backend cannot delay
// stop requests for every other device.
// Existing action IDs remain queryable for idempotent reconciliation. An
// invalid ticket means permanent shutdown has already started.
StopAllTicket beginStopAll(bool delegate_active_stop = false);
// Completes a StopAll participant after the caller has stopped and
// confirmed all other devices. The queue resumes only when every ticket in
// the current round reports success and the worker is idle. True means this
// ticket was completed successfully; another concurrent ticket may still
// keep the queue paused. False is fail-closed: the ticket was stale,
// shutdown won the race, a stop was not confirmed, or the executor was not
// idle when the last ticket completed.
bool finishStopAll(
const StopAllTicket& ticket,
bool all_devices_stop_confirmed);
// Permanently rejects new actions, cancels queued/active work, requests a
// typed stop, and tells the worker to exit after canceled work is drained.
// This transition is irreversible for this executor instance. Returns true
// when the active Action devices reported a confirmed stop.
bool disableForShutdown();
bool waitForIdle(std::chrono::milliseconds timeout);
const std::string& instanceId() const noexcept;
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace cmvr::service
#endif // CMVR_ES_ACTION_QUEUE_EXECUTOR_H