- Shipped
- August 10, 2026 at 5:57 PM UTC
- Author
- Kamo
- Commit
- 4007c5b
Routing a new ticket ran inside the creation transaction, so anything it hit rolled the ticket back with it and the member asking for help got "Failed to create ticket" with nothing saved anywhere. Two things hit it, both latent until chat requests started reaching this code — round-robin had effectively never executed in production, so it had never met YugabyteDB: - getEligibleAgents swept every applied-rights row in the org and filtered in Java: thousands of rows joined to `members`, run late in a write transaction. YugabyteDB can only transparently restart a read that is the first statement in its transaction, so this raised "Restart read required" (SQLState 40001). It now uses the indexed right-filtered lookup that SupportQueueService and SupportPendingCountService already use. - A freshly created round-robin tracker was immediately locked PESSIMISTIC_WRITE. The entity is unversioned, so that is SELECT ... FOR UPDATE against a row this same uncommitted transaction had only just inserted; it returns nothing and Hibernate raises StaleObjectStateException. Nothing can contend for a row that does not exist yet — the unique constraint on TOPIC_ID is what settles a creation race. Existing trackers are still locked. Structurally, routing now happens in its own transaction after the ticket has committed (SupportController calls routeNewTicket, falling back to announceNewTicket if that fails). Assignment is a convenience; the ticket is the thing that must survive. This also gives assignment's large read a transaction where it is the first statement.