fix: Use contact_id instead of sender_id for Instagram message locks

Previously, the lock key for Instagram used sender_id,
which for echo messages (outgoing) would be the account's own ID. This
caused all outgoing messages to compete for the same lock, creating a
bottleneck during bulk messaging.

The fix introduces contact_instagram_id method that correctly identifies
the contact's ID regardless of message direction:
- For echo messages (outgoing): uses recipient.id (the contact)
- For incoming messages: uses sender.id (the contact)

This ensures each conversation has a unique lock, allowing parallel
processing of webhooks while maintaining race condition protection
within individual conversations.

Fixes lock acquisition errors in Sidekiq when processing bulk Instagram
messages.
This commit is contained in:
Vishnu Narayanan
2025-11-11 20:42:34 +05:30
parent e81152608d
commit 6cef7ce861
+14 -1
View File
@@ -8,7 +8,7 @@ class Webhooks::InstagramEventsJob < MutexApplicationJob
def perform(entries)
@entries = entries
key = format(::Redis::Alfred::IG_MESSAGE_MUTEX, sender_id: sender_id, ig_account_id: ig_account_id)
key = format(::Redis::Alfred::IG_MESSAGE_MUTEX, sender_id: contact_instagram_id, ig_account_id: ig_account_id)
with_lock(key) do
process_entries(entries)
end
@@ -77,6 +77,19 @@ class Webhooks::InstagramEventsJob < MutexApplicationJob
@entries&.first&.dig(:id)
end
def contact_instagram_id
messaging = @entries&.dig(0, :messaging, 0)
return nil unless messaging
# For echo messages (outgoing from our account), use recipient's ID (the contact)
# For incoming messages (from contact), use sender's ID (the contact)
if messaging.dig(:message, :is_echo)
messaging.dig(:recipient, :id)
else
messaging.dig(:sender, :id)
end
end
def sender_id
@entries&.dig(0, :messaging, 0, :sender, :id)
end