I’m trying to send a message automatically to all users subscribed to a specific channel every couple of seconds(it’s a status update type message). I’ve gotten everything working with a handle_info which I can test by setting up a :timer.send_interval(5_000, :updates) in the join function of the channel module. That works fine but with each user that joins another timer starts so its not ideal for actual usage. Any idea how to start a timer like that outside of the channel?
I’ve tried creating a function in the channel called start_updates which just has that timer line in it then calling it from lib/myapp.ex in the start function with Myapp.UpdateChannel.start_updates() and though it does get called the timer inside doesn’t appear to work.
I’m not quite sure if it really helps you, but there is quantum available at hex.pm, perhaps it may help you.
A quick and dirty solution which comes to my mind using it, were to have a function which connects to the channel, sends the message and leaves the channel again.
A much saner way, were to start a GenServer (or similar) with your app, which does connect to the channel and gets a message from quantum and on this message it gets translated into the channel message and then send. But I’m not quite sure, how GenServer-messages and Channel-messages behave alltogether.
I created a new file in /lib/myapp/update_users.ex
defmodule MyApp.UpdateUsers do
use GenServer
import Ecto
import Ecto.Query, only: [from: 1, from: 2]
def start_link do
GenServer.start_link(__MODULE__, %{})
end
def init(state) do
Process.send_after(self(), :work, 5_000) # In 5 seconds
{:ok, state}
end
def handle_info(:work, state) do
#get data here. I also set the start_id from the state or set it to 0
MyApp.Endpoint.broadcast("updates:activities", "activities", %{source: a.source, points: a.points, name: a.name})
# Start the timer again
Process.send_after(self(), :work, 5_000) # In 5 seconds
#pass the max_id into the state so we can skip previously seen data in next iteration
{:noreply, %{"last_id" => max_id}}
end
end
Then added
worker(MyApp.UpdateUsers,[])
into lib/myapp.ex in the start/2 method and it seems to work a charm