Back to Feed
article 3m read

A failed load would get saved right over the staff file by the break scheduler

Rereading a day of my own commits, I found that a failed read in my break scheduler shows an empty list, and the next edit writes that emptiness over the real file. Old files and error replies take similar wrong turns.

Article DepthPractice

Flow

A save path that can't wipe the file

  1. 1Check the status

    Look at what the server said before reading the body.

  2. 2Check the shape

    Make sure it's a list or a map of days before using it.

  3. 3Allow saving

    Only after a good load, or a clear answer that no file exists.

  4. 4Server checks too

    Refuse a body with the wrong shape.

  5. 5Temp file, then swap

    Nobody ever reads a half-written file.

  6. 6Keep the last copy

    One bad save can be rolled back.

If my break scheduler can't read the staff file, it shows me an empty list. Then it lets me save that over the real one.

I never saw it happen. I found it when I read back a day of my own commits.

That day I moved the staff list into a JSON file on the server, with a screen to add, rename and remove people. I split the schedule up by date, so each day has its own plan. I added a lunch length for each person. Then I patched loading for old files. Together those steps left the code making calls it was never built to make.

When a failed read looks empty

Both loaders fetch the file and read the JSON. If anything goes wrong, they start from empty. The page looks normal.

The page also saves, and every save sends the whole list. The server writes whatever it gets over the file. So if the read fails, I see no staff. I add one person. The save sends a list of one. Now the file has one person. Nobody is told.

The page falls back to an empty list when the load fails, adds the person, and saves that list over the whole file.

The new person also gets the first id number, and old schedules may use that number for someone else.

When an error looks like data

The loaders never check whether the server said no. A rejected request still sends back a small JSON note. The loader reads that note as if it were the data. On the staff screen, that just breaks things. On the schedule, I'm guessing it gets saved into the file. I didn't check the schedule side that day.

When old files get today's date

Old files held one plan with no date. The patch files that plan under whatever day the screen is showing. The next save makes that stick. The printout reads old files its own way, so it can disagree with the screen.

The date key is in UTC, so late at night it can be tomorrow. The print page uses the server's clock. Pick one time zone and pass the day along.

A rename only fixes the current day's rows. Other days keep the old name. And names go into the page as raw HTML, which is unsafe now that a file holds them.

What I'd build next time

Make the loader come back with one of three answers:

  • Loaded: the server said yes, and the data has the right shape. Saving is on.
  • Absent: the file doesn't exist yet. Start empty.
  • Failed: anything else. Show an error and turn saving off.

On the server, check the shape before writing. Write to a temp file and swap it in. Keep the last copy. Turn old files into the new shape once, on purpose, with a date I pick.

Keep reading

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

5 paths forward