perf: skip conversation loading in /meta endpoint (#13564)
# Pull Request Template
## Summary
- Adds `perform_meta_only` method to `ConversationFinder` that runs
setup and counts without loading the paginated conversation list
- Updates `/api/v1/conversations/meta` to use `perform_meta_only`
instead of `perform`
## Problem
The `/meta` endpoint calls `ConversationFinder#perform` which:
1. Runs all filters and setup (`set_up`)
2. Computes 3 COUNT queries (`set_count_for_all_conversations`)
3. Filters by assignee type
4. **Builds the full paginated conversation list** with
`.includes(:taggings, :inbox, {assignee: {avatar_attachment: [:blob]}},
{contact: {avatar_attachment: [:blob]}}, :team, :contact_inbox)` +
sorting + pagination
The controller then **discards the conversations** and only uses the
counts:
```ruby
def meta
result = conversation_finder.perform
@conversations_count = result[:count] # conversations thrown away
end
```
## Type of change
- [x] Performance fix
## How Has This Been Tested?
- [ ] Verify /meta returns correct mine/unassigned/assigned/all counts
- [ ] Verify counts update when switching inbox, team, or status filters
- [ ] Verify conversation list still loads correctly (uses perform, not
affected)
- [ ] Monitor response time reduction for /meta in NewRelic after deploy
## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] 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
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Pranav <pranav@chatwoot.com>
This commit is contained in:
@@ -15,7 +15,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
||||
end
|
||||
|
||||
def meta
|
||||
result = conversation_finder.perform
|
||||
result = conversation_finder.perform_meta_only
|
||||
@conversations_count = result[:count]
|
||||
end
|
||||
|
||||
|
||||
@@ -55,6 +55,22 @@ class ConversationFinder
|
||||
}
|
||||
end
|
||||
|
||||
def perform_meta_only
|
||||
set_up
|
||||
|
||||
mine_count, unassigned_count, all_count, = set_count_for_all_conversations
|
||||
assigned_count = all_count - unassigned_count
|
||||
|
||||
{
|
||||
count: {
|
||||
mine_count: mine_count,
|
||||
assigned_count: assigned_count,
|
||||
unassigned_count: unassigned_count,
|
||||
all_count: all_count
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_up
|
||||
|
||||
@@ -190,6 +190,32 @@ describe ConversationFinder do
|
||||
end
|
||||
end
|
||||
|
||||
context 'with perform_meta_only' do
|
||||
let(:params) { { assignee_type: 'assigned' } }
|
||||
|
||||
it 'returns only count without conversations' do
|
||||
result = conversation_finder.perform_meta_only
|
||||
expect(result).to have_key(:count)
|
||||
expect(result).not_to have_key(:conversations)
|
||||
end
|
||||
|
||||
it 'returns the correct counts' do
|
||||
result = conversation_finder.perform_meta_only
|
||||
expect(result[:count]).to eq({
|
||||
mine_count: 2,
|
||||
assigned_count: 3,
|
||||
unassigned_count: 1,
|
||||
all_count: 4
|
||||
})
|
||||
end
|
||||
|
||||
it 'returns same counts as perform' do
|
||||
meta_result = conversation_finder.perform_meta_only
|
||||
full_result = conversation_finder.perform
|
||||
expect(meta_result[:count]).to eq(full_result[:count])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with unattended' do
|
||||
let(:params) { { status: 'open', assignee_type: 'me', conversation_type: 'unattended' } }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user