Commit 999eec1
committed
feat(promo-codes): finish TOCTOU fix — remove post-facto check, add tests
Step 3 of 3. The per-member QuantityPerAccount check now lives solely
in PreProcessReservationTask::reserveMemberQuotas (added in ad113d5,
leak-guarded in 77c3059), where it runs atomically under the
PESSIMISTIC_WRITE row lock on the parent promo code, BEFORE
ReserveTicketsTask and ReserveOrderTask commit any tickets.
Changes:
- Remove the belt-and-suspenders post-facto check from
ApplyPromoCodeTask::run. A comment now points at the pre-reservation
location and links to smarcet's TOCTOU reproduction for context.
The old check counted committed tickets and could not distinguish
concurrent orders' rows — see the race narrative in PR #525.
- Delete tests/Unit/Services/ApplyPromoCodeTaskConcurrencyTest.php.
smarcet added this in the cherry-picked 2e0ef84 to prove the TOCTOU
bug against the old check surface (static
getTicketCountByMemberAndPromoCode). That surface is no longer in
the write path, so the test targets removed code. The narrative is
preserved — and extended — in the new file below.
- Delete tests/Unit/Services/ApplyPromoCodeTaskQuantityPerAccountTest.php.
All six cases validated the exact post-facto check that was just
removed.
- Add tests/Unit/Services/PreProcessReservationTaskConcurrencyTest.php
with 6 cases exercising the new surface via reflection on
reserveMemberQuotas:
1. First reserve succeeds when no prior row exists (repo `add`
called with qty_used=1).
2. Second reserve rejects when the prior row's QtyUsed already
sits at the limit (the serialized-second-request flow that
replaces smarcet's TOCTOU reproduction).
3. Within-limit reserve increments the existing row.
4. Limit = 0 bypasses reservation entirely (unlimited per account).
5. Non-IDomainAuthorizedPromoCode codes are skipped (no
reservation repo calls).
6. undo() decrements each reserved counter exactly once and is
idempotent via the $undone guard.
Verified:
docker exec summit-api composer dump-autoload # pick up new entity
docker exec summit-api vendor/bin/phpunit --filter "PreProcessReservationTask|SagaCompensationTest|ApplyPromoCodeTask"
→ 13/13 pass (3 PHPUnit deprecations match repo baseline).
Outstanding from smarcet's PR #525 review: #7 (discoverPromoCodes N+1)
is the only remaining item.1 parent 2e0ef84 commit 999eec1
4 files changed
Lines changed: 337 additions & 677 deletions
File tree
- app/Services/Model/Imp
- tests/Unit/Services
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
815 | 815 | | |
816 | 816 | | |
817 | 817 | | |
818 | | - | |
819 | | - | |
820 | | - | |
821 | | - | |
822 | | - | |
823 | | - | |
824 | | - | |
825 | | - | |
826 | | - | |
827 | | - | |
828 | | - | |
829 | | - | |
830 | | - | |
831 | | - | |
832 | | - | |
833 | | - | |
834 | | - | |
835 | | - | |
836 | | - | |
837 | | - | |
838 | | - | |
839 | | - | |
840 | | - | |
841 | | - | |
842 | | - | |
843 | | - | |
844 | | - | |
845 | | - | |
846 | | - | |
847 | | - | |
848 | | - | |
849 | | - | |
850 | | - | |
851 | | - | |
852 | | - | |
853 | | - | |
854 | | - | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
855 | 825 | | |
856 | 826 | | |
857 | 827 | | |
| |||
Lines changed: 0 additions & 328 deletions
This file was deleted.
0 commit comments