hi,
I was trying to build the notification using this tutorial here
- Created the todo channel
defmodule PgsubWeb.TodoChannel do
use PgsubWeb, :channel
alias Pgsub.Pgsub.Todo
alias Pgsub.Repo
def join("todo:list", payload, socket) do
if authorized?(payload) do
{:ok, socket}
else
{:error, %{reason: "unauthorized"}}
end
end
def handle_in("todos", _payload, socket) do
broadcast_all_to!(socket)
{:noreply, socket}
end
def handle_in("insert", %{"todo" => data}, socket) do
%Todo{}
|> Todo.changeset(data)
|> Repo.insert!
broadcast_all_to!(socket)
{:noreply, socket}
end
def handle_in("update", %{"todo" => data}, socket) do
Todo
|> Repo.get(data["id"])
|> Todo.changeset(data)
|> Repo.update!
broadcast_all_to!(socket)
{:noreply, socket}
end
def handle_in("delete", %{"todo" => data}, socket) do
Todo
|> Repo.get(data["id"])
|> Repo.delete!
broadcast_all_to!(socket)
{:noreply, socket}
end
defp authorized?(_payload) do
true
end
defp broadcast_all_to!(socket) do
todos = Todo |> Repo.all
PgsubWWeb.Endpoint.broadcast!(socket.topic, "todos", %{todos: todos})
end
end
- created the trigger migration for the user
CREATE OR REPLACE FUNCTION notify_todos_changes()
RETURNS trigger AS $$
DECLARE
current_row RECORD;
BEGIN
IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
current_row := NEW;
ELSE
current_row := OLD;
END IF;
PERFORM pg_notify(
'todos_changes',
json_build_object(
'table', TG_TABLE_NAME,
'type', TG_OP,
'id', current_row.id,
'data', row_to_json(current_row)
)::text
);
RETURN current_row;
END;
$$ LANGUAGE plpgsql;
- Creating a genserver to handle the notification
defmodule Pgsub.Notifications do
use GenServer
alias Pgsub.{Pgsub.Todo, Repo}
import Poison, only: [decode!: 1]
def start_link(channel) do
GenServer.start_link(__MODULE__, channel)
end
def init(channel) do
{:ok, pid} = Application.get_env(:pgsub, Pgsub.Repo)
|> Postgrex.Notifications.start_link()
ref = Postgrex.Notifications.listen!(pid, channel)
data = Todo |> Repo.all
{:ok, {pid, ref, channel, data}}
end
@topic "todo:list"
def handle_info({:notification, pid, ref, "todos_changes", payload}, {pid, ref, channel, data}) do
%{
"data" => raw,
"id" => id,
"table" => "todos",
"type" => type
} = decode!(payload)
row = for {k, v} <- raw, into: %{}, do: {String.to_atom(k), v}
updated_data = case type do
"UPDATE" -> Enum.map(data, fn x -> if x.id === id do Map.merge(x, row) else x end end)
"INSERT" -> data ++ [struct(Todo, row)]
"DELETE" -> Enum.filter(data, &(&1.id !== id))
end
PgsubWeb.Endpoint.broadcast!(@topic, "todos", %{todos: updated_data})
{:noreply, {pid, ref, channel, updated_data}}
end
end
After all this when I’m trying to insert the new user. I’m not getting the notification that I have inserted the new user. Although when I’m trying to insert something else which is not user.
It’s giving me some pid which I don’t know how to get when I’m inserting the user
Last message: {:notification, #PID<0.702.0>, #Reference<0.289176621.289406977.235956>
Can anyone help me here