bitwalker / swarm

Easy clustering, registration, and distribution of worker processes for Erlang/Elixir
MIT License
1.19k stars 102 forks source link

No function clause matching Swarm.IntervalTreeClock.sum/2 #141

Open balena opened 4 years ago

balena commented 4 years ago

I'm using Swarm in a big cluster and I'm always getting the following error in exactly one node:

00:34:51.845 [error] GenStateMachine Swarm.Tracker terminating
** (FunctionClauseError) no function clause matching in Swarm.IntervalTreeClock.sum/2
    (swarm 3.4.0) lib/swarm/tracker/crdt.ex:140: Swarm.IntervalTreeClock.sum(1, {0, 1})
    (swarm 3.4.0) lib/swarm/tracker/crdt.ex:29: Swarm.IntervalTreeClock.join/2
    (swarm 3.4.0) lib/swarm/tracker/tracker.ex:1005: Swarm.Tracker.handle_replica_event/4
    (stdlib 3.13) gen_statem.erl:1166: :gen_statem.loop_state_callback/11
    (stdlib 3.13) proc_lib.erl:226: :proc_lib.init_p_do_apply/3

Basically it is attempting to join two interval tree clocks 1 and {0, 1}, which, apparently by definition, is undefined. The ITC 1 is coming from the %TrackerState which holds a clock with this value 1.

Either the ITC is missing a definition for this case or the Swarm code is saving 1 in %TrackerState.clock in a wrong way.

balena commented 4 years ago

I was able to reproduce the problem as follows:

> {lclock, rclock} = Clock.seed() |> Clock.fork()
> {lclock1, rclock1} = Clock.fork(lclock)
> Clock.join(lclock, rclock1) 
** (FunctionClauseError) no function clause matching in Swarm.IntervalTreeClock.sum/2

    The following arguments were given to Swarm.IntervalTreeClock.sum/2:

        # 1
        1

        # 2
        {0, 1}

    Attempted function clauses (showing 3 out of 3):

        defp sum(0, x)
        defp sum(x, 0)
        defp sum({l1, r1}, {l2, r2})

    lib/swarm/tracker/crdt.ex:140: Swarm.IntervalTreeClock.sum/2
    lib/swarm/tracker/crdt.ex:142: Swarm.IntervalTreeClock.sum/2
    lib/swarm/tracker/crdt.ex:29: Swarm.IntervalTreeClock.join/2

As I understand, you cannot join clocks of different "generations".