Using receive/1 for timeouts

Elixir has a function receive/1 which is defined in the Kernel.SpecialForms module and is available for use anywhere in your code without the module prefix.

The receive/1 takes an optional after clause with a timeout value that gets executed if the process has not received a matching message in the given time. We can combine this with a recursive call to execute code at given intervals.

If that sounds cryptic I hope this helps

defmodule Example do def process() do

receive do

after

5_000 ->

IO.puts "5 seconds elapsed"

process()

end

end end

If you were to call the process/0 function here it would keep printing “5 seconds elapsed” every 5 seconds.

Creating a periodic Task module

The function above isn’t terribly useful by itself, for one it never returns and besides we’d want it to start when the application starts.

We can create a module that starts our process in a Task and can be added to the applications supervision tree

defmodule Example.BitcoinPriceUpdater do

use Task def start_link(_arg) do

Task.start_link(&poll/0)

end def poll() do

receive do

after

60_000 ->

get_price()

poll()

end

end defp get_price() do

# Call API & Persist

IO.puts "To the moon!"

end end

If you are on Elixir 1.5 or newer by using the use Task at the top of your module your Application supervisor can do something like this



defmodule Example.Application do @moduledoc false use Application def start(_type, _args) do

children = [

Example.BitcoinPriceUpdater

] opts = [strategy: :one_for_one, name: Example.Supervisor]

Supervisor.start_link(children, opts)

end

end

If you are on an older version of Elixir you’ll have to specify the children with something like this instead

children = [

worker(Example.BitcoinPriceUpdater, [])

]

In any case what you have is a module as part of your Application supervision tree that is started automatically when your Application is started and it will keep calling the given piece of code periodically.