The calendar caches a resource's availability for feed_max_age seconds, default 30, configurable as "Availability feed cache lifetime". The seat map does not. It is the one availability surface still computed on every request, and it is the one under the most simultaneous load: a booking-opening rush puts every visitor's seat map straight onto the database.

A seat map view costs roughly half a dozen reads (which seats are taken, pool counts, pool definitions, tariffs by grade, what each allotment has taken) plus the entity loads for the slot, resource, venue and the visitor's basket. Only the venue geometry and the pinning list are cached today; everything else is rebuilt per visitor, and every visitor of one session gets the same answer.

Freshness is not what is being traded

A seat map is stale the moment it renders: somebody books a second later and the page in front of the booker is wrong, and stays wrong for as long as they look at it. Against seconds to minutes of that, a few seconds of server-side staleness adds almost nothing to what a booker actually experiences.

Correctness never came from the map. It comes from the slot lock, and the map already assumes it can be wrong: a click on a taken seat is refused and the seat repaints. So the trade is not correctness against speed. It is a slightly higher rate of refused clicks against a large drop in database load, and the page's own age already dominates that rate. The lifetime should be chosen from how often a booker may click a dead seat, not from any worry about overbooking.

Resync the whole map on a refused click

Today a refused click corrects one seat. Refetching the whole state instead makes staleness self-healing: the first booker to hit a dead seat resyncs their entire map, so a longer lifetime stops accumulating error. This is what makes the cache safe to lengthen, and it should be configurable alongside the lifetime.

What has to come out of the shared entry

mine, the visitor's own basket, is per session and has to be merged in per request rather than cached.

heldColor is per permission. It is filled only for an operator who may choose an allotment, so a shared entry has to vary on user.permissions or a booker is told which audience the front row is being held for. It is safe today only because the map's state carries max-age = 0.

The feed does not invalidate when what it counts changes

Separate from the above, and true today. AvailabilityController tags its cached feed with yoyaku_slot_list, yoyaku_slot_tariff_list and yoyaku_resource_tariff_list, plus the resource and the settings. Bookings deliberately ride the lifetime instead of a tag, which is what lets it absorb a rush. But configuration an operator changes should take effect at once, and three groups are missing:

  • allotments: yoyaku_allotment_list, yoyaku_resource_allotment_list, yoyaku_slot_allotment_list
  • pinnings: yoyaku_pinning_list, yoyaku_pinned_place_list
  • placement generally: nothing at all, so closing an area or repointing a configuration leaves the feed stale too, which predates allotments entirely

The shape is the problem rather than the list: the feed hardcodes what availability depended on when it was written, and every feature that has since joined the arithmetic is invisible to it. A small core service returning the cache tags availability depends on, with a tagged-service collector so yoyaku_placement contributes its own, would let the next module declare its tags instead of the feed guessing. A cached seat map needs the same tags, so this is worth settling first.

Issue fork yoyaku-3615588

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mably created an issue. See original summary.

  • mably committed 0026dfa3 on 1.x
    task: #3615588 Cache the seat map's availability like the calendar's,...
mably’s picture

Status: Active » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.