morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
morph::model::ActionRecordingError Class Reference

Thrown when an action executed and its mutation committed, but the framework could not finish reporting that success. More...

#include <registry.hpp>

Inheritance diagram for morph::model::ActionRecordingError:

Public Member Functions

 ActionRecordingError (std::string result, std::string cause)
 Constructs the error with a message of the form "action executed but was not recorded: <cause>".
const std::string & result () const noexcept
 Returns the committed action's JSON-encoded result.
const std::string & cause () const noexcept
 Returns the underlying failure's message, without this type's prefix.

Detailed Description

Thrown when an action executed and its mutation committed, but the framework could not finish reporting that success.

Raised by the two sites that actually run Model::execute — the server dispatch path (morph::model::detail::ActionDispatcher::registerAction's runner) and the in-process path (Bridge::executeVia's localOp, bridge.hpp) — for anything that fails after Model::execute returned: serialising the result (ActionTraits<Action>::resultToJson, which throws detail::ParseError) and appending the journal entry (a journal::IActionLog whose append could not reach its backend, which action_log.hpp requires it to signal by throwing).

It exists because those failures are not execution failures and must not be reported as one. An action whose journal append throws has already changed the model; telling the caller the action was rejected invites a retry of a write that landed, and recording journal::Outcome::Failed for it puts a permanent lie in the audit trail, attributed to the action rather than to the infrastructure that failed. So a post-execution failure is a distinct type carrying a distinct message: the action ran, the reporting did not.

No journal entry is written when the throw came from resultToJson. A Succeeded entry carries the result by definition (see docs/spec/journal/journal.md, LogEntry::result), and there is none to carry; the caller is told instead, which is the only channel left.

Deriving from std::runtime_error keeps existing catch (const std::exception&) handling working — RemoteServer::dispatchExecute's strand catch still turns this into an err reply, and LocalBackend's still rejects the Completion — while a caller that wants to tell a committed-but-unrecorded action from a rejected one can catch this type and read result().

Definition at line 385 of file registry.hpp.

Constructor & Destructor Documentation

◆ ActionRecordingError()

morph::model::ActionRecordingError::ActionRecordingError ( std::string result,
std::string cause )
inline

Constructs the error with a message of the form "action executed but was not recorded: <cause>".

Parameters
resultJSON-encoded result of the committed action, or "" when serialising it is what failed.
causestd::exception::what() from the failure that stopped the recording.

Definition at line 393 of file registry.hpp.

Member Function Documentation

◆ result()

const std::string & morph::model::ActionRecordingError::result ( ) const
inlinenodiscardnoexcept

Returns the committed action's JSON-encoded result.

Returns
The result JSON, or "" when resultToJson is what threw.

Definition at line 400 of file registry.hpp.

◆ cause()

const std::string & morph::model::ActionRecordingError::cause ( ) const
inlinenodiscardnoexcept

Returns the underlying failure's message, without this type's prefix.

Returns
std::exception::what() of the failure that stopped the recording.

Definition at line 404 of file registry.hpp.


The documentation for this class was generated from the following file: