Back to Feed
article 3m read

Scheduler moved to a real database and can't save its own staff list

Four versions of the shift scheduler's move from flat files to a database got a read-through. Every one keeps a delete-everything save that runs into foreign keys or orphans rows and reads and writes staff under different names, so a plain save can wipe the admin flag. The MySQL ones also ship a setup that only works once.

Article DepthPractice

Flow

Turning a wipe-and-refill save into a safe one

  1. 1Round-trip test

    Load, send back untouched, load again, compare.

  2. 2Change the parent save

    Update people by ID and remove only the ones who are gone.

  3. 3One name converter

    Use the same function for reading and for saving.

The new staff save in the shift scheduler deletes every person, then adds back whoever the browser sent. But each shift points at a staff member, and the database won't delete a person while a shift still points at them.

So once there's one shift, saving staff fails and nothing changes. The browser likely never knows, because it doesn't check the answer.

Every version wipes the table first

The app used to keep staff, shifts and chores in plain files. That day there were four versions of moving it into a database. They all save the same way: delete everything, insert what came in, all inside one transaction. That copies the old rule, where the browser sent the whole file and the server stored it. The transaction keeps a crash from leaving half a list. It doesn't make the save fit a database where rows point at each other.

Where the links bite

On the MySQL versions, the staff save fails once any shift or assigned chore exists. The version on an embedded database file may be worse. I don't see it turning on the links at all, so the delete would work and some shifts could drop out of view.

The read and the write use different names

The staff read sends back names with underscores. The staff write looks for camelCase names and uses defaults when it can't find them. Likely the browser just sends back what it loaded.

Loading and then saving the same list loses the flag, because the names don't match on the way back.

In my app that wipes the admin flag and resets lunch lengths. Every write now needs an admin. On a fresh install with no shifts, the first staff save demotes everyone, and after that every write is refused. Once shifts exist, the link rule blocks the save, which is the only thing keeping the flags safe. That's luck, not design.

What I'd do instead: one function that converts names, used for both reading and writing, and a save that updates people by ID and only removes the ones who are gone.

The admin check trusts the URL

The admin check uses a user number from the page address. With no number, it assumes the first user, and the import makes that person an admin if their record has no admin setting. So anyone who opens the page can end up as the admin.

Setup that only works once

The setup runs the same staff save first. It works on an empty database and fails on a second run, so it can't fix a half-done install. The first version also writes its config file before testing the connection. If the test fails, the file stays, and the next run quits because the file exists. A later version tests first.

Lost settings and one bad shift

Preferred position and standing tasks never make it into the database. One shift with no person ID sinks the whole schedule save. Editing one chore rewrites them all. Two browsers still overwrite each other. The old file code had its own junk: a lock queue that gave up and wrote anyway, and a check that never rejected anything.

Before anyone clicks save

I haven't run any of this. It's from reading the code, and none of the versions has a test. Until the staff save keeps the admin flag, I wouldn't put any of the four in front of real staff.

Keep reading

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

5 paths forward