Skip to content

Conversation

@foxfriends
Copy link

@foxfriends foxfriends commented Dec 29, 2025

Added support for PostgreSQL LISTEN/NOTIFY by lightly wrapping the implementation in pgo.

As in pgo:

  • The notifications listener is started as a new process, different from a regular connection.
  • The listen(conn, channel) function subscribes to a Postgres channel.
  • unlisten(conn, reference) can be used to unsubscribe.
  • Notifications from Postgres are sent to the process that called listen as the Notify type. Receive these using the pog.notification_selector().

General usage example:

let assert Ok(db) = pog.default_config("db")
    |> pog.start()

let assert Ok(notifications) = pog.default_config("notifications")
    |> pog.start_notifications()

let assert Ok(reference) = pog.listen(notifications.data, "some_channel")

let selector = pog.notification_selector()

let assert Ok(_) = pog.query("NOTIFY some_channel, 'some_payload'")
    |> pog.execute(db.data)

let assert Ok(Notify(pid, ref, chan, data)) = process.selector_receive(selector, 100)
assert pid == notifications.pid
assert ref == reference
assert chan == "some_channel"
assert data = "some_payload"

pog.unlisten(notifications.data, reference)

Closes #13

@foxfriends foxfriends force-pushed the main branch 3 times, most recently from 4184091 to dae5cc3 Compare December 31, 2025 19:05
Added support for PostgreSQL `LISTEN/NOTIFY` by lightly wrapping the
implementation in `pgo`.

As in `pgo`:
* The notifications listener is started as a new process, different from a regular connection.
* The `listen(conn, channel)` function subscribes to a Postgres channel.
* `unlisten(conn, reference)` can be used to unsubscribe.
* Notifications from Postgres are sent to the process that called `listen` as the `Notify` type. Receive these using the `pog.notification_selector()`.

General usage example:

```gleam
let assert Ok(db) = pog.default_config("db")
    |> pog.start()

let assert Ok(notifications) = pog.default_config("notifications")
    |> pog.start_notifications()

let assert Ok(reference) = pog.listen(notifications.data, "some_channel")

let selector = pog.notification_selector()

let assert Ok(_) = pog.query("NOTIFY some_channel, 'some_payload'")
    |> pog.execute(db.data)

let assert Ok(Notify(pid, ref, chan, data)) = process.selector_receive(selector, 100)
assert pid == notifications.pid
assert ref == reference
assert chan == "some_channel"
assert data = "some_payload"

pog.unlisten(notifications.data, reference)
```
@foxfriends
Copy link
Author

erleans/pgo#119

I found and patched a bug in the underlying pgo implementation, so I suggest waiting until that's merged before considering accepting this PR.

Having been trying out my patch for a few days in a project, I am finding it to work fine, but maybe is not the most idiomatic Gleam; pretty new to it all, and not sure the best way to represent this system, I went with a "light" approach so far, mimicking the pgo interface, but open to suggestions to make it more "Gleam" flavoured for sure. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LISTEN/NOTIFY support?

1 participant