defmodule DVR do @moduledoc """ Documentation for Dvr. """ @type replay_id() :: integer() @type payload() :: any() @type topics() :: list(String.t()) require Logger @spec record(payload(), topics()) :: {:ok, replay_id()} | {:error, any()} def record(payload, topics), do: record(payload, topics, calculate_id()) def record(payload, topics, id) do write = fn -> :mnesia.write({:dvr, id, payload, topics}) end case :mnesia.transaction(write) do {:atomic, _} -> {:ok, id} err -> {:error, err} end end @spec replay(replay_id()) :: {:ok, list(tuple)} | {:error, any()} def replay(id) do select = fn -> :mnesia.select(:dvr, [ { {:dvr, :"$1", :"$2", :"$3"}, [{:>, :"$1", id}], [:"$$"] } ]) end case :mnesia.transaction(select) do {:atomic, result} -> Stream.map(result, fn [_, payload, topics] -> {payload, topics} end) err -> {:error, err} end end @spec search(replay_id()) :: {:ok, replay_id()} | {:not_found, replay_id()} def search(id) do read = fn -> :mnesia.read({:dvr, id}) end case :mnesia.transaction(read) do {:atomic, []} -> case :mnesia.transaction(fn -> :mnesia.first(:dvr) end) do {:atomic, earliest_id} -> {:not_found, earliest_id} err -> {:error, err} end {:atomic, _} -> {:ok, id} err -> {:error, err} end end @spec calculate_id() :: replay_id() def calculate_id, do: DateTime.utc_now() |> DateTime.to_unix(:microsecond) end