fix(voice): close lock-window gaps in accept, throttle, and call_attributes_changed?
This commit is contained in:
@@ -113,14 +113,28 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
|
||||
end
|
||||
|
||||
# 138006 = no call permission yet; send opt-in template (throttled) and surface state to FE.
|
||||
# Lock the conversation so concurrent initiate requests can't both pass the throttle gate
|
||||
# and double-send the opt-in template.
|
||||
def render_permission_request
|
||||
return render json: { status: 'permission_pending' } if permission_request_throttled?
|
||||
status = nil
|
||||
@conversation.with_lock do
|
||||
if permission_request_throttled?
|
||||
status = 'permission_pending'
|
||||
next
|
||||
end
|
||||
|
||||
sent = provider_service.send_call_permission_request(@conversation.contact.phone_number.delete('+'))
|
||||
return render_could_not_create_error(I18n.t('errors.whatsapp.calls.permission_request_failed')) unless sent
|
||||
sent = provider_service.send_call_permission_request(@conversation.contact.phone_number.delete('+'))
|
||||
if sent
|
||||
record_permission_request_wamid(sent)
|
||||
status = 'permission_requested'
|
||||
else
|
||||
status = 'failed'
|
||||
end
|
||||
end
|
||||
|
||||
record_permission_request_wamid(sent)
|
||||
render json: { status: 'permission_requested' }
|
||||
return render_could_not_create_error(I18n.t('errors.whatsapp.calls.permission_request_failed')) if status == 'failed'
|
||||
|
||||
render json: { status: status }
|
||||
end
|
||||
|
||||
def permission_request_throttled?
|
||||
|
||||
@@ -40,6 +40,9 @@ module Enterprise::Conversation
|
||||
def call_attributes_changed?
|
||||
return false if previous_changes['additional_attributes'].blank?
|
||||
|
||||
previous_changes['additional_attributes'][1].keys.intersect?(%w[call_status call_direction])
|
||||
# Compare before/after values for call keys — checking key presence alone
|
||||
# rebroadcasts on any unrelated additional_attributes write once the keys exist.
|
||||
before, after = previous_changes['additional_attributes']
|
||||
%w[call_status call_direction].any? { |key| (before || {})[key] != (after || {})[key] }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,10 +4,14 @@ class Whatsapp::CallService
|
||||
def accept
|
||||
raise Voice::CallErrors::CallFailed, 'sdp_answer is required' if sdp_answer.blank?
|
||||
|
||||
call.with_lock { transition_to_in_progress! }
|
||||
update_message_status('in_progress')
|
||||
update_conversation_call_status(call.display_status)
|
||||
broadcast(:accepted, accepted_by_agent_id: agent.id)
|
||||
# All side effects under the lock so a concurrent terminate cannot finalize
|
||||
# the call between status update and the message/conversation/broadcast writes.
|
||||
call.with_lock do
|
||||
transition_to_in_progress!
|
||||
update_message_status('in_progress')
|
||||
update_conversation_call_status(call.display_status)
|
||||
broadcast(:accepted, accepted_by_agent_id: agent.id)
|
||||
end
|
||||
call
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user