Seat a party under the hold's own locks, so a rush is served rather than refused

A hold read the whole slot to answer questions about a handful of seats, and it chose the seats it was about to take above its own locks. Every booker who reached at once therefore read the same free house and was offered the same seats: the first was served, and the rest were refused for seats that were free when they asked. On 8000 seats sold at one price, 160 bookers at once sold 1460 and refused 84 per cent of what they asked for.

What it does now

A request reaches the engine as a request, rather than as lines composed above it. Where its units go is decided inside the locks, against what is committed, so being offered a seat and taking it are one moment. The locks are taken before anything is written, so a hold no longer holds a site-wide row for the length of its own queue.

A hold reads the seats it names, by key, and the area it is being seated into. A slot's seats are rows of their own carrying whether each has gone, so what is left in an area is a seek rather than a subtraction over a house, and it shrinks as the sale goes on instead of growing. The seating asks for areas a page at a time in house order and turns another page whenever the party would not be sitting together, keeping what it has read, so stopping early can only skip reads it did not need.

What may be locked and what may be read are one question asked once, so a party can only be seated inside what was locked for it. A party too big for any one area waits on every area it could be seated in; a booker adding to a basket waits on the area their party already sits in; the slot's own row is waited on only where the hall offers no areas at all. A party given an area that turns out not to seat it is not refused there: the guess is dropped and the hall asked again with the house open to it.

How many areas a party that chose none may be offered is a field rule on the resource, party_area. One keeps every party in the best area and queues them all for it, a number spreads them over that many, and zero spreads over every area with room for them. Four is shipped, and a hall of one area has nothing to decide.

A seat cannot be sold twice, and the database is what says so. Claiming moves only rows that are still free, and a hold that moves fewer rows than it claimed is taken back whole rather than committed on top of somebody else's seats. A booking saved outside the hold path is refused rather than written onto a seat another booking holds. Under both, a booking carries the seat it consumes with a unique key over it, so the rule holds even where those rows have drifted from what the bookings say: a slot drawn before this module was installed carries none at all, and every guard above reads them. The column is empty whenever a line consumes nothing or names no seat, and repeated empties do not collide, so released lines, pooled units and halls without seats are outside the rule entirely. A hold that meets the key is refused the way a full house refuses.

The booking page's area cards cost a count, not a walk. Each card carries how many seats its part of the house has left, and answering it read every free seat of the slot into PHP to count them there. It is a count taken by the database now, narrowed to the parts of the house that hold the grades a tariff prices. Both readers share one query, so what is counted still passes every rule that decides what may be offered: the areas a configuration opens, the seats an allotment holds, the grades the tariff prices. Which blocks a hall's grades sit in, and how many seats it physically holds, are kept between requests and carry the venue's tag: they are facts about the building, so they change when an operator edits it and never because anybody booked.

The shipped availability lifetime goes from thirty seconds to five. At a hundred and fifty seats a second a thirty second old picture is thousands of seats out of date, and a booker shown one picks seats that have gone.

Measured

A house of 8000 seats in 16 areas, 160 bookers at once, driven from empty until it sells out.

before after
a party that names no seat 1460 of 8000 sold, 84 per cent refused 8000 of 8000, on 8000 distinct places
refused while the house still had room 10 to 20 per cent none, and the sale ran a fifth faster
a booker clicking seats 160.2 and 166.6 seats a second 164.1, run as A, B, A on one machine
what a hold costs the same statements, with one read fewer

How many areas a party may be given buys latency rather than throughput: one area waits about 3.5 s, two about 2.1, four about 1.6, and the house sells no slower at any of them. Four is shipped for that reason.

On a hall ten times the size, 80000 places in 80 areas, claiming through the endpoint the booking page uses:

80000 places, 40 bookers at once seats a second a claim
as #3617848 merged 16.5 3731 ms
this branch about 50 235 ms

The booking page itself is 21 ms there and 5 ms on the hall of eight thousand, where a hundred and sixty bookers take seats at 177 a second with a claim's median at 349 ms. The key costs nothing measurable: 54.3 seats a second with it and 53.9 without, run as A, B, A.

The rig that produced these numbers ships with them: tests/load with its runbook, and a test module that claims through an endpoint of its own so a run measures the engine rather than the booking form.

Not in this

  • #3617101: keeping on each anchor how much of its scope is consumed. Batched so a party moves each row once it still costs a statement per hold, and nothing reads the number yet, so it stays with its reader.
  • #3617848: claiming through an endpoint of its own, so the booking page stays cacheable.
  • #3617880: composing a rearrangement under the locks.
  • #3617891: seating a party that cannot sit together in as few groups as possible.
  • #3617528: repairing a slot whose seats have gone missing.

Since the rebase

A claim reads the block it is about, not the house. The number every area card carries was answered by listing every free seat of the slot and counting them, and again by a second reader when the hold chose where to seat the party. It is one reading now, counted by the database, narrowed to the parts of the house a tariff is sold in, and kept for as long as an availability figure may be believed; the seats this request took come off it before it answers, so a booker sees their own claim at once. How many seats a hall holds, and where its grades sit, are facts about the building and are kept between requests.

An area taken by the number is bounded on its seats. What the hall holds there less what the slot still offers of it, rather than a grouped read over every consuming booking inside the lock. Only a pooled area counts the bookings, having no seats to count instead. That is the mode a house of five thousand seats and upwards is most likely to be run in, and it cost twice what selling seat by seat cost.

Measured, 80000 places in 80 areas, forty bookers at once: a claim's median 3731 ms when #3617848 merged and 90 ms now, about 60 seats a second against 16.5, and 51411 rows read where a claim read 213671. With every area assigned: 59.8 seats a second against 59.9 for the same hall sold seat by seat, where 1.x managed 3.7.

The rig gained what none of this could be judged by. The engine stamps the moment its anchor rows are granted and the load test module writes down the span to the commit, so locked.php reports what a hold HOLDS rather than what a transaction lasts, which counts the queue as well. Its reset also empties the baskets, which are the largest thing in the database within a day of running.

Edited by Frank Mably

Merge request reports

Loading
Loading