Maestro and Ecto 3

Introduction

Like many blogs in our profession, I begin by focusing on a particular set of technologies Elixir, Ecto 3, and maestro such that this article is doomed to inevitable obsolescence. Nevertheless, it is a great place for me to start as it is focused on things that I am actively developing on now and interested in working on/with for the foreseeable future. Enough with the character development… On to the software development!

Maestro

Maestro began out of necessity for a project at Pylon. The key differentiator between maestro and other open source alternatives for event sourcing in Elixir is the focus on causal consistency for events. In simpler terms, if you have maestro running on two nodes that can’t see each other (but they can still see the database), they will make progress without violating each other’s view of the model. How? We require through database transactions that the events are sequentially ordered. Additionally, a local copy of the model will always make a best effort to see all previous events before accepting new commands.

We’ll dig into some of the more interesting implementation details at a later date, but consistency is a cognitive burden that is nice to set aside without having to complicate the code you write on a day to day basis.

Moving to Ecto 3

Ecto 3 has been out for a while now, so I really have been delinquent in my responsibilities in maintaining maestro by waiting as long as I have to upgrade it; however, our application was not going to move Ecto 3 immediately, and I use integration with an existing application as a way of fully validating certain design decisions like dialyzer type specs.

The first thing I encountered when migrating to v3 was the split between ecto and ecto_sql. This was written about at length on the elixir blog here, but I never really looked at where the lines were drawn until now. Because of existing dependencies in maestro, I found that I had to explicitly specify both to get my mix deps.get to play nice, but it wasn’t required to explicitly specify ecto afterwards. I assume this was user error, as ecto_sql very clearly depends on ecto

Other than that, the changes were mostly painless.

  • migrations_path moved from Mix.Ecto to Ecto.Migrator
  • :adapter is specified on the Repo and not in config
  • Multi.run/3 warns against having a run function with arity 1
  • Ecto.Changeset.unique_constraint’s :message must be a string

The only one that really surprised me was the last one, but the error message for FunctionClauseError made it relatively straightforward to track down and fix. It can be seen here in maestro and the relevant line of code in ecto can be seen here. I liked having a message that was not just specific but also an atom as it felt more deliberate as a library developer.

Conclusion

I really psyched myself out on how much work the migration was going to be. It is always refreshing to be able to update dependencies and have things play nicely without much fuss. While your migration to Ecto 3 might be more eventful, I found it to be a highlight of my OSS programming experience in recent months.

In upcoming posts, I’m going to work on a sample application that uses maestro. It’s been a while since I’ve had to greenfield a project with it, so now is a great time to sit down and dig back in. The documentation will be tested. I’ll also use the opportunity to talk about the design decisions which might be more interesting than the sample app itself.