MaxiTaxi is a very simple application:
- Taxis send their location information to MaxiTaxi.
- Customers can order a taxi and use it to get from A to B.
The system will track:
- The last known position of each taxi.
- Whether a taxi is occupied or not.
The following operations will be supported:
- Update the location of a taxi.
- Search for a nearby taxi that is unoccupied.
- Enter a taxi.
- Leave a taxi.
The tutorial is split into 4 branches:
exercise_1
exercise_2
exercise_3
exercise_4
You can start with exercise_1
. If you have completed the exercises, then you can continue in that branch with your own solutions, or you can choose to switch to the exercise_2
branch to continue.
The topics covered are:
- libcluster & :rpc
- Distributed location database
- Horde
- Horde partition tolerance
Install libcluster in the application.
Configure libcluster using the guide in the README (Cluster.Strategy.Epmd
) to connect nodes maxi1@127.0.0.1
and maxi2@127.0.0.1
.
Start the nodes:
iex --name maxi1@127.0.0.1 -S mix
iex --name maxi2@127.0.0.1 -S mix
Confirm that the nodes are connected:
iex(maxi1@127.0.0.1)1> Node.list()
[:"maxi2@127.0.0.1"]
We will distribute the location database to all nodes in the cluster. We will use :rpc.call/4
for this.
- Send updates to all nodes in the cluster using
:rpc.call/4
. - Implement a TTL of 2s on updates to prevent stale information from being served (in case of a netsplit for example).
Use send/2
instead of :rpc.call/4
. This will help us avoid bottlenecks in :rpc
.
Reminder: {name, node}
.
Now we have a "distributed location database", but there is no way for nodes to recover if there is a conflict.
- Use
delta_crdt
to make the database eventually consistent.
Note: information on nodes can still be out of date, but after a netsplit the database will globally converge.
A taxi can be entered and exited, but we can't allow more than one customer to enter a taxi.
We will use Horde
(docs) to distribute taxi processes among the nodes in the cluster. We will register and access the taxi processes using Horde.Registry
. Horde.Registry
will also keep them unique.
Horde.DynamicSupervisor
will ensure that if a node goes down, that the taxi processes are restarted on another node.
- start taxi state processes using Horde.DynamicSupervisor
- register processes with Horde.Registry