Zurga

Zurga

EctoSync - sync changes from a cache

Subscribe to events emitted by EctoWatch, and cache the changed row. Use the sync/3 function to update an in-memory row or list of rows using the cached version of the changed row.

This library aims to solve the problem of tracking changes of database rows across processes without causing database stampedes. All possible update paths for each pair of schemas that are connected is determined to avoid brute-forcing through all preloaded associations.

Say you have a Post schema that has many Tags associated through a PostsTags schema and you want to automatically update the Tags for the loaded Posts in a LiveView:

appplication.ex


children: [...,
  {EctoSync, repo: TestRepo, watchers: EctoSync.watchers(Post, assocs: [:tags])},
  ...
  ]

PostLive.ex

alias MyApp.Posts.{Post, PostsTags}

def mount(params, session, socket) do
  posts = list_posts(preload: [:tags])
  if connected?(socket) do
    EctoSync.subscribe(Post, assocs: [:tags])
  end

  {:ok, assign(socket, posts: posts)}
end

def handle_info({{PostsTags, _event}, _} = sync_args, socket) do
  {:noreply, update(socket, :posts, &EctoSync.sync(&1, sync_args))}
end

If you want to add preloads to the changed row, this is possible by adding a Map like this:

EctoSync.sync(post, sync_args, preloads: %{Tag => [:posts]})

It is still in an early stage of development and has not been tested in production. I would love to get feedback on this package.

Package on hex.pm here:

Documentation:

Repo:

Most Liked

Zurga

Zurga

Version 0.2.0 has been released. It brings some changes and supports new features.

Features:

  • The algorithm updating the in-memory rows has been made more efficient by using a graph of the Schemas in the watchers and determining possible paths at application boot time.
  • :through is fully supported.
  • :where is supported on has_one and has_many.

Changes:

  • The messages sent by EctoSync are now a tuple of the following format: {EctoSync, {schema, event, identifiers, ref}}. This allows them to be distinguished from other events that are in the form of tuples.
  • The trigger names in Postgres are shortened automatically to make sure that the character limit is not surpassed.

Future work:

  • A library to provide utility functions to work with Phoenix LiveView
  • Batching system for events.

Where Next?

Popular in Announcing Top

RobinBoers
Renders Jinja templates, either from disk or defined at runtime, with support for all native Jinja features (including extends). It does...
New
halostatue
Enviable is a small collection of functions to make working with environment variables easier when configuring Elixir projects. It is des...
New
kzemek
I’ve recently released v0.2.0 of my Python interop library, Snex. This version rolls up all work-in-progress improvements that have been...
New
jechol
I’m excited to share FeistelCipher and AshFeistelCipher, PostgreSQL-based libraries that provide encrypted integer IDs using the Feistel ...
New
New
Antrater
Hi there! At Moon Design System, we have been working hard for the past six months on the next generation of our LiveView component libra...
New
webofbits
Helix is a visual workflow designer for AI agents and multi-agent systems, built with Phoenix and React Flow. It provides an intuitive dr...
#ai
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New
waseigo
DiskSpace Hi everyone, I needed this for a project I’ve been working on, and couldn’t find a simple solution that would work. The solutio...
New
martosaur
Hello, I’m excited to introduce InstructorLite – a fork of the Instructor package. Instructor brought the very idea of structured LLM p...
New

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New

We're in Beta

About us Mission Statement