Current section
Files
Jump to
Current section
Files
lib/routemaster/drain/json_decoder.ex
defmodule Routemaster.Drain.JsonDecoder do
@moduledoc """
Wraps Poison to explicitly decode JSON into `Routemaster.Drain.Event` structures.
"""
alias Routemaster.Drain.Event
defmodule InvalidPayloadError do
@moduledoc false
defexception [:message]
end
@doc """
This function is the only [expected interface](https://github.com/elixir-lang/plug/blob/v1.3.5/lib/plug/parsers/json.ex#L47)
for the decoder objects.
The caller expects this to raise exceptions in case of failures.
This decoder is only used to parse JSON payloads received from the bus.
The JSON body received from the bus should always be a list, so if it valid
JSON but is not a list this function will raise a `Routemaster.Drain.JsonDecoder.InvalidPayloadError`
exception.
"""
@spec decode!(binary) :: list
def decode!(body) do
case Poison.decode!(body, as: [%Event{}]) do
list when is_list(list) ->
validate!(list)
_ ->
raise InvalidPayloadError, message: "Received payload is not an array"
end
end
defp validate!(list) do
if all_events_complete?(list) do
list
else
raise InvalidPayloadError, message: "The events in the received payloads are not complete"
end
end
defp all_events_complete?([]), do: true
defp all_events_complete?(list) do
Enum.all?(list, &Event.complete?/1)
end
end