Created
June 2, 2021 13:16
-
-
Save slashdotdash/3fe2dbcac4193f3bcd42a14f14188091 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule InvalidEvent do | |
@doc """ | |
Module to be used when an event cannot be deserialized from the event store. | |
The payload field will be populated with the source event data if | |
deserialization is possible. | |
Receiving this event usually indicates an event has been removed or renamed in | |
the source code between releases. Deserializing to this invalid event module | |
allows the application to continue running, otherwise it would terminate as | |
the persisted event cannot be deserialized to a valid or existing Elixir | |
struct. | |
""" | |
defstruct [:payload] | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule JsonSerializer do | |
@moduledoc """ | |
A serializer that uses the JSON format. | |
Events that cannot be deserialized, due to missing event module, will be | |
replaced by `InvalidEvent` which includes a payload field containing the | |
original event data. | |
""" | |
require Logger | |
alias Commanded.Serialization.JsonDecoder | |
@doc """ | |
Serialize given term to JSON binary data. | |
""" | |
def serialize(term) do | |
Jason.encode!(term) | |
end | |
@doc """ | |
Deserialize given JSON binary data to the expected type. | |
""" | |
def deserialize(binary, config \\ []) do | |
{type, opts} = | |
case Keyword.get(config, :type) do | |
nil -> {nil, []} | |
type -> {TypeProvider.to_struct(type), [keys: :atoms]} | |
end | |
case decode(binary, type, opts) do | |
{:ok, event} -> | |
event | |
:error -> | |
decode_invalid_event(binary, opts) | |
end | |
end | |
# Attempt to deserialize as an invalid event. | |
defp decode_invalid_event(binary, opts) do | |
case decode("{\"payload\": #{binary}}", %InvalidEvent{}, opts) do | |
{:ok, %InvalidEvent{} = event} -> | |
event | |
:error -> | |
# Decoding the source event as the invalid event payload failed, just | |
# return an empty `InvalidEvent` struct | |
%InvalidEvent{} | |
end | |
end | |
defp decode(binary, type, opts) do | |
try do | |
decoded = | |
binary | |
|> Jason.decode!(opts) | |
|> to_struct(type) | |
|> JsonDecoder.decode() | |
{:ok, decoded} | |
rescue | |
error -> | |
Logger.error(fn -> | |
"Failed to deserialize event #{inspect(binary)} due to: " <> inspect(error) | |
end) | |
:error | |
end | |
end | |
defp to_struct(data, nil), do: data | |
defp to_struct(data, struct), do: struct(struct, data) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment