DDL transaction for db:migrate:redo task

db:migrate:redo Rake task is very convenient. I use it often to change the code in up migration method. As usual, during development I make mistakes there. And if db:migrate:redo fails on up, the second run of db:migrate:redo rolls back the previous migration. What actually concludes that db:migrate:redo is not idempotent.

Currently there is the only way to deal with that is to remember that if up fails, use db:migrate instead of db:migrate:redo. IMO that’s not very convenient.

I propose to wrap db:migrate:redo task into DDL transaction to make db:migrate:redo idempotent and eliminate that inconvenience.

1 Like

We currently never wrap multiple migrations in a single transaction, and even though this is a bit different (because it’s two runs of the same migration), my first thought is that I feel like the same rule should probably apply.

(There’s also the fact that the migration might disable the DDL transaction, but that’s probably less important – we could still do it for the common case.)

Another option (with other trade-offs) would be to have db:migrate:redo refuse to run when 1) there are unapplied migrations, and 2) it has not been given a specific transaction number to confirm what it should be re-doing. That’d at least give you an error instead of undoing a different migration. I wonder whether redo-with-pending-migrations is an important use case?

Thinking it through, it might actually be worth trying a PR to see what the implementation would look like to do the transaction-wrapping you propose. If the code isn’t too bad, I could probably get behind an argument that we’re only running a single migration, and it just happens to be doing twice as much work as it normally would.


Thanks @matthewd I’ve implemented it. If you have time please review this PR. I’m no sure if I did it right, so any feedback is welcome. Thank you!