I’m really interested in Elixir, and as a starter project wanted to put together a tool similar to theStrong Migrations gem for Rails. Briefly, this would examine your (pending) Ecto migrations and inform you if they could impact a running service (e.g. removing an existing column, the table lock required by non-concurrent index creation).
I’ve spent a bit of time reading up on the basics of Elixir, and had a quick look at Ecto, and I’m a bit stumped on how this could be accomplished.
The original strong_migrations gem simply overrides methods within ActiveRecord to decorate them with safety checks. I’ve never much liked this approach, but don’t see much of a choice when you’re trying to add behavior on top of a closed system.
It looks like the cleanest way this could be done would be to create another module that could be
used after (or maybe instead of)
Ecto.Migration. This would keep that same overriding behavior and warn users when it encounters a problematic migration. I see a lot of potential for problems here, mostly due to the same issues you always encounter when trying to override existing code. Also, before I got too deep to really understand what I was reading, it looked like I might run into problems with methods not being tagged as overrideable anyways.
Another idea I had was to set up a “proxy runner”. This would stand in between the migration and
Ecto.Migration.Runner, acting as a kind of gatekeeper. My hope there would be to pick up on
Ecto.Migration's internal calls to
Runner methods and touch up the behavior of those. I’m relatively sure this won’t work since
Ecto.Migration is already working against an alias of the
Runner module, but I’m still a little hazy on when that would be resolved. (i.e. if I aliased something else to
Runner within the migration, would
Ecto.Migration methods pick up on that alias or keep using their own)
The last idea I had was to put together a custom adapter and catch things there. This has the problem of sometimes needing to “be” the real adapter (i.e. when querying out current migration state) but mostly not. So, again, it looks like trying to override an existing thing would be happening. On the plus side, that would make it easier to sort out any database-specific limitations.
Can anyone shine some light on these ideas? I know I’m probably diving pretty deep for a first experiment, but this struck my interest and seems like it could produce something valuable for the community.