Current section

Files

Jump to
evoq src evoq_hope.erl
Raw

src/evoq_hope.erl

%% @doc Hope behavior for evoq.
%%
%% Hopes are integration artifacts for outbound RPC requests between
%% agents or bounded contexts. Unlike facts (fire-and-forget), hopes
%% expect a response.
%%
%% Key characteristics:
%% - Binary keys (JSON-safe), serializable for transport
%% - Represent a request/intention directed at another agent
%% - Cross boundary via mesh RPC or similar transport
%% - Named "hope" because the caller hopes for a response but
%% cannot guarantee one (distributed systems reality)
%%
%% == Required Callbacks ==
%%
%% - hope_type() -> binary()
%% - new(Params) -> {ok, Hope} | {error, Reason}
%% - to_payload(Hope) -> map()
%% - from_payload(Payload) -> {ok, Hope} | {error, Reason}
%%
%% == Optional Callbacks ==
%%
%% - validate(Hope) -> ok | {error, Reason}
%% - serialize(Payload) -> {ok, binary()} | {error, Reason}
%% - deserialize(Binary) -> {ok, map()} | {error, Reason}
%% - schema() -> map()
%%
%% @author rgfaber
-module(evoq_hope).
%% Required callbacks
-callback hope_type() -> binary().
-callback new(Params :: map()) -> {ok, Hope :: term()} | {error, Reason :: term()}.
-callback to_payload(Hope :: term()) -> map().
-callback from_payload(Payload :: map()) -> {ok, Hope :: term()} | {error, Reason :: term()}.
%% Optional callbacks
-callback validate(Hope :: term()) -> ok | {error, Reason :: term()}.
-callback serialize(Payload :: map()) -> {ok, binary()} | {error, Reason :: term()}.
-callback deserialize(Binary :: binary()) -> {ok, map()} | {error, Reason :: term()}.
-callback schema() -> map().
-optional_callbacks([validate/1, serialize/1, deserialize/1, schema/0]).
%% Default implementations
-export([default_serialize/1, default_deserialize/1]).
%% @doc Default serialization using OTP 27 json module.
-spec default_serialize(map()) -> {ok, binary()} | {error, term()}.
default_serialize(Payload) when is_map(Payload) ->
try
{ok, json:encode(Payload)}
catch
error:Reason -> {error, {json_encode_failed, Reason}}
end.
%% @doc Default deserialization using OTP 27 json module.
-spec default_deserialize(binary()) -> {ok, map()} | {error, term()}.
default_deserialize(Binary) when is_binary(Binary) ->
try
{ok, json:decode(Binary)}
catch
error:Reason -> {error, {json_decode_failed, Reason}}
end.