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:
parent
3d18ec9e40
commit
d7982a6ffd
12 changed files with 153 additions and 70 deletions
1
Gemfile
1
Gemfile
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -12,3 +12,4 @@ internal_check_new_versions_job:
|
||||||
cron: "*/5 * * * *"
|
cron: "*/5 * * * *"
|
||||||
class: "TriggerScheduledItemsJob"
|
class: "TriggerScheduledItemsJob"
|
||||||
queue: scheduled_jobs
|
queue: scheduled_jobs
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
41
swagger/paths/conversation/create.yml
Normal file
41
swagger/paths/conversation/create.yml
Normal 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
|
|
@ -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
|
|
@ -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'
|
||||||
|
|
|
@ -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": [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue