Current section

Files

Jump to
one_piece_commanded lib one_piece commanded protobuf_mapper.ex
Raw

lib/one_piece/commanded/protobuf_mapper.ex

if Code.ensure_loaded?(Protobuf) do
defprotocol OnePiece.Commanded.ProtobufMapper do
@moduledoc """
Protocol for encoding and decoding `Protobuf` structs.
The protocol is required when using the `OnePiece.Commanded.EventStore.ProtobufJsonbSerializer` serializer and
working with Aggregate snapshotting. Since the Aggregates are not `Protobuf` structs, the serializer needs to
encode and decode them to a `Protobuf` struct.
## Example
```elixir
defmodule MyApp.MyAggregate do
alias MyApp.Proto.MyAggregateProto
use OnePiece.Commanded.Aggregate, identifier: :id
embedded_schema do
field(:initiated?, :boolean, default: false)
end
end
defimpl OnePiece.Commanded.ProtobufMapper, for: MyApp.MyAggregate do
alias MyApp.MyAggregate
alias MyApp.Proto.MyAggregateProto
def message_module(%MyAggregate{} = _aggregate), do: MyAggregateProto
def to_proto_message(%MyAggregate{} = aggregate) do
%MyAggregateProto{
id: aggregate.id,
initiated: aggregate.initiated?
}
end
def from_proto_message(%MyAggregate{} = aggregate, %MyAggregateProto{} = proto_message) do
aggregate
|> Map.put(:id, proto_message.id)
|> Map.put(:initiated?, proto_message.initiated)
end
end
```
"""
@fallback_to_any true
@doc """
Given a struct, returns a `Protobuf` struct.
The default implementation returns the message itself because implicitly expects the struct to be a
`Protobuf` struct. No need to map the struct to the message.
"""
def to_proto_message(message)
@doc """
Given the initial message, and the decoded `Protobuf` struct, returns the decoded term.
The default implementation returns the decoded term itself because implicitly expects the initial message to be a
`Protobuf` struct. No need to map the decoded term to the initial message.
"""
def from_proto_message(message, term)
@doc """
Returns the module name of the `Protobuf` struct.
The default implementation returns the struct name of the message because implicitly expects the struct to be a
`Protobuf` struct. No need to map the struct to the message.
"""
def proto_module(message)
end
defimpl OnePiece.Commanded.ProtobufMapper, for: Any do
def to_proto_message(message) do
message
end
def from_proto_message(_message, term) do
term
end
def proto_module(%module_name{} = _message) do
module_name
end
end
end