perf: merge 3 conversation COUNT queries in /meta into single query (#13536)
# Pull Request Template ## Description - Merges 3 separate COUNT queries in `ConversationFinder#set_count_for_all_conversations` into a single query using PostgreSQL `COUNT(*) FILTER (WHERE ...)` - Every call to `/meta` and conversation index fires 3 COUNT queries against the conversations table — one for "mine", one for "unassigned", one for "all". These share the same base query and scan the same rows, but execute as 3 independent round-trips. from pg_stats | Query | Calls | Total DB Time | Avg Latency | |-------|-------|--------------|-------------| | COUNT unassigned | 4.1M | 141,081 sec | 34ms | | COUNT all | 4.1M | 132,302 sec | 32ms | | COUNT mine | 3.7M | 37,637 sec | 10ms | | **Total** | **~12M** | **311,020 sec** | | `/meta` alone runs at 2.3K RPM (NewRelic), triggered on every WebSocket event (conversation created/updated/status changed/assignee changed). Fixes https://linear.app/chatwoot/issue/INF-43/make-single-query-to-count-the-assigned-unassigned-and-all-instead-of ## Type of change - [x] Performance fix ## How Has This Been Tested? - [x] Verify conversation list shows correct mine/unassigned/assigned/all counts - [x] Verify /meta endpoint returns correct counts - [x] Verify counts update correctly when assigning/unassigning conversations - [x] Verify counts with team filter applied - [x] Monitor DB query count reduction in NewRelic after deploy ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] 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 --------- Co-authored-by: Sony Mathew <ynos1234@gmail.com>
This commit is contained in:
co-authored by
Sony Mathew
parent
6d26e7930a
commit
a901c87ab4
@@ -40,7 +40,7 @@ class ConversationFinder
|
||||
def perform
|
||||
set_up
|
||||
|
||||
mine_count, unassigned_count, all_count, = set_count_for_all_conversations
|
||||
mine_count, unassigned_count, all_count = set_count_for_all_conversations
|
||||
assigned_count = all_count - unassigned_count
|
||||
|
||||
filter_by_assignee_type
|
||||
@@ -184,6 +184,17 @@ class ConversationFinder
|
||||
end
|
||||
|
||||
def set_count_for_all_conversations
|
||||
return legacy_count_for_all_conversations if @conversations.limit_value || @conversations.offset_value || @conversations.eager_loading?
|
||||
|
||||
counts = @conversations.unscope(:order).pick(
|
||||
Arel.sql("COUNT(*) FILTER (WHERE assignee_id = #{current_user.id})"),
|
||||
Arel.sql('COUNT(*) FILTER (WHERE assignee_id IS NULL)'),
|
||||
Arel.sql('COUNT(*)')
|
||||
)
|
||||
counts || [0, 0, 0]
|
||||
end
|
||||
|
||||
def legacy_count_for_all_conversations
|
||||
[
|
||||
@conversations.assigned_to(current_user).count,
|
||||
@conversations.unassigned.count,
|
||||
|
||||
Reference in New Issue
Block a user