Twilio Taskrouter: Как предотвратить переназначение отклоненного задания последнему работнику в очереди?
Я использую NodeJS для управления рабочим процессом Twilio Taskrouter. Моя цель состоит в том, чтобы задача, назначенная на неработающего работника в основной очереди, была обозначена как queueSid
, если не выполнено одно из следующих действий:
Ни один из рабочих в очереди не установлен в режим ожидания
Резервирования для задачи уже были отклонены каждым работником в очереди
В этих случаях задача должна перейти к следующей очереди, идентифицированной как automaticQueueSid
, Вот как я создаю JSON для рабочего процесса (он включает в себя фильтр, так что входящий вызов от агента не должен генерировать исходящий вызов для того же агента):
configurationJSON(){
var config={
"task_routing":{
"filters":[
{
"filter_friendly_name":"don't call self",
"expression":"1==1",
"targets":[
{
"queue":queueSid,
"expression":"(task.caller!=worker.contact_uri) and (worker.sid NOT IN task.rejectedWorkers)",
"skip_if": "workers.available == 0"
},
{
"queue":automaticQueueSid
}
]
}
],
"default_filter":{
"queue":queueSid
}
}
}
return config;
}
Это приводит к тому, что резервирование не создается после того, как задача достигает очереди. Мой журнал событий показывает, что произошли следующие события:
workflow.target-matched
workflow.entered
task.created
Это так далеко, как он получает и просто висит там. Когда я заменяю линию
"expression":"(task.caller!=worker.contact_uri) and (worker.sid NOT IN task.rejectedWorkers)"
с
"expression":"(task.caller!=worker.contact_uri)
Затем резервирование будет правильно создано для следующего доступного работника или отправлено automaticQueueSid
если на входящем звонке нет рабочих, так что skip_if
работает правильно. Так может быть что-то не так с тем, как я написал целевое выражение?
Я попытался обойти эту проблему, установив недоступность работника после того, как он отклонил резервирование, следующим образом:
clientWorkspace
.workers(parameters.workerSid)
.reservations(parameters.reservationSid)
.update({
reservationStatus:'rejected'
})
.then(reservation=>{
//this function sets the worker's Activity to Offline
var updateResult=worker.updateWorkerFromSid(parameters.workerSid,process.env.TWILIO_OFFLINE_SID);
})
.catch(err=>console.log("/agent_rejects: error rejecting reservation: "+err));
Но, похоже, происходит то, что, как только оговорка будет отклонена, прежде чем worker.updateWorkerFromSid()
Вызов, Taskrouter уже сгенерировал новое резервирование и назначил его тому же работнику, и мое обновление Activity завершилось неудачно со следующей ошибкой:
Error: Worker [workerSid] cannot have its activity updated while it has 1 pending reservations.
В конце концов, кажется, что для работника естественным образом установлено значение "Не в сети", и задание истекает и перемещается в следующую очередь, как показано следующими событиями / описаниями:
worker.activity.update
Worker [friendly name] updated to Offline Activity
reservation.timeout
Reservation [sid] timed out
task-queue.moved
Task [sid] moved out of TaskQueue [friendly name]
task-queue.timeout
Task [sid] timed out of TaskQueue [friendly name]
После этого момента задание перемещается в следующую очередь automaticQueueSid
обрабатываться доступными работниками, зарегистрированными в этой очереди. Я не уверен, почему используется тайм-аут, так как я не включил его в свою конфигурацию рабочего процесса.
Я в замешательстве - как я могу получить задачу, чтобы успешно перейти в следующую очередь после отклонения резервирования последнего работника?
ОБНОВЛЕНИЕ: хотя ответ @philnash помог мне правильно справиться с worker.sid NOT IN task.rejectedWorkers
В конечном итоге я реализовал эту функцию, используя параметр RejectPendingReservations при обновлении доступности работника.
2 ответа
Twilio разработчик евангелист здесь.
rejectedWorkers
не является атрибутом, который автоматически обрабатывается TaskRouter. Вы ссылаетесь на этот ответ моей коллеги Меган, в которой она говорит:
Например, вы можете обновить TaskAttributes, чтобы иметь список отклоненных рабочих SID, а затем в рабочем процессе сказать, что worker.sid NOT IN task.rejectedWorkerSids.
Итак, чтобы отфильтровать по rejectedWorkers
Атрибут необходимо поддерживать самостоятельно, обновив задачу перед тем, как отклонить бронирование.
Дайте мне знать, если это поможет.
Мне удается сделать нечто подобное, используя URL-адрес обратного вызова назначения для рабочего процесса, который обрабатывает маршрутизацию задачи.
Я создал бессерверную функцию, которая обновляет атрибут задачи, например «отклонено», до значения true и устанавливает URL-адрес этой функции в качестве упомянутого обратного вызова.
Кроме того, я добавляю этот атрибут к созданию задачи и использую его в качестве фильтра в фильтрах шагов сопоставления рабочего процесса.
Разница здесь в том, что мне нужно было то, что если вызов был отклонен для какого-либо работника (хотя бы один раз), он переходит в другую очередь (с другой бизнес-логикой).