ProductPromotion
Logo

Elixir

made by https://0x3d.site

GitHub - cheerfulstoic/ecto_watch: EctoWatch allows you to easily get notifications about database changes directly from PostgreSQL.
EctoWatch allows you to easily get notifications about database changes directly from PostgreSQL. - cheerfulstoic/ecto_watch
Visit Site

GitHub - cheerfulstoic/ecto_watch: EctoWatch allows you to easily get notifications about database changes directly from PostgreSQL.

GitHub - cheerfulstoic/ecto_watch: EctoWatch allows you to easily get notifications about database changes directly from PostgreSQL.

EctoWatch

(Thanks to Erlang Solutions for sponsoring this project)

HexDocs documentation

EctoWatch allows you to easily setup notifications of database changes directly from PostgreSQL.

Often in Elixir applications a Phoenix.PubSub.broadcast is inserted into the application code to notify the rest of the application about inserts, updates, or deletions (e.g. Accounts.insert_user/Accounts.update_user/Accounts.delete_user). This has a few potential problems:

  • Developers may forget to call these functions and make updates directly through MyApp.Repo.*.
  • Often different standards of PubSub messages are used. 1
  • Often full records are used which can scale poorly since messages in Elixir are copied in memory when sent.
  • Sometimes records are sent preloaded with different associations in different cases, requiring either careful coordination or sending all associations regardless of where they are needed.

By getting updates directly from PostgreSQL, EctoWatch ensures that messages are sent for every change (even changes from other clients of the database). EctoWatch also establishes a simple, standardized set of messages for inserts, updates, and deletes so that there can be consistency across your application. By default only the id of the record is sent (makeing for smaller messages).

Example use-cases for EctoWatch

  • Updating LiveView in real-time
  • Sending emails when a record is updated
  • Updating a cache when a record is updated
  • Sending a webhook request to inform another system about a change

Usage

To use EctoWatch, you need to add it to your supervision tree and specify watchers for Ecto schemas and update types. It would look something like this in your application.ex file (after MyApp.Repo and MyApp.PubSub):

  alias MyApp.Accounts.User
  alias MyApp.Accounts.Package

  {EctoWatch,
   repo: MyApp.Repo,
   pub_sub: MyApp.PubSub,
   watchers: [
     {User, :inserted},
     {User, :updated},
     {User, :deleted},
     {Package, :inserted},
     {Package, :updated}
   ]}

This will setup:

  • triggers in PostgreSQL during application startup
  • an Elixir process for each watcher which listens for notifications and broadcasts them via Phoenix.PubSub

Then any process (e.g. a GenServer, a LiveView, a Phoenix channel, etc...) can subscribe to messages like so:

  EctoWatch.subscribe({User, :inserted})
  EctoWatch.subscribe({User, :updated})
  EctoWatch.subscribe({User, :deleted})

  EctoWatch.subscribe({Package, :inserted})
  EctoWatch.subscribe({Package, :updated})

(note that if you are subscribing in a LiveView mount callback you should subscribe inside of a if connected?(socket) do to avoid subscribing twice).

You can also subscribe to individual records:

  EctoWatch.subscribe({User, :updated}, user.id)
  EctoWatch.subscribe({User, :deleted}, user.id)

... OR you can subscribe to records by an association column (but the given column must be in the extra_columns list for the watcher! See below for more info on the extra_columns option):

  EctoWatch.subscribe({User, :updated}, {:role_id, role.id})
  EctoWatch.subscribe({User, :deleted}, {:role_id, role.id})

Once subscribed, messages can be handled like so (LiveView example are given here but handle_info callbacks can be used elsewhere as well):

  def handle_info({{User, :inserted}, %{id: id}}, socket) do
    user = Accounts.get_user(id)
    socket = stream_insert(socket, :users, user)

    {:noreply, socket}
  end

  def handle_info({{User, :updated}, %{id: id}}, socket) do
    user = Accounts.get_user(id)
    socket = stream_insert(socket, :users, user)

    {:noreply, socket}
  end

  def handle_info({{User, :deleted}, %{id: id}}, socket) do
    socket = stream_delete_by_dom_id(socket, :songs, "users-#{id}")

    {:noreply, socket}
  end

There are a lot of features to check out! Check out the HexDocs documentation for all of the details!

Installation

The package can be installed from hex by adding ecto_watch to your list of dependencies in mix.exs:

def deps do
  [
    {:ecto_watch, "~> 0.11.1"}
  ]
end

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/ecto_watch.

  • Having a single topic (e.g. users) means that all messages are sent to all subscribers, which can be inefficient.
  • Having a topic per record (e.g. users:1, users:2, etc.) means that a subscriber needs to subscribe to every record, which can be inefficient.
  • There may be inconsistancy in pluralization of topics (e.g. a user vs. packages topics) which can be confusing and lead to bugs.
  • Having a message that is just {:updated, id} doesn't make it clear which schema was updated, using {schema, id} doesn't make it clear which operation happened.

Footnotes

  1. more info about PubSub message standards:

Articles
to learn more about the elixir concepts.

Resources
which are currently available to browse on.

mail [email protected] to add your project or resources here 🔥.

FAQ's
to know more about the topic.

mail [email protected] to add your project or resources here 🔥.

Queries
or most google FAQ's about Elixir.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory