chore: Add assigned option to conversation finder API (#2630)

- Adds the ability to filter all the conversations which are assigned
- Add rack timeout gem
- Remove size attribute from Sidekiq config
This commit is contained in:
Sojan Jose 2021-07-14 22:51:27 +05:30 committed by GitHub
parent 3d18ec9e40
commit d7982a6ffd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 153 additions and 70 deletions

View file

@ -53,6 +53,7 @@ gem 'activerecord-import'
gem 'dotenv-rails' gem 'dotenv-rails'
gem 'foreman' gem 'foreman'
gem 'puma' gem 'puma'
gem 'rack-timeout'
gem 'webpacker', '~> 5.x' gem 'webpacker', '~> 5.x'
# metrics on heroku # metrics on heroku
gem 'barnes' gem 'barnes'

View file

@ -384,6 +384,7 @@ GEM
rack rack
rack-test (1.1.0) rack-test (1.1.0)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rack-timeout (0.6.0)
rails (6.0.3.7) rails (6.0.3.7)
actioncable (= 6.0.3.7) actioncable (= 6.0.3.7)
actionmailbox (= 6.0.3.7) actionmailbox (= 6.0.3.7)
@ -666,6 +667,7 @@ DEPENDENCIES
puma puma
pundit pundit
rack-cors rack-cors
rack-timeout
rails rails
redis redis
redis-namespace redis-namespace

View file

@ -73,6 +73,8 @@ class ConversationFinder
@conversations = @conversations.assigned_to(current_user) @conversations = @conversations.assigned_to(current_user)
when 'unassigned' when 'unassigned'
@conversations = @conversations.unassigned @conversations = @conversations.unassigned
when 'assigned'
@conversations = @conversations.where.not(assignee_id: nil)
end end
@conversations @conversations
end end

View file

@ -3,11 +3,11 @@ require Rails.root.join('lib/redis/config')
schedule_file = 'config/schedule.yml' schedule_file = 'config/schedule.yml'
Sidekiq.configure_client do |config| Sidekiq.configure_client do |config|
config.redis = Redis::Config.sidekiq config.redis = Redis::Config.app
end end
Sidekiq.configure_server do |config| Sidekiq.configure_server do |config|
config.redis = Redis::Config.sidekiq config.redis = Redis::Config.app
end end
# https://github.com/ondrejbartas/sidekiq-cron # https://github.com/ondrejbartas/sidekiq-cron

View file

@ -12,3 +12,4 @@ internal_check_new_versions_job:
cron: "*/5 * * * *" cron: "*/5 * * * *"
class: "TriggerScheduledItemsJob" class: "TriggerScheduledItemsJob"
queue: scheduled_jobs queue: scheduled_jobs

View file

@ -1,16 +1,10 @@
module Redis::Config module Redis::Config
DEFAULT_SENTINEL_PORT ||= '26379'.freeze DEFAULT_SENTINEL_PORT ||= '26379'.freeze
SIDEKIQ_SIZE ||= 25
class << self class << self
def app def app
config config
end end
def sidekiq
app.merge(size: SIDEKIQ_SIZE)
end
def config def config
@config ||= sentinel? ? sentinel_config : base_config @config ||= sentinel? ? sentinel_config : base_config
end end

View file

@ -6,7 +6,7 @@ describe ::ConversationFinder do
let!(:account) { create(:account) } let!(:account) { create(:account) }
let!(:user_1) { create(:user, account: account) } let!(:user_1) { create(:user, account: account) }
let!(:user_2) { create(:user, account: account) } let!(:user_2) { create(:user, account: account) }
let!(:inbox) { create(:inbox, account: account) } let!(:inbox) { create(:inbox, account: account, enable_auto_assignment: false) }
before do before do
create(:inbox_member, user: user_1, inbox: inbox) create(:inbox_member, user: user_1, inbox: inbox)
@ -15,6 +15,8 @@ describe ::ConversationFinder do
create(:conversation, account: account, inbox: inbox, assignee: user_1) create(:conversation, account: account, inbox: inbox, assignee: user_1)
create(:conversation, account: account, inbox: inbox, assignee: user_1, status: 'resolved') create(:conversation, account: account, inbox: inbox, assignee: user_1, status: 'resolved')
create(:conversation, account: account, inbox: inbox, assignee: user_2) create(:conversation, account: account, inbox: inbox, assignee: user_2)
# unassigned conversation
create(:conversation, account: account, inbox: inbox)
Current.account = account Current.account = account
end end
@ -28,10 +30,28 @@ describe ::ConversationFinder do
end end
end end
context 'with assignee' do context 'with assignee_type all' do
let(:params) { { assignee_type: 'all' } } let(:params) { { assignee_type: 'all' } }
it 'filter conversations by assignee' do it 'filter conversations by assignee type all' do
result = conversation_finder.perform
expect(result[:conversations].count).to be 4
end
end
context 'with assignee_type unassigned' do
let(:params) { { assignee_type: 'unassigned' } }
it 'filter conversations by assignee type unassigned' do
result = conversation_finder.perform
expect(result[:conversations].count).to be 1
end
end
context 'with assignee_type assigned' do
let(:params) { { assignee_type: 'assigned' } }
it 'filter conversations by assignee type assigned' do
result = conversation_finder.perform result = conversation_finder.perform
expect(result[:conversations].count).to be 3 expect(result[:conversations].count).to be 3
end end

View file

@ -20,14 +20,6 @@ describe ::Redis::Config do
expect(app_config[:url]).to eq(redis_url) expect(app_config[:url]).to eq(redis_url)
expect(app_config[:password]).to eq(redis_pasword) expect(app_config[:password]).to eq(redis_pasword)
end end
it 'checks for sidekiq redis config' do
sidekiq_config = described_class.sidekiq
expect(sidekiq_config.keys).to match_array([:url, :password, :size, :network_timeout, :reconnect_attempts])
expect(sidekiq_config[:url]).to eq redis_url
expect(sidekiq_config[:password]).to eq redis_pasword
expect(sidekiq_config[:size]).to eq described_class::SIDEKIQ_SIZE
end
end end
context 'when redis sentinel is used' do context 'when redis sentinel is used' do
@ -58,10 +50,5 @@ describe ::Redis::Config do
expect(described_class.app[:url]).to eq("redis://#{redis_master_name}") expect(described_class.app[:url]).to eq("redis://#{redis_master_name}")
expect(described_class.app[:sentinels]).to match_array(expected_sentinels) expect(described_class.app[:sentinels]).to match_array(expected_sentinels)
end end
it 'checks for sidekiq redis config' do
expect(described_class.sidekiq.keys).to match_array([:url, :password, :sentinels, :size, :network_timeout, :reconnect_attempts])
expect(described_class.sidekiq[:size]).to eq described_class::SIDEKIQ_SIZE
end
end end
end end

View file

@ -0,0 +1,41 @@
get:
tags:
- Conversation
operationId: conversationList
description: List all the conversations with pagination
summary: Conversations List
parameters:
- $ref: '#/parameters/account_id'
- name: assignee_type
in: query
type: string
enum: ['me', 'unassigned', 'all', 'assigned']
required: true
- name: status
in: query
type: string
enum: ['open', 'resolved', 'bot']
required: true
- name: page
in: query
type: integer
required: true
- name: inbox_id
in: query
type: integer
- name: labels
in: query
type: array
items:
type: string
responses:
200:
description: Success
schema:
$ref: '#/definitions/conversation_list'
400:
description: Bad Request Error
schema:
$ref: '#/definitions/bad_request_error'
description: Access denied

View file

@ -1,45 +1,3 @@
get:
tags:
- Conversation
operationId: conversationList
description: List all the conversations with pagination
summary: Conversations List
parameters:
- $ref: '#/parameters/account_id'
- name: assignee_type
in: query
type: string
enum: ['me', 'unassigned', 'all']
required: true
- name: status
in: query
type: string
enum: ['open', 'resolved', 'bot']
required: true
- name: page
in: query
type: integer
required: true
- name: inbox_id
in: query
type: integer
- name: labels
in: query
type: array
items:
type: string
responses:
200:
description: Success
schema:
$ref: '#/definitions/conversation_list'
400:
description: Bad Request Error
schema:
$ref: '#/definitions/bad_request_error'
description: Access denied
get: get:
tags: tags:
- Conversation - Conversation
@ -53,7 +11,7 @@ get:
- name: assignee_type - name: assignee_type
in: query in: query
type: string type: string
enum: ['me', 'unassigned', 'all'] enum: ['me', 'unassigned', 'all', 'assigned']
- name: status - name: status
in: query in: query
type: string type: string

View file

@ -156,7 +156,11 @@ public/api/v1/inboxes/{inbox_identifier}/contacts/{contact_identifier}/conversat
/api/v1/accounts/{account_id}/conversations: /api/v1/accounts/{account_id}/conversations:
parameters: parameters:
- $ref: '#/parameters/account_id' - $ref: '#/parameters/account_id'
$ref: ./conversation/index_or_create.yml $ref: ./conversation/index.yml
/api/v1/accounts/{account_id}/conversations/:
parameters:
- $ref: '#/parameters/account_id'
$ref: ./conversation/create.yml
/api/v1/accounts/{account_id}/conversations/{converstion_id}: /api/v1/accounts/{account_id}/conversations/{converstion_id}:
parameters: parameters:
- $ref: '#/parameters/account_id' - $ref: '#/parameters/account_id'

View file

@ -1406,7 +1406,8 @@
"enum": [ "enum": [
"me", "me",
"unassigned", "unassigned",
"all" "all",
"assigned"
] ]
}, },
{ {
@ -1542,6 +1543,78 @@
} }
} }
}, },
"/api/v1/accounts/{account_id}/conversations/": {
"get": {
"tags": [
"Conversation"
],
"operationId": "conversationList",
"description": "List all the conversations with pagination",
"summary": "Conversations List",
"parameters": [
{
"$ref": "#/parameters/account_id"
},
{
"name": "assignee_type",
"in": "query",
"type": "string",
"enum": [
"me",
"unassigned",
"all",
"assigned"
],
"required": true
},
{
"name": "status",
"in": "query",
"type": "string",
"enum": [
"open",
"resolved",
"bot"
],
"required": true
},
{
"name": "page",
"in": "query",
"type": "integer",
"required": true
},
{
"name": "inbox_id",
"in": "query",
"type": "integer"
},
{
"name": "labels",
"in": "query",
"type": "array",
"items": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/conversation_list"
}
},
"400": {
"description": "Bad Request Error",
"schema": {
"$ref": "#/definitions/bad_request_error"
}
},
"description": "Access denied"
}
}
},
"/api/v1/accounts/{account_id}/conversations/{converstion_id}": { "/api/v1/accounts/{account_id}/conversations/{converstion_id}": {
"parameters": [ "parameters": [
{ {