Back to Feed
article 3m read

Migrate script that opened by dropping every table

Turning chores into templates forced a real upgrade path that asks the database what it has before adding anything. Reading the diff, I found a second route to the wipe still open and a backfill that can get stranded.

Article DepthPractice

Flow

The question each step asks before it acts

  1. 1Main script

    Is the most basic table missing? Only then install from zero.

  2. 2Chore columns

    Is the guard column missing? Then add the new columns.

  3. 3Name copy

    Should run every time, since it only fills blank names.

  4. 4Break-schedule helper

    Is one table missing? Then it installs from zero, which can wipe real data.

Every time, the scheduling app's migrate script ran the installer first. The installer starts by dropping every table. On an empty database, no harm. On the real one, with the stores' staff, shifts and chores, it wipes the app before the import starts.

Where the pressure came from

The agent was turning chores into templates. A chore used to be a line of text with maybe a person and a date. Now it has a name, a priority, a repeat rule, a time window, limits on how often it lands, and side tables for who may do it. Adding that to the installer is easy. Moving a live database to the new shape, without a wipe, is the real job.

Asking the database first

The upgrade doesn't remember past runs. It asks the database what's there: this table, this column, this index, this key. Each step runs only if its piece is missing. One new column stands guard for the big block of new columns. On an old database the upgrade adds what's missing. On a current one it should do nothing.

Old chores get a name copied from their old text. And the installer now runs only when the most basic table is missing, which means the database is truly empty.

The second door, still open

A helper that adds default break schedules also ran the installer. Now it only does that when one table is missing. But one missing table isn't an empty database. A database full of real data that lacks that table would still get wiped.

The guard covers too much

The name copy sits behind the same guard as the new columns. If the columns get added and the copy fails, the next run skips both, and those chores stay nameless. The copy only touches blank names, so it can run every time.

The copy belongs outside the guard, where it can run every time. That change hasn't been made yet, so the risk is still live.

One more thing: every old chore becomes an active, daily task the moment the upgrade runs, and nothing says so.

A typo standing guard

The old script loaded that helper by the wrong file name. Unless I'm misreading it, it would have crashed near the top, before the wipe. The new change fixed the name. So the new check is now the only thing in the way at the entry point.

Untested, and only a backup to go back to

There are no tests yet, and going back means restoring a backup. The chore table is now written down in two places, with nothing that compares them, so the day they drift apart I won't hear about it.

Keep reading

Pick up a connected idea or branch into a nearby one.

5 paths forward
Related idea

The draft button checked for duplicates, then left a gap wide enough for a second one

The button that saves a delivery as a draft in the stores' inventory system checked first and wrote its record only after a slow outside call, so a second click could slip through. Now it claims the delivery in the database first, lets a partial unique index refuse the second claim, fixes a payload hash that couldn't see nested fields, and adds a narrow admin cancel for claims that get stuck.

via #databases · #reliability