Qqwy

Qqwy

TypeCheck Core Team

Ecto-less migrations?

Hello everyone!

As you might or might not know, Planga is a thing we’re building: It’s a seamless chat integration service.

Currently, I am busy working out the details of making Planga as scalable as it can be.
As has been discussed before in Mnesia vs Cassandra (vs CouchDB vs ...) - your thoughts?, we’re currently in the process of moving away from Mnesia to some other type of (decentralized!) datastore.

However, this brings two problems with it:

  1. It’s nearly impossible to use Ecto. On one hand, there do exist a couple of Ecto wrappers for these datastores, but they are experimental at best. (And we already are experiencing this with the ecto_mnesia wrapper… migrations are a pain and setting up the database in the testing environment is a mystery I haven’t solved yet). On the other: Distributed datastores are quite far away from what Ecto (2.0) is commonly used for: Queries (some are supported, many are not because of the data format of these decentralized datastores), Migrations (if you have your database in multiple nodes, it is near-impossible to migrate ‘tables’ at the same time).

We will still be using Ecto for its validations, but we probably will have to manage our database insertions/lookups/updates manually.

  1. Migrations. Planga is supposed to scale. We try to plan ahead as good as we can, but I am certain that there will be more fields added to our datastructures in the future.

However, this poses a problem: Once you have millions of messages stored in a (distributed) datastore, data migrations are near-impossible to run.
Instead, I currently think it makes more sense to define a way to version the datastructures, and allow older versions of the data structures to be transformed to the new expected format once it has been fetched from the datastore.
In this way, except in some advanced features where we need to add new indexes to the datastore or something, iterating over all datastructure in the datastore becomes unneccesary.

But now my question: What would be the best way to set up something like this? It feels like something that belongs in the Schema file at least. I am currently thinking about adding multiple heads for a function, one for every ‘version’ of the datastructure, which are then called incrementally (the version being an integer) until the ‘current’ version is reached.

Has someone experience with these kinds of things? I think it is sort of similar to the code_change function that is part of the GenServer behaviour, but then it is part of the data-layer rather than the code-layer.

Help is greatly appreciated!

Most Liked Responses

jeremyjh

jeremyjh

I think your idea is a good one. It reminds me a little bit of the Haskell library SafeCopy. They use TH (macros) to generate typeclass implementations and I suppose you could possibly do something similar with protocols, but I think a new function head that just knows how to migrate to the next version would make more sense. I’d probably make separate named, versioned structs for each version so it is clear what kind of structures each migration clause is operating on. This may seem like a lot of overhead but you could tuck older versions away in a separate file.

Where Next?

Popular in Questions Top

marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: <h1>Create Post</h1> <%= ...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> somethi...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New

Other popular topics Top

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
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement