|
morph 0.1.0
Asynchronous bridge between GUI thread and business models
|
Type-erased, JSON-in/JSON-out execute path for actions whose concrete C++ type is only known by its registered string id at the call site (e.g. a schema-driven GUI that reads action names out of a JSON Schema at runtime). More...
#include <bridge.hpp>
Public Types | |
| using | Executor = std::function<::morph::async::Completion<std::string>(void*, std::string_view)> |
| Deserialises bodyJson, dispatches through the handler's Bridge, and resolves with the JSON-encoded result. | |
Public Member Functions | |
| template<typename Model, typename Action> | |
| void | registerAction (std::string_view modelId, std::string_view actionId) |
| Registers the executors for (Model, Action) under the given string ids. | |
| template<typename Sharing> | |
| ::morph::async::Completion< std::string > | execute (std::string_view modelId, std::string_view actionId, void *handler, std::string_view bodyJson) const |
| Looks up and invokes the executor for (modelId, actionId), specialised for the caller's own Sharing policy. | |
| template<typename Sharing> | |
| bool | contains (std::string_view modelId, std::string_view actionId) const noexcept |
| Checks whether an executor is registered for (modelId, actionId), specialised for the caller's own Sharing policy, without invoking it. | |
Static Public Member Functions | |
| static ActionExecuteRegistry & | instance () |
| Returns the process-level singleton registry. | |
Type-erased, JSON-in/JSON-out execute path for actions whose concrete C++ type is only known by its registered string id at the call site (e.g. a schema-driven GUI that reads action names out of a JSON Schema at runtime).
Populated automatically by BRIDGE_REGISTER_ACTION — no action-specific code is required at any call site. Every entry calls through the real BridgeHandler<Model>::execute<Action>() (so sessions, backend switches, and completions all behave exactly as they do for hand-written call sites), unlike morph::model::detail::ActionDispatcher, which calls Model::execute directly against an already-owned model holder and is only ever used server-side.
HARD REQUIREMENT (other direction of the same constraint documented on morph::model::detail::registerActionExecutorOnce in registry.hpp): registration into this registry happens via registerActionExecutorOnce<Model, Action>, which BRIDGE_REGISTER_ACTION calls unconditionally but which is only defined here, in bridge.hpp. Every translation unit that calls BRIDGE_REGISTER_ACTION must therefore include this header (directly or transitively), or that translation unit's static initializer will fail to link.
Definition at line 62 of file bridge.hpp.
| using morph::bridge::ActionExecuteRegistry::Executor = std::function<::morph::async::Completion<std::string>(void*, std::string_view)> |
Deserialises bodyJson, dispatches through the handler's Bridge, and resolves with the JSON-encoded result.
Definition at line 66 of file bridge.hpp.
|
inline |
Registers the executors for (Model, Action) under the given string ids.
Populates one Executor per Sharing policy the framework defines (NoSharing and AllowShared), keyed by (modelId, actionId, typeid(Sharing)), rather than a single executor that unconditionally assumes NoSharing. A handler whose Sharing is anything else must be dispatched through the matching executor: the wrong one static_casts handlerVoid to the wrong BridgeHandler<Model, Sharing> instantiation, so kShared resolves incorrectly inside it and a payload-/result-keyed action's attach-or-promote step silently never runs. Both executors' bodies are otherwise byte-for-byte identical (built once, from the same generic lambda template, instantiated for NoSharing and again for AllowShared — the only two sharing tags morph::bridge defines), so this costs one extra closure per registered action, not per call. Defined out-of-line after BridgeHandler to avoid forward reference issues.
| Model | Model type whose handler will execute the action. |
| Action | Action type to register. |
| modelId | String id the model is registered under. |
| actionId | String id the action is registered under. |
Out-of-line definition of ActionExecuteRegistry::registerAction. Placed here after BridgeHandler is fully defined so we can safely cast and call its methods.
Builds one executor per Sharing policy the framework defines (NoSharing, AllowShared) from the same generic-lambda template, static_casting handlerVoid to the matching BridgeHandler<Model, Sharing>* in each — see bridge.md's design-decision entry for why a single NoSharing-only executor is unsound for a shared handler.
Definition at line 3063 of file bridge.hpp.
|
inlinenodiscard |
Looks up and invokes the executor for (modelId, actionId), specialised for the caller's own Sharing policy.
| Sharing | NoSharing or AllowShared — the caller's own sharing policy. |
| modelId | String id of the target model. |
| actionId | String id of the action to execute. |
| handler | Type-erased BridgeHandler<Model, Sharing>* matching modelId. |
| bodyJson | JSON-encoded action payload. |
| std::runtime_error | if no executor was registered for that triple. |
Definition at line 101 of file bridge.hpp.
|
inlinenodiscardnoexcept |
Checks whether an executor is registered for (modelId, actionId), specialised for the caller's own Sharing policy, without invoking it.
registerAction always files both the NoSharing and AllowShared executors for a given (Model, Action) pair (see its own doc comment), so for any action registered via BRIDGE_REGISTER_ACTION this answers the same for either Sharing – the template parameter exists for symmetry with execute<Sharing> and to stay correct if that ever changes, not because the two currently disagree.
| Sharing | NoSharing or AllowShared — the caller's own sharing policy. |
| modelId | String id of the target model. |
| actionId | String id of the action to check. |
Definition at line 130 of file bridge.hpp.
|
inlinestatic |
Returns the process-level singleton registry.
Definition at line 209 of file bridge.hpp.