diff --git a/app/agent.go b/app/agent.go index 384a965..8e90bed 100644 --- a/app/agent.go +++ b/app/agent.go @@ -123,11 +123,19 @@ func (app *App) SetAgentBreakOut(agent agent_manager.AgentObject) *model.AppErro func (app *App) hangupNoAnswerChannels(chs []*model.CallNoAnswer) { for _, ch := range chs { - if err := app.callManager.HangupById(ch.Id, ch.AppId); err != nil { - app.Log.Error(err.Error(), - wlog.Err(err), - wlog.String("call_id", ch.Id), - ) + if ch.Id != nil && ch.AppId != nil { + if err := app.callManager.HangupById(*ch.Id, *ch.AppId); err != nil { + app.Log.Error(err.Error(), + wlog.Err(err), + wlog.String("call_id", *ch.Id), + ) + } + } else { + // low cps race call DEV-4783 + att, ok := app.Queue().Manager().GetAttempt(ch.AttemptId) + if ok { + att.SetCancel() + } } } } diff --git a/model/call.go b/model/call.go index 2375ea7..9df6155 100644 --- a/model/call.go +++ b/model/call.go @@ -250,8 +250,9 @@ type CallActionHangup struct { } type CallNoAnswer struct { - Id string `json:"id" db:"id"` - AppId string `json:"app_id" db:"app_id"` + Id *string `json:"id" db:"id"` + AppId *string `json:"app_id" db:"app_id"` + AttemptId int64 `json:"attempt_id" db:"attempt_id"` } type AmdAiResult struct { diff --git a/queue/attempt.go b/queue/attempt.go index 4323e49..6f056ff 100644 --- a/queue/attempt.go +++ b/queue/attempt.go @@ -590,6 +590,14 @@ func (a *Attempt) SetCancel() { } } +func (a *Attempt) Canceled() bool { + a.RLock() + c := a.canceled + a.RUnlock() + + return c +} + func (a *Attempt) Cancel() <-chan struct{} { return a.cancel } diff --git a/queue/call_progressive.go b/queue/call_progressive.go index 1d455ca..a7e1bfd 100644 --- a/queue/call_progressive.go +++ b/queue/call_progressive.go @@ -166,6 +166,12 @@ func (queue *ProgressiveCallQueue) run(attempt *Attempt, team *agentTeam, agent }) } + if attempt.Canceled() { + queue.queueManager.SetAttemptAbandonedWithParams(attempt, queue.MaxAttempts+1, 0, nil) + queue.queueManager.LeavingMember(attempt) + return + } + //FIXME update member call id team.Distribute(queue, agent, NewDistributeEvent(attempt, agent.UserId(), queue, agent, queue.Processing(), nil, mCall)) attempt.memberChannel = mCall diff --git a/store/sqlstore/agent_store.go b/store/sqlstore/agent_store.go index 2bb2b41..6ec479b 100644 --- a/store/sqlstore/agent_store.go +++ b/store/sqlstore/agent_store.go @@ -219,15 +219,17 @@ WHERE (q_1.team_id IS NULL OR a_1.team_id = q_1.team_id) func (s *SqlAgentStore) GetNoAnswerChannels(agentId int, queueTypes []int) ([]*model.CallNoAnswer, *model.AppError) { var res []*model.CallNoAnswer - _, err := s.GetMaster().Select(&res, `select c.id, c.app_id + _, err := s.GetMaster().Select(&res, `select c.id, c.app_id, at.id attempt_id from call_center.cc_member_attempt at left join call_center.cc_queue q on q.id = at.queue_id left join call_center.cc_calls c on case when q.type = 4 then c.id::text = at.member_call_id else c.id::text = at.agent_call_id end + and c.answered_at isnull + and c.id notnull where at.agent_id = :AgentId - and c.answered_at isnull - and c.id notnull - and (:QueueTypes::smallint[] isnull or q.type = any(:QueueTypes::smallint[]))`, map[string]interface{}{ + and at.channel = 'call' + and at.state = 'offering' + and (:QueueTypes::smallint[] isnull or q.type = any (:QueueTypes::smallint[]))`, map[string]interface{}{ "AgentId": agentId, "QueueTypes": pq.Array(queueTypes), })