Repository navigation
Conversation
0bf2152 to
cdf3811
Compare
|
Given something like a rolling deploy, does this do anything to prevent writes to the table while we're undergoing this process? |
| fn {reason, blocks} -> " - #{reason} (#{blocked_when(blocks)})" end | ||
| ) | ||
|
|
||
| warn(""" |
There was a problem hiding this comment.
wonder if we should error instead, and then have them pass like an explicit --no-rebuild if they want to skip it, and we just ignore it then and don't even try to generate migrations that we know won't work.
There was a problem hiding this comment.
I would say eventually yes, but initially i didn't want to force it on users since it's quite a big change, and users that do want that behaviour can easily flip the config at the repo level, to not have to think about it
It also depends on whether you want to support multiple ecto_sql versions. Since older ones lack the required callbacks they cannot have this default rebuild behaviour.
There was a problem hiding this comment.
Right but at the moment don't the migratiosn that emit alter statements just straight up fail?
|
Had some comments, in general this looks good but we can't merge it until we could reasonably deploy it unless you can do something to make it support both old and new versions of ecto_sql when it releases. |
cdf3811 to
8fe9f0d
Compare
I actually didn't know it was possible to have a rolling deploy with sqlite. On a single host, it seems possible to have overlapping containers sharing one db. The current PR on its own doesn't do anything to prevent writes during the migration, the guarantee comes from sqlite itself and its single writer model. So if the migration transaction acquires the write lock, concurrent writes either wait or fail. EDIT: added a guard to ensure the migration runs inside a transaction f652cd3 |
Yes of course, I am fine with that! I thought it could be useful to already open the PR even if it's not merged anytime soon I didn't think about supporting multiple ecto_sql versions, I explored this in 104a56a and 39b2fa0 does that look reasonable? Currently the CI would only run against a single ecto_sql version, the rebuild table part is not covered unless we change the workflow. So up to you, maybe waiting for the ecto_sql release is simpler |
55aa54b to
f652cd3
Compare
Closes #239.
Adds opt-in table rebuilds for changes sqlite can't make in place (--rebuild-tables, or rebuild_tables: true in the repo config).
The generator then writes a rebuild_table migration (create, copy, drop, rename, as in the sqlite docs) instead of a failing statement.
By default, generated migrations are unchanged and only a hint says what could not be done.
It needs before_transaction/1 and after_transaction/1 from elixir-ecto/ecto_sql#758 (merged, not released yet).
I suggest reading by commit, but it's still quite large. The last 3 could be separate if you prefer.
Manual testing
The steps below were drafted with AI help. I ran them myself against a fresh Ash project.
Setup
(The
ecto_sqlandectolines are only needed until elixir-ecto/ecto_sql#758 is released; Mix only honorsoverridein your ownmix.exs, not the one in this branch. Amin_sqlite_versionwarning is printed when compiling; it comes from upstream.)1. Make an attribute optional. In
lib/support_desk/support/ticket.ex, replace thesubjectattribute with:Prints (in yellow) what SQLite can't do in place, then a
modify :subject, :text, null: truemigration that would fail.The migration is a
rebuild_table :ticketswith a comment saying why,subjecthas noNOT NULLany more, and both tickets are still there. (It also listsmodify :status ... default: "open": a plaindefault:becomes the column default.)2. Add a required attribute without a default. In the same file, add above the
statusattribute:mix ash.codegen add_priority --rebuild-tables && mix ash.migrateThe migration has a
REVIEW:note, andmix ash.migratestops withNOT NULL constraint failed: tickets_rebuild.priority, changing nothing. Give the existing rows a value, as the note says:Both rows have
priority = 1.3. Change a type. Change
priorityto a string:typeofis nowtext. The migration comment warns that a value that doesn't convert would be copied as it is.4. Drop a foreign key. First give a ticket a representative, while the foreign key still exists:
sqlite3 support_desk_dev.db "insert into representatives (id, name) values ('r', 'Ada'); update tickets set representative_id = 'r' where id = 'a'"In
lib/support_desk/support/ticket.ex, delete this block:and add this attribute above
status:The migration comment says
dropping the foreign key tickets_representative_id_fkey. The query showsa|r,b|and0: the rows keep their value and the table has no foreign key any more. Without--rebuild-tables, the generated migration raises "SQLite does not support dropping foreign key constraints".5. Roll back.
mix ash_sqlite.rollback -n 1 sqlite3 support_desk_dev.db "select id, representative_id from tickets; select \"table\" from pragma_foreign_key_list('tickets')"The foreign key to
representativesis back (representatives) and the rows are still there (a|r,b|).Contributor checklist
Leave anything that you believe does not apply unchecked.