Skip to content

Clean-cut refactoring: waiting list move-up / interval notification (freetobookagain)Β #1506

Description

@georgmaisser

Important

πŸ‘‰ Start here: What does this feature actually do?

INTERVALLBENACHRICHTIGUNG_FREIE_PLAETZE_FUNKTIONSWEISE_2026-08-04.md (internal, German) β€” the human-readable description of the current behaviour (triggers, minute-by-minute flow, confirmation modes 0/1/2, stop conditions, support checklist). Please read this first, in full β€” all other documents assume this understanding.

What this is about

The feature complex "interval notification for free places" (bookingoption_freetobookagain + send_mail_interval + confirm_bookinganswer + the ad-hoc task chains) has accumulated a massive bugfix history over two years (among others Wunderbyte-GmbH/Wunderbyte-GmbH#1019, #1087, #1146, #1165, #1296, #1462, #1648, #1962) and most recently caused a production incident reported in July 2026 (unconfirm loop re-offering the same user, no batch move-up when several places become free, complete process stall). The causes are structural, not one-off slips. Decision: complete refactoring with a clean cut β€” no parallel operation, no permanent feature flags.

The full analysis and target architecture live in secret_docs (internal):

Core of the target architecture: a persistent offer table (booking_waitlist_offers) plus a single capacity-driven reconciler replaces the two ad-hoc task chains; rules remain a pure messaging layer; all triggers (cancellation, maxanswers, campaigns, unconfirm, late joiners, offer expiry, heartbeat) only call reconcile().

⚠️ Mandatory order of work

The order of work is a fixed part of this ticket and non-negotiable:

  1. Review the requirements list (R-numbers in the requirements document). It was distilled from the current plugin state and the entire fix history and is the acceptance yardstick for the refactoring. Clarify any doubts/objections with the maintainer BEFORE starting β€” after that the list is frozen.
  2. Close the test gaps β€” BEFORE any refactoring line is written:
    • Category A (A1–A11): characterisation tests for all [KEEP] behaviour against the current code (must be green on base). Biggest single gap: the existing unconfirm test only asserts that an immediate task is created β€” not for whom; that is exactly how the reported production bug went undetected.
    • Category C (C1–C5): PHPUnit tests for the migration of running interval chains. Fixtures = chains genuinely created through today's engine (pending mail/confirm/repeat tasks with usersalreadytreated), then the upgrade step, then assertions: no duplicate mails, open confirmations stay valid, orphaned tasks cleaned up, idempotency. These tests must be fully implemented and reviewed before the actual refactoring work starts.
    • Category B (B1–B7): target-behaviour tests for [CHANGE]/[NEW] (batch move-up, declined skip, offer expiry, heartbeat) β€” as a separate, initially skipped suite.
  3. Only then: the refactoring per blueprint phases 2–3 (data model + reconciler, then the switchover as a clean cut in a single release, removal of the legacy chain code).
  4. Follow-up work (phase 4): docs, release notes for the intentional behaviour changes (K1/T8/K4/K7), verification of the four reported incident scenarios against the new version.

Before phase 1, the open policy decisions in blueprint Β§5 must be settled with the maintainer (scope of "declined", offer-expiry semantics, hard stop on "always" misconfiguration, heartbeat frequency).

Ground rules: all mod_booking work on branch base; coding style phpcs 0 errors / 0 warnings; PHPUnit patterns see coverage document Β§4.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions