Skip to content

Keep operator complexity in sync with clamped ticket complexity - #4

Merged
daniser merged 2 commits into
masterfrom
fix/operator-complexity-follows-ticket-clamp
Nov 10, 2026
Merged

daniser merged 2 commits into
masterfrom
fix/operator-complexity-follows-ticket-clamp

Conversation

@EgorGruzdev

Copy link
Copy Markdown
Contributor

Follow-up to #3, based on its branch.

Problem

#3 stops the decrement from failing, but the counter still drifts below the real sum, and one source of that drift is onTicketMetricsAdjusted:

  • TicketProjector clamps the ticket's complexity at zero: max(0, complexity + adjustment).
  • OperatorProjector adds the raw adjustment to total_complexity.

Ticket at 0, adjustment -5: the ticket stays at 0 but the operator loses 5. A later +5 adds 5 to both. The operator is now 5 below the sum of its tickets, and closing the ticket subtracts 5 from it again. Before #3 this ended in SQLSTATE[22003]: 1690 BIGINT UNSIGNED value is out of range, and it still happens in production.

The handler also did read-modify-write in PHP (update(['total_complexity' => ...])), which overwrote concurrent increments.

Change

onTicketMetricsAdjusted adds the ticket's actual change to the operator, max(0, old + adjustment) - old, atomically: increment() for a positive delta, decrementToZero() from #3 for a negative one. $ticket->complexity is still the old value here because OperatorProjector (weight 0) runs before TicketProjector (weight 5).

Verified

In the host app against local MySQL, with projector calls in Projectionist order, inside rolled-back transactions:

  • ticket 0, adjustments -5 then +5, then close: operator 7 → 7 → 12 → 7. Before this change it was 2 after the first adjustment.
  • ticket 4, adjustment -9: operator 10 → 6. Before this change it was 1.
  • close, unbind and rebind with drifted counters (Clamp operator counter decrements at zero #3): counters floor at 0, no exception.

EgorGruzdev and others added 2 commits November 2, 2026 21:39
bound_tickets and total_complexity are unsigned; a drifted counter made
decrement() throw SQLSTATE 22003 on ticket close/unbind, which aborted
projection and left the closed ticket bound to the operator.
Base automatically changed from fix/clamp-operator-counter-decrements to master November 10, 2026 10:34
@daniser
daniser merged commit c5a6bd3 into master Nov 10, 2026
0 of 2 checks passed
@daniser
daniser deleted the fix/operator-complexity-follows-ticket-clamp branch November 10, 2026 10:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants