Skip to content

Commit d031518

Browse files
committed
relax drift? to match the paper and unburden the client
1. Relax recv max drift to check only `l - pt` and not `abs(l - pt)`. In the paper, maximum drift is limited to the absolute value of the difference between the logical and physical time as a corollary of the algorithm, which only requires checking when the logical clock is in the future of physical time. This allows us to recv old timestamps, which simplifies clients by allowing them to recv the timestamps of all events before acting and allowing this library to ensure that the causal order is preserved. 2. We were checking max drift on send, but that only catches errors caused by a system administrator setting the system clock to jump or, more commonly, causing an error whenever the computer running the VM sleeps.
1 parent 5859ff4 commit d031518

3 files changed

Lines changed: 17 additions & 25 deletions

File tree

lib/hlclock/server.ex

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,8 @@ defmodule HLClock.Server do
3434
end
3535

3636
def handle_call(:send_timestamp, _from, data) do
37-
case Timestamp.send(data.timestamp, physical_time(), data.max_drift) do
38-
{:ok, timestamp} ->
39-
{:reply, {:ok, timestamp}, %{data | timestamp: timestamp}}
40-
41-
{:error, error} ->
42-
{:reply, {:error, error}, data}
43-
end
37+
{:ok, timestamp} = Timestamp.send(data.timestamp, physical_time())
38+
{:reply, {:ok, timestamp}, %{data | timestamp: timestamp}}
4439
end
4540

4641
def handle_call(
@@ -60,13 +55,8 @@ defmodule HLClock.Server do
6055
def handle_info(:periodic_send, data) do
6156
Process.send_after(self(), :periodic_send, interval(data))
6257

63-
case Timestamp.send(data.timestamp, physical_time(), data.max_drift) do
64-
{:ok, ts} ->
65-
{:noreply, %{data | timestamp: ts}}
66-
67-
{:error, _} ->
68-
{:noreply, data}
69-
end
58+
{:ok, ts} = Timestamp.send(data.timestamp, physical_time(), data.max_drift)
59+
{:noreply, %{data | timestamp: ts}}
7060
end
7161

7262
defp physical_time, do: System.os_time(:millisecond)

lib/hlclock/timestamp.ex

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ defmodule HLClock.Timestamp do
1010
languages/representations.
1111
"""
1212

13+
import Kernel, except: [send: 2]
14+
1315
defstruct [:time, :counter, :node_id]
1416

1517
alias __MODULE__, as: T
@@ -41,13 +43,19 @@ defmodule HLClock.Timestamp do
4143
Generate a single HLC Timestamp for sending to other nodes or
4244
local causality tracking
4345
"""
44-
def send(%{time: old_time, counter: counter, node_id: node_id}, pt, max_drift) do
46+
def send(%{time: old_time, counter: counter, node_id: node_id}, pt) do
4547
new_time = max(old_time, pt)
4648
new_counter = advance_counter(old_time, counter, new_time)
49+
{:ok, new(new_time, new_counter, node_id)}
50+
end
4751

48-
with :ok <- handle_drift(old_time, new_time, max_drift) do
49-
{:ok, new(new_time, new_counter, node_id)}
50-
end
52+
# Compatibility for older users of Timestamp that may be providing the max_drift.
53+
def send(
54+
%{time: old_time, counter: counter, node_id: node_id},
55+
pt,
56+
_max_drift
57+
) do
58+
send(%{time: old_time, counter: counter, node_id: node_id}, pt)
5159
end
5260

5361
@doc """
@@ -186,7 +194,7 @@ defmodule HLClock.Timestamp do
186194
end
187195

188196
defp drift?(l, pt, max_drift) do
189-
abs(l - pt) > max_drift
197+
l - pt > max_drift
190198
end
191199

192200
defp advance_counter(old_time, counter, new_time) do

test/hlclock/timestamp_test.exs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,6 @@ defmodule HLClock.TimestampTest do
104104
assert t0.time == t1.time
105105
assert t1.counter == 1
106106
end
107-
108-
test "send can fail due to excessive drift" do
109-
t0 = Timestamp.new(0, 0, 0)
110-
{:error, err} = Timestamp.send(t0, 5 + 1, @max_drift)
111-
assert err == :clock_drift_violation
112-
end
113107
end
114108

115109
describe "recv_timestamp/2" do

0 commit comments

Comments
 (0)