Once you have an Elixir project with many processes communicating, you’ll eventually run into the need for a consumer to ask a question that your asynchronous processes might or might not yet have the data to answer. For programmers new to concurrent programming it can be tempting to just use :timer.sleep/1 in front of your request to “guarantee” that the asynchronous work has been completed. Or maybe you’d be tempted to build in some polling logic where you keep checking a process's state periodically until it has the information you expect. Both options are less than ideal.

With the release of Elixir 1.4 we have some awesome tools built into the standard library to help us handle situations like this. We’ll be using the Registry module to function as a pubsub server to help with this problem.

Our AsyncWorker has a public api of get/1 set/2 which should seem pretty straightforward. In this case however, we need our get/1 function to support eventually having the value that we need. This is where the Registry comes in.

Let’s follow our get/1 function. We use GenServer.call/2 to send the {:get, "some-key"} message. That is handled on line 35. Map.get/3 allows us to get the value for the requested key from our state if it has been set, but if it hasn’t we provide a default of {:wait, @registry, key} . This gives the client all the information it needs to subscribe to receive messages from the server using Registry.register/3 (you can see the implementation in wait/2 ).

Ok let’s look at what happens when the server gets it’s {:set, “some-key", “some-value"} message. We handle that cast on line 40. We immediately call the private broadcast/2 message which uses Registry.dispatch/3 to broadcast a message to all processes that are subscribed to the topic (in our case the requested key) on the registry.