defmodule OhMyExOhIrcd.IRC.HLC do
@moduledoc """
Tiny Hybrid Logical Clock for tagging cluster-wide events.
A timestamp is `{wall_ms, logical, node}`. Sorting these gives a
total order that:
* tracks wall-clock time when clocks agree;
* stays monotonic across a node even if the wall clock jumps backward;
* breaks ties by `node` so two events with identical clocks still
sort consistently across the cluster.
Only useful for ordering CRDT log entries on heal — not a substitute
for proper consensus.
"""
use Agent
@type t :: {non_neg_integer(), non_neg_integer(), node()}
def start_link(_),
do: Agent.start_link(fn -> {0, 0} end, name: __MODULE__)
@spec now() :: t()
def now do
wall = System.system_time(:millisecond)
Agent.get_and_update(__MODULE__, fn {last_wall, last_logical} ->
if wall > last_wall do
{{wall, 0, node()}, {wall, 0}}
else
{{last_wall, last_logical + 1, node()}, {last_wall, last_logical + 1}}
end
end)
end
@doc "Observe an external timestamp; advance our clock so future stamps stay > it."
@spec observe(t()) :: :ok
def observe({wall, logical, _node}) do
Agent.update(__MODULE__, fn {our_wall, our_logical} ->
cond do
wall > our_wall -> {wall, logical}
wall == our_wall and logical > our_logical -> {wall, logical}
true -> {our_wall, our_logical}
end
end)
end
end
neiam
/oh-my-ex-oh-ircd
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
1.4 KiB · text
History
4b6fe3b