What is the best way in elixir to create a foreground process that tick on every given amount of time?
My main problem is that an approach like:
defmoulde Ticker do
def tick do
do_something()
:timer.sleep(1000)
tick
end
end
works, but is wrong by design. It's definitely not ticking every second, but every second PLUS the time for do_something() to complete. I could spawn a process to handle the "something" but still there is a small lag.
Also, I'm trying to build a mix app, there is some GenServers involved, and a main foreground process (the one I'm asking here) that should call the servers every x seconds. Is there an otp way of doing this?
If you prefer sending a message instead of calling a function at a given interval, you can use :timer.send_interval/3
E.g. if you want to send a message to a GenServer
every second as OP mentions in their answer, you could do the following:
:timer.send_interval(:timer.seconds(1), target_pid, :tick)
Where target_pid
is the PID of the GenServer
you want to send a message to. Then you can handle this message in your GenServer
like this:
def handle_info(:tick, state) do
do_something()
{:noreply, state}
end
I think timer:apply_interval/4
should suit your needs. It is used something like this:
defmodule Tick do
def tick do
IO.inspect(:tick)
end
end
:timer.apply_interval(:timer.seconds(1), Tick, :tick, [])
The arguments in order are the interval, a module name, the function to call and the arguments to call it with. Then you can send messages to your GenServers
inside that function. Check out the full documentation here: apply_interval/4
Another thing to consider is that if your tick
function is only ever sending simple messages to some GenServers
then it is probably extremely fast, so your implementation might be OK, once wrapped in a Task
and plugged into the supervision tree (if you don't care about the potential slight drift that is).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With