iachat/enterprise/app/models
Tanmay Deep Sharma 0592cccca9
fix: prevent lost custom_attributes updates from concurrent jsonb writes (#14040)
## Linear ticket
https://linear.app/chatwoot/issue/CW-6834/billing-upgrade-didnt-work

## Description
A `customer.subscription.updated` Stripe webhook for account 76162
returned 200 OK but did not persist the new `subscribed_quantity`. Root
cause: a race condition between the webhook handler and
`increment_response_usage` (Captain usage counter), both doing
read-modify-write on the `custom_attributes` JSONB column. The webhook
wrote `quantity: 6`, then a concurrent `save` from
`increment_response_usage` overwrote the entire hash with stale data —
restoring `quantity: 5`.

Fix: use atomic `jsonb_set` so usage counter updates only touch the
single key they care about, instead of rewriting the whole
`custom_attributes` hash. `increment_custom_attribute` also performs the
increment in SQL, making concurrent increments correct as well.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- New regression spec in `handle_stripe_event_service_spec.rb` that
simulates concurrent webhook + `increment_response_usage` and asserts
both `subscribed_quantity` and `captain_responses_usage` survive
- Existing account, billing, captain, and topup specs all pass locally

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
2026-04-13 19:03:37 +07:00
..
captain feat: captain custom tools v1 (#13890) 2026-04-02 12:40:11 +05:30
channel feat(enterprise): add voice conference API (#13064) 2025-12-15 15:11:59 -08:00
concerns feat: captain custom tools v1 (#13890) 2026-04-02 12:40:11 +05:30
enterprise fix: prevent lost custom_attributes updates from concurrent jsonb writes (#14040) 2026-04-13 19:03:37 +07:00
account_saml_settings.rb feat: update users on SAML setup and destroy [CW-2958][CW-5612] (#12346) 2025-09-15 21:20:22 +05:30
agent_capacity_policy.rb feat: Add agent capacity controllers (#12200) 2025-08-26 19:12:58 -07:00
applied_sla.rb chore: Add dependant destroy_async for sla events (#12774) 2025-10-31 09:19:56 +05:30
article_embedding.rb feat: legacy features to ruby llm (#12994) 2025-12-11 14:17:28 +05:30
captain_inbox.rb feat(ee): Add Captain features (#10665) 2025-01-14 16:15:47 -08:00
company.rb feat: Add automatic favicon fetching for companies (#13013) 2026-03-05 18:51:28 -08:00
copilot_message.rb feat: Update UI for Copilot (#11561) 2025-06-02 22:02:03 -05:00
copilot_thread.rb feat: Add support for more tool, standardize copilot chat service (#11560) 2025-05-23 01:07:07 -07:00
custom_role.rb feat: Add APIs to manage custom roles in Chatwoot (#9995) 2024-08-23 17:18:28 +05:30
inbox_capacity_limit.rb feat: allow zero conversation limit capacity policy (#13964) 2026-04-06 11:39:14 +05:30
sla_event.rb feat: Conversation API to return applied_sla and sla_events (#9174) 2024-04-01 23:30:07 +05:30
sla_policy.rb fix: Prevent SLA deletion timeouts by moving to async job (#12944) 2025-12-10 12:28:47 +05:30