tl;dr:
Given the simplicity of the request anything other than a GenServer seems overkill.
def handle_call(:got_partner?, {pid, _ref}, nil), do: {:reply, :ok, pid}
def handle_call(:got_partner?, {pid, _ref}, pid), do: {:reply, :ok, pid}
def handle_call(:got_partner?, {pid, _ref}, waiting) when is_pid(waiting) do
Supervisor.start_child(App.GameServer.Supervisor, [waiting, pid])
{:reply, :ok, nil}
end
Looking at my code your first question may be to ask why I would have a "Puritan Clause"[tm] to prevent a player from playing with themselves[0].
To defend against a player getting orphaned if they're in the queue and the MatchMaker GenServer (above) crashes I would put an :erlang.send_event call in the Player GenServer to re-submit them every 10 seconds until they've been moved into a game. The "Puritan Clause"[tm] ensures that if a different player doesn't arrive in those 10 seconds they're not dispatched to play with themselves.
Now for the "too long"[1]:
There are many ways to skin this cat. I'm hoping you get a variety of answers. Here's mine from the point of view of someone who has a very high bar that must be met before I consider adding an RDBMS.
With an RDBMS you gain:
- Persistence
- Easy visibility of data for other tools via SQL.
You also gain:
- An external dependency that doesn't use the same failure characteristics as the beam.
- Latency.
- Additional complexity in deployment.
This certainly isn't a significant enough requirement in my mind to reach for an RDBMS but if you're using it for something else in your application then the bar has already been met. But should you still use it even if it's there already?
The way you describe your matchmaking process it sounds as simple as "is there anyone in the queue already?" so that's what I implemented. I explicitly chose to serialize requests __because it's a queue__ and our actions upon it need to be atomic. To make those atomic you need to do transactions on a single column single row table. This will serialize all your requests __outside of your control__.
Naturally, if your requirements became more complex or you're needing to interoperate with other applications written in other languages an RDBMS may make more sense. Apart from having to match based on criteria that already exists in a database from long queue lengths I can't think of any good reason to use it. Nope, even with that I still can't. Others on the list may...
ETS is another option which would allow the player GenServers to "self-organize". Far more complex in my view.
If you want to talk about the scenario where you have multiple systems in a cluster which are geographically distributed and you want to deal with network partitioning then I'd be looking at :gproc. You'd want to try in the main to keep your players in the same systems / regions as much as possible so additional metadata like that would be useful in your decision making.
Thanks,