Postgrex notifications

CREATE OR REPLACE FUNCTION notify_posts_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(
'posts_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;
CREATE TRIGGER notify_posts_changes_trg
AFTER INSERT OR UPDATE OR DELETE
ON posts
FOR EACH ROW
EXECUTE PROCEDURE notify_posts_changes();
LISTEN posts_changes;
pg_config = Application.get_env(:posts, Posts.Repo)
{:ok, pid} = Postgrex.Notifications.start_link(pg_config)
{:ok, ref} = Postgrex.Notifications.listen(pid, channel)
receive do
notification -> notification
end
receive do
{:notification, pid, ref, "posts_changes", payload} -> payload
end
Poison.decode! payload
...
children = [
...,
worker(Posts.PgListener, ["posts_changes"], id: :posts_changes),
...
]
...
defmodule Posts.PgListener do
use GenServer
import Poison, only: [decode!: 1] def start_link(channel) do
GenServer.start_link(__MODULE__, channel)
end
def init(channel) do
pg_config = Application.get_env(:posts, Posts.Repo)
{:ok, pid} = Postgrex.Notifications.start_link(pg_config)
{:ok, ref} = Postgrex.Notifications.listen(pid, channel)
{:ok, {pid, channel, ref}
end
def handle_info(
{:notification, pid, ref, "posts_changes", payload},
{pid, channel, ref} = state) do
Posts.Endpoint.broadcast("posts", "change", decode!(payload)
{:noreply, state}
end
end

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store