From 91da28a32994aac8d63706d7bf22162881a7dfb0 Mon Sep 17 00:00:00 2001 From: Muhsin <12408980+muhsin-k@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:45:39 +0400 Subject: [PATCH] fix(voice): scope inbound Call lookup and handle create races - Scope the existing-call pre-check to the inbound account + inbox. - Rescue ActiveRecord::RecordNotUnique so a concurrent Twilio retry doesn't 500 when two webhooks race to create the same Call. --- enterprise/app/services/voice/inbound_call_builder.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/enterprise/app/services/voice/inbound_call_builder.rb b/enterprise/app/services/voice/inbound_call_builder.rb index fa5afc691..1cc04fe81 100644 --- a/enterprise/app/services/voice/inbound_call_builder.rb +++ b/enterprise/app/services/voice/inbound_call_builder.rb @@ -13,7 +13,7 @@ class Voice::InboundCallBuilder end def perform! - existing = Call.find_by(provider: :twilio, provider_call_id: call_sid) + existing = find_existing_call return existing if existing ActiveRecord::Base.transaction do @@ -25,10 +25,18 @@ class Voice::InboundCallBuilder call.update!(message_id: message.id) call end + rescue ActiveRecord::RecordNotUnique + # A concurrent Twilio retry won the create race; return what now exists. + find_existing_call || raise end private + def find_existing_call + Call.where(account_id: account.id, inbox_id: inbox.id) + .find_by(provider: :twilio, provider_call_id: call_sid) + end + def ensure_contact! account.contacts.find_or_create_by!(phone_number: from_number) do |record| record.name = from_number if record.name.blank?