Packages
ferricstore
0.11.4
0.11.14
0.11.12
0.11.11
0.11.10
0.11.9
0.11.8
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.0
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.2.0
0.1.0
FerricFlow durable workflows and queues with native-protocol storage, Raft durability, and Bitcask persistence.
Current section
Files
Jump to
Current section
Files
lib/ferricstore/raft/command_stamp.ex
defmodule Ferricstore.Raft.CommandStamp do
@moduledoc false
alias Ferricstore.HLC
alias Ferricstore.TermCodec
@max_physical_ms Bitwise.bsl(1, 48) - 1
@max_logical Bitwise.bsl(1, 16) - 1
defguardp valid_metadata(physical_ms, logical, wall_time_ms)
when is_integer(physical_ms) and physical_ms >= 0 and
physical_ms <= @max_physical_ms and is_integer(logical) and logical >= 0 and
logical <= @max_logical and is_integer(wall_time_ms) and wall_time_ms >= 0 and
wall_time_ms <= physical_ms
@type hlc_ts :: {non_neg_integer(), non_neg_integer()}
@type stamped_command ::
{term(), %{hlc_ts: hlc_ts(), wall_time_ms: non_neg_integer()}}
@spec stamp(term()) :: stamped_command()
def stamp({command, %{hlc_ts: {physical_ms, logical}, wall_time_ms: wall_time_ms}} = stamped)
when valid_metadata(physical_ms, logical, wall_time_ms) and is_tuple(command) do
stamped
end
def stamp({command, %{hlc_ts: _invalid_or_removed_stamp}}) when is_tuple(command) do
raise ArgumentError, "invalid stamped command metadata"
end
def stamp(command) do
{hlc_ts, wall_time_ms} = HLC.now_with_wall()
{command, %{hlc_ts: hlc_ts, wall_time_ms: wall_time_ms}}
end
@spec to_ttb(term()) :: {:ttb, binary()}
def to_ttb(command) do
{:ttb, TermCodec.encode(stamp(command))}
end
@spec decode_ttb(term()) :: {:ok, stamped_command()} | {:error, :invalid_preencoded_command}
def decode_ttb(binary) when is_binary(binary) do
with {:ok, term} <- TermCodec.decode(binary) do
case term do
{command,
%{
hlc_ts: {physical_ms, logical},
wall_time_ms: wall_time_ms
}} = stamped
when is_tuple(command) and valid_metadata(physical_ms, logical, wall_time_ms) ->
{:ok, stamped}
_invalid ->
{:error, :invalid_preencoded_command}
end
else
{:error, :invalid_external_term} -> {:error, :invalid_preencoded_command}
end
end
def decode_ttb(_binary), do: {:error, :invalid_preencoded_command}
end