I've got an elixir (Phoenix) application that retrieves analytic data for users at regular intervals.
I've got an AnalyticSupervisor
to supervise AnalyticWorker
s.
defmodule AnalyticsSupervisor do
use Supervisor
def start_link do
Supervisor.start_link(__MODULE__, [], name: :analytics_supervisor)
end
def init(_) do
children = [
worker(AnalyticsWorker, [])
]
supervise(children, strategy: :simple_one_for_one)
end
def start_worker(user) do
Supervisor.start_child(:analytics_supervisor, [user])
end
end
The AnalyticWorker
is is using gproc as a process registry to create a dynamic process name and queue an analytic call.
defmodule AnalyticsWorker do
use GenServer
def start_link(user) do
GenServer.start_link(__MODULE__, user, name: via_tuple(user))
end
defp via_tuple(user) do
{:via, :gproc, {:n, :l, {:analytics_worker, user.id}}}
end
def init(user) do
queue_analytic_call(user)
{:ok, user}
end
def queue_analytic_call(user) do
:timer.apply_after(50000, __MODULE__, :call_anlaytics, [user])
end
end
The AnaylticSupervisor
is started when my Phoenix application is started, and will queue up analytic calls for any existing users.
The problem is, if I start off another iex
session, this will also start the supervisor and workers - I'll end up with multiple processes for the same job.
I thought that using gproc
as a process registry, this would be prevented - but each iex
session is creating it's own process registry.
How to I ensure that the processes are unique, regardless of whether they're being queued by an iex session or my Phoneix application?
Is there a better way of achieving unique scheduled jobs than what I'm doing?