Ecto.Observable - bring observability to your repos!

Hi folks,

Just released Ecto.Observable - an easy way to bring “observable” functionality to your Ecto.Repo’s. Hook into the life cycle of your records to expand features without muddying your contexts.

Check it out at: Ecto.Observable

Work in progress! PR’s and suggestions welcome!

Cheers

3 Likes

For note, unless explicitly stated by a parent project it’s usually best not to choose a submodule inside a parent project as your name (like Ecto.Observable) and instead just concat them (EctoObservable) so you don’t have to worry about namespace collisions later. :slight_smile:

Interesting pattern though, does it work transactionally?

7 Likes

Nice library! I’d use something like this whenever Postgrex.Notifications wasn’t available.

Some ideas based on a quick skim of the code, apologies in advance if I’ve misunderstood something:

  1. It appears that observers are notified before an enclosing transaction is comitted:

https://github.com/nsweeting/ecto_observable/blob/master/lib/ecto/observable/observable.ex#L311-L316

This can cause problems if the observers have side effects like sending emails, publishing to message queues, etc.

  1. The observers all run sequentially in the same process as the caller. This may not be ideal if they perform long operations. Something like Task.Supervisor.async_stream_no_link could be used to execute them concurrently in separate processes.

  2. It looks like observers need to be stateless, this can make it tricky when you want the similar functionality in two observers with slightly different configuration. Something like the Plug.init callback that allows some context to be passed in to the observer would be useful. Another pattern I like would be to make Observer a protocol. You can provide an implementation for atom for stateless module based observers.

5 Likes

Thanks for the feedback!

@OvermindDL1 - I released a new version that removes the Ecto namespace from the library. All the additional repo actions are wrapped in a transaction.

@mbuhot - thanks for the comments.

I have worked with Postgrex.Notifications a little bit as well. Although I like the idea of handling the data at the time of action a little bit more. Its already in struct form, and is easy to pattern match against without having to do additional encoding.

Correct me if I’m wrong, but notifications would return it in json form no? Also - if you have multiple boxes running - I assume you have to ensure the listener is running as a global process if you dont want every box to take action on a notification. I’m wondering if this would ever become a bottleneck? One could implement a pool under this if needed obviously.

I debated whether to implement each observer callback as an async process. In the end, I decided to let the user decide what they want - with the callback implementing any async functionality. Although perhaps something like insert_and_async_notify/2 would be nice.

Will look into #3!

Cheers
Nick

1 Like