RTC Toolkit 6.0.0
Loading...
Searching...
No Matches
measurable.hpp
Go to the documentation of this file.
1
11
12#ifndef RTCTK_COMPONENTFRAMEWORK_MEASURABLE_HPP
13#define RTCTK_COMPONENTFRAMEWORK_MEASURABLE_HPP
14
15#include <optional>
16
23
25namespace detail {
38public:
45 explicit MeasureContext(const rad::cii::Request<std::string, std::string>& request)
46 : m_logger(GetLogger("rtctk")), m_request(request), m_arg() {
47 m_arg = JsonPayload::parse(m_request.GetRequestPayload());
48 }
49 MeasureContext(MeasureContext&&) noexcept = default;
50
51 const JsonPayload& GetArg() const noexcept {
52 return m_arg;
53 }
54
61 void SetResult(const JsonPayload& result) {
62 m_result = result.dump();
63 }
64
70 void SendReply() noexcept {
71 try {
72 m_request.SetReplyValue(m_result);
73 } catch (const std::exception& exception) {
74 LOG4CPLUS_ERROR(
75 m_logger, "MeasureContext::SendReply: Failed to send reply: " << exception.what());
76 } catch (...) {
77 LOG4CPLUS_ERROR(
78 m_logger,
79 "MeasureContext::SendReply: Failed to send reply with unknown exception.");
80 }
81 }
82
86 void SendErrorReply(std::exception_ptr eptr) noexcept {
87 try {
88 m_request.SetException(RequestFailed(NestedExceptionPrinter(std::move(eptr)).Str()));
89 } catch (const RtctkException& exception) {
90 LOG4CPLUS_ERROR(
91 m_logger,
92 "MeasureContext::SendErrorReply: Failed to send reply: " << exception.what());
93 } catch (...) {
94 LOG4CPLUS_ERROR(
95 m_logger,
96 "MeasureContext::SendErrorReply: Failed to send reply with unknown exception.");
97 }
98 }
99
100private:
101 log4cplus::Logger& m_logger;
102 rad::cii::Request<std::string, std::string> m_request;
106 JsonPayload m_arg;
110 std::string m_result;
111};
112} // namespace detail
113
149template <typename Super>
150struct Measurable : Super {
151 static_assert(std::is_base_of_v<RtcComponent, Super>, "'Measurable' requires 'RtcComponent'");
152
157 class BizLogicIf : public Super::BizLogicIf {
158 public:
159 // Due to Doxygen limitations the multi-line @exception_basic command cannot have the '*'
160 // character on each line.
173 virtual JsonPayload ActivityMeasuring(StopToken stop_token, const JsonPayload& arg) {
174 (void)stop_token;
175 return {"42"};
176 }
177
187 virtual bool GuardMeasuringAllowed(const JsonPayload& arg) {
188 return true;
189 }
190 };
191
195 class InputStage : public Super::InputStage {
196 public:
197 using Super::InputStage::InputStage;
198
199 void Start() override {
200 Super::InputStage::Start();
201
202 MeasCmdsImpl::Register(this->m_replier, this->m_engine);
203 }
204 };
205
209 class OutputStage : public Super::OutputStage {
210 public:
211 OutputStage(StateMachineEngine& engine, BizLogicIf& bl) : Super::OutputStage(engine, bl) {
212 // Handlers ###################################################################
213
214 engine.RegisterRejectHandler<events::Measure, RequestRejected>();
215
217 this->m_engine.PostEvent(std::make_unique<events::MeasureDone>());
218 };
219
220 m_measure_error_handler = [this](std::exception_ptr eptr) {
221 this->m_engine.PostEvent(std::make_unique<events::MeasureError>(std::move(eptr)));
222 };
223
224 // No Disable in states ###############################################################
225
226 this->m_no_disable_in_states.emplace_back("On::Operational:Measure:Busy");
227
228 // No Update in states ################################################################
229
230 this->m_no_update_in_states.emplace_back("On::Operational:Measure:Busy");
231
232 // No Measure in states ###############################################################
233
234 this->m_no_measure_in_states.emplace_back("On:Update:Busy");
235
236 // Guards #####################################################################
237
238 engine.RegisterGuardStatic<events::Measure>(
239 "GuardMeasuringAllowed", [this](const events::Measure& ev) {
248 auto act_state = this->m_engine.GetState();
249 for (auto& s : m_no_measure_in_states) {
250 if (act_state.find(s) != std::string::npos) {
251 return false;
252 }
253 }
254 detail::MeasureContext ctx(ev.GetPayload());
255 if (static_cast<BizLogicIf&>(this->m_logic)
256 .GuardMeasuringAllowed(ctx.GetArg())) {
257 // Measure is allowed so context is stored.
258 assert(!m_measure_ctx);
259 m_measure_ctx.emplace(std::move(ctx));
260 return true;
261 }
262 return false;
263 });
264
265 // Activities #####################################################################
266 engine.RegisterActivity(
267 "ActivityMeasuring",
268 [this](StopToken stop_token) {
269 assert(m_measure_ctx);
270 JsonPayload result =
271 static_cast<BizLogicIf&>(this->m_logic)
272 .ActivityMeasuring(std::move(stop_token), m_measure_ctx->GetArg());
273 // note: SetResult may throw
274 m_measure_ctx->SetResult(result);
275 },
278
279 // Actions #####################################################################
280 engine.RegisterAction("ActionMeasuringDone", [this](auto c) {
281 assert(m_measure_ctx);
282 m_measure_ctx->SendReply();
283 m_measure_ctx.reset();
284 });
285
286 engine.RegisterActionStatic<events::MeasureError>(
287 "ActionMeasuringFailed", [this](const events::MeasureError& ev) {
288 assert(m_measure_ctx);
289 m_measure_ctx->SendErrorReply(ev.GetPayload());
290 m_measure_ctx.reset();
291 });
292 }
293
294 protected:
296 std::optional<detail::MeasureContext> m_measure_ctx;
297 std::function<void()> m_measure_success_handler;
298 std::function<void(std::exception_ptr)> m_measure_error_handler;
299 std::list<std::string> m_no_measure_in_states;
300 };
301
305 class ModelBuilder : public Super::ModelBuilder {
306 public:
307 explicit ModelBuilder(StateMachineEngine& engine) : Super::ModelBuilder(engine) {
308 // clang-format off
309 this->mm.ModStateType("On::Operational", Parallel);
310
311 this->mm.AddState(Composite, "On::Operational:Measure:", "On::Operational");
312 this->mm.AddState(Initial, "On::Operational:Measure:Initial", "On::Operational:Measure:");
313 this->mm.AddState(Simple, "On::Operational:Measure:Idle", "On::Operational:Measure:");
314 this->mm.AddState(Simple, "On::Operational:Measure:Busy", "On::Operational:Measure:", "ActivityMeasuring");
315
316 this->mm.AddTrans("On::Operational:Measure:Initial" , "On::Operational:Measure:Idle" );
317 this->mm.AddTrans("On::Operational:Measure:Idle" , "On::Operational:Measure:Busy", events::Measure::ID, "GuardMeasuringAllowed");
318 this->mm.AddTrans("On::Operational:Measure:Busy" , "On::Operational:Measure:Idle", events::MeasureDone::ID, "", "ActionMeasuringDone");
319 this->mm.AddTrans("On::Operational:Measure:Busy" , "On::Operational:Measure:Idle", events::MeasureError::ID, "", "ActionMeasuringFailed");
320 // clang-format on
321 }
322 };
323};
324
325} // namespace rtctk::componentFramework
326
327#endif
static void Register(CommandReplier &replier, StateMachineEngine &engine)
Definition measCmdsImpl.hpp:36
Business logic interface for Measurable mixin.
Definition measurable.hpp:157
virtual bool GuardMeasuringAllowed(const JsonPayload &arg)
Determines if measurement is possible at this time with the provided argument.
Definition measurable.hpp:187
virtual JsonPayload ActivityMeasuring(StopToken stop_token, const JsonPayload &arg)
Activity executed in its own thread that peforms the requested measurement specified by JSON argument...
Definition measurable.hpp:173
void Start() override
Definition measurable.hpp:199
ModelBuilder(StateMachineEngine &engine)
Definition measurable.hpp:307
std::function< void()> m_measure_success_handler
Definition measurable.hpp:297
std::function< void(std::exception_ptr)> m_measure_error_handler
Definition measurable.hpp:298
std::optional< detail::MeasureContext > m_measure_ctx
Context storage used for each accepted Measure request.
Definition measurable.hpp:296
std::list< std::string > m_no_measure_in_states
Definition measurable.hpp:299
OutputStage(StateMachineEngine &engine, BizLogicIf &bl)
Definition measurable.hpp:211
Adapter object intended to be used in contexts without direct access to the output-stream object.
Definition exceptions.hpp:168
Thrown if the command was accepted but the task to run failed.
Definition rtcComponent.hpp:52
Thrown if a command is not allowed in current state or guard.
Definition rtcComponent.hpp:39
The RtctkException class is the base class for all Rtctk exceptions.
Definition exceptions.hpp:220
Definition stateMachineEngine.hpp:34
void RegisterGuardStatic(const std::string &id, std::function< bool(const Event &)> guard)
Register guard for statically known event type.
Definition stateMachineEngine.hpp:125
void RegisterAction(const std::string &id, ActionMethod action)
Register action.
Definition stateMachineEngine.cpp:85
void RegisterRejectHandler(const std::string &id, RejectMethod reject)
Register reject handler.
Definition stateMachineEngine.cpp:128
void RegisterActivity(const std::string &id, ActivityMethod activity, SuccessMethod on_success, FailureMethod on_failure)
Register activity.
Definition stateMachineEngine.cpp:120
void RegisterActionStatic(const std::string &id, std::function< void(const Event &)> action)
Register action for statically known event type.
Definition stateMachineEngine.hpp:92
Holds context necessary for processing a measure request to completion.
Definition measurable.hpp:37
const JsonPayload & GetArg() const noexcept
Definition measurable.hpp:51
MeasureContext(const rad::cii::Request< std::string, std::string > &request)
Construct context with provided request.
Definition measurable.hpp:45
void SendErrorReply(std::exception_ptr eptr) noexcept
If reply is pending, set exception to the provided value.
Definition measurable.hpp:86
void SetResult(const JsonPayload &result)
Sets serialised reply from JSON payload, but does not send it.
Definition measurable.hpp:61
MeasureContext(MeasureContext &&) noexcept=default
void SendReply() noexcept
Send reply using result set with SetResult().
Definition measurable.hpp:70
Provides macros and utilities for exception handling.
log4cplus::Logger & GetLogger(const std::string &name="app")
Get handle to a specific logger.
Definition logger.cpp:191
Defines the JSON payload type JsonPayload.
Logging Support Library based on log4cplus.
Implementation of MAL commands for layer 'Measurable'.
Definition measurable.hpp:25
Definition commandReplier.cpp:21
@ Simple
Definition model.hpp:22
@ Composite
Definition model.hpp:22
@ Parallel
Definition model.hpp:22
@ Initial
Definition model.hpp:22
rad::StopToken StopToken
Definition stopToken.hpp:19
nlohmann::json JsonPayload
Type requirements:
Definition jsonPayload.hpp:24
Lifecycle of a basic 'RtcComponent'.
A simple Stop Token.
Life cycle extension to make RtcComponent Measurable.
Definition measurable.hpp:150