From ffa124d0d5475abca5c3872f1eec841d11177320 Mon Sep 17 00:00:00 2001 From: Pranav Date: Tue, 9 Sep 2025 21:38:37 -0700 Subject: [PATCH] fix: Use .find_by instead .where().first (#12402) While investigating a customer-reported issue, I found that some emails were appearing late in Chatwoot. The root cause was query timeouts. It only happened for emails with an in_reply_to header. In these cases, Chatwoot first checks if a message exists with message_id = in_reply_to. If not, it falls back to checking conversations where additional_attributes->>'in_reply_to' = ?. We were using: ```rb @inbox.conversations.where("additional_attributes->>'in_reply_to' = ?", in_reply_to).first ``` This looked harmless, but .first caused timeouts. Without .first, the query ran fine. The issue was the generated SQL: ```sql SELECT * FROM conversations WHERE inbox_id = $1 AND (additional_attributes->>'in_reply_to' = '') ORDER BY id ASC LIMIT $2; ``` The ORDER BY id forced a full scan, even with <10k records. The fix was to replace .first with .find_by: ```rb @inbox.conversations.find_by("additional_attributes->>'in_reply_to' = ?", in_reply_to) ``` This generates: ```sql SELECT * FROM conversations WHERE inbox_id = $1 AND (additional_attributes->>'in_reply_to' = '') LIMIT $2; ``` This avoids the scan and runs quickly without needing an index. By the way, Cursor and Claude failed [here](https://github.com/chatwoot/chatwoot/pull/12401), it just kept on adding the index without figuring out the root cause. Co-authored-by: Muhsin Keloth --- app/mailboxes/imap/imap_mailbox.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/mailboxes/imap/imap_mailbox.rb b/app/mailboxes/imap/imap_mailbox.rb index bd591b05a..5fea49722 100644 --- a/app/mailboxes/imap/imap_mailbox.rb +++ b/app/mailboxes/imap/imap_mailbox.rb @@ -42,7 +42,7 @@ class Imap::ImapMailbox message = @inbox.messages.find_by(source_id: in_reply_to) if message.nil? - @inbox.conversations.where("additional_attributes->>'in_reply_to' = ?", in_reply_to).first + @inbox.conversations.find_by("additional_attributes->>'in_reply_to' = ?", in_reply_to) else @inbox.conversations.find(message.conversation_id) end