Packages

A GenServer that syncs HLClock timestamps between nodes using Phoenix.PubSub.

Current section

Files

Jump to
hlclock_synchronizer lib hlclock_synchronizer.ex
Raw

lib/hlclock_synchronizer.ex

defmodule HLClockSynchronizer do
@moduledoc """
Handles synchronization of the `HLClock` timestamps.
Periodic sync of timestamps between nodes helps to ensure one-way
causality determination across the system.
"""
use GenServer
@topic "hlclock"
@doc "Send a synchronization message to the cluster"
def sync(pubsub, clock) do
{:ok, ts} = HLClock.now(clock)
Phoenix.PubSub.broadcast_from(pubsub, self(), @topic, {:sync, ts})
end
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: opts[:name] || __MODULE__)
end
def init(opts) do
pubsub = Keyword.fetch!(opts, :pubsub)
clock = Keyword.fetch!(opts, :clock)
state = %{interval: opts[:interval] || :timer.seconds(30), pubsub: pubsub, clock: clock}
{:ok, state, {:continue, :pubsub_subscribe}}
end
def handle_continue(:pubsub_subscribe, state) do
Phoenix.PubSub.subscribe(state.pubsub, @topic)
{:noreply, state, {:continue, :setup_sync}}
end
def handle_continue(:setup_sync, state) do
sync(state.pubsub, state.clock)
schedule_sync(state.interval)
{:noreply, state}
end
defp schedule_sync(interval) do
:timer.send_after(interval, :send_sync)
end
def handle_info({:sync, remote_ts}, state) do
HLClock.recv_timestamp(state.clock, remote_ts)
{:noreply, state}
end
def handle_info(:send_sync, state) do
sync(state.pubsub, state.clock)
{:noreply, state}
end
end