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.