Building StateHandoff Interface
Testing state handoff
Before implementing the DeltaCrdt library to create a replicated data store, I first want to build the interface for the data store.
Yesterday, I created the StateHandoff module to play around with cluster node join/leave events, but it doesn’t actually do anything yet.
I create a new test module which will help me think about the public interface for this module and guide my design decsions as I implement the desired behavior.
| |
The cluster setup logic is duplicated from my existing Minotaur.Cluster.GameSessionTest module, but I’m not too worried about refactoring this code for reuse at this point.
The test module does not compile because StateHandoff does not yet implement the stash or pickup functions.
The test is guiding me to write these functions, but I will only write enough to make the module compile.
Once it compiles, I’ll continue to work in small steps to make the test pass.
defmodule Minotaur.Cluster.StateHandoffTest do
# ...
def stash(_key, _value) do
:ok
end
def pickup(_key) do
nil
end
end
I now have a compiling, but failing test.
Breaking down the problem
Thinking about what I need to make this test case pass, I realize I can break the problem down further. I can first implement the feature for stashing and picking up state with a single node, then build another feature off that which supports multiple nodes interacting with the store. Splitting the work into two features will allow me to work in smaller steps and focus on less scope of work at a time.
I’ll leave this first test case in a failing state for now since it covers the second feature behavior. I create a new test case to validate a single node can pick up stashed state.
| |
I can now focus on implementing DeltaCrdt for a single node and delay worrying about how the state will be synced across the cluster.
I install DeltaCrdt as a dependency in my mix.exs file.
Then, I update the StateHandoff module to start a linked CRDT process and store the pid as the GenServer state.
| |
I update the stash function to call the GenServer with a :stash event and then implement the callback handler for the event.
| |
I run the test case which fails because the StateHandoff GenServer is not yet started.
It is time to add the handoff module to the top-level application supervision tree so it starts up on each node.
The test still fails, but it doesn’t blow up before it reaches the assertion in the test case.
1) test when state is stashed by one node state can be picked up from same node (Minotaur.Cluster.StateHandoffTest)
test/cluster/state_handoff_test.exs:23
Assertion with == failed
code: assert {:ok, @stash_value} == res
left: {:ok, %Minotaur.GameEngine.Game{id: "ABYZ", round_end_time: nil, world: nil, players: nil, registered_actions: %{}, round: 1}}
right: nil
Now I need to implement the pickup function to retrieve the stored data from the CRDT process.
| |
The test case for a single node is now passing!
I don’t have much time today to continue, but I’m happy with the small progress and a clear path for where to go next.