Repair a slot whose seats have gone missing, when it is saved
A slot carries one row per seat of its hall, and every read on the booking path asks those rows. A seat with no row is a seat nobody can buy: it is not offered, and it is not reported as taken either, so the slot looks healthy while quietly refusing that seat to everybody.
Saving a slot now reconciles it. The seats the hall has and the rows the slot offers are compared, what is missing is added and what belongs to a seat the hall no longer has is settled. Set operations rather than a walk, so it is a fixed handful of statements whatever the size of the house. A row it adds is free only where no booking holds that seat: the bookings are read in the same statement, so a repair cannot open a seat somebody is sitting in, and a house that is legitimately sold out is left exactly as it is.
The flag is now a named state (SeatState: free, taken, gone), because a seat that leaves the hall while a booking holds it needs a third answer. Its row is kept and marked gone: dropping it would leave the booking naming nothing, and freeing it would offer a seat that is not in the building. Every read asks whether a seat is free, so a gone seat is out of sale, out of the block counts and out of the seating without a query changing. Releasing that booking drops the row, and deleting a seat a consuming booking holds is refused, in the entity rather than only in the form, while the booking is still in reach to be moved.
Three doors, in the manner of the venue's numbering tab:
- a Seats tab on the slot, saying how many seats have no row, how many rows are for seats the hall no longer has and how many rows disagree with what is booked. Reading it changes nothing.
- a Repair the seats button beside the findings, through the Batch API: one slot of a stadium is eighty thousand rows.
drush yoyaku:slot-seats [slot] [--fix], over one slot or every slot played in a hall, exiting non-zero on a finding so a deployment can gate on it. This is the door an upgrade needs.
Measured on the load rig's hall of 80000 places: a slot save costs about 0.35 s and the check about 0.1 s, against 26 ms and 9 ms on a hall of 8000. A slot of 80000 places that had lost every row was written back in under a second, with 74213 free and 5787 taken, no state disagreeing with the bookings and no row in the wrong block.
Tests: a kernel class covering the reconcile, the three states, the release, the refusal and a stepped repair, plus a scenario on the admin UI test for the tab and its button. Docs and the French translation are in the same commit.