I have a task router with some workers, when there is an incoming call and the worker does not answer the call, then the worker is been updated, and the status is been set to offline. Can I avoid that and keep the worker in the available activity state?
worker.on 'activity.update', #_onWorkerActivityUpdated
Configuring Default Activities for Worker State Transitions
If a Reservation times out, the Worker is placed in the TimeoutActivity identified by the Workspace. By default this is Offline.
Related
In our Twilio application we would like to use TaskRouter to distribute incoming calls. Suppose we would like to handle the following scenario:
All Workers login to front-end application and have their status set to Available. If there are any incoming calls, Workers receive them in the UI.
Some Workers have this custom attribute: {"work_hours": [600, 1600], "phone_numbers": ["+1...", "+1..."]}. If for some reason this Worker becomes Unavailable during their working hours set between "work_hours" attribute, we would still like to have incoming calls forwarded to their personal phones from "phone_numbers" attribute.
If the above fails, we would like to forward the incoming call to Voicemail.
Basically, my question is whether it is possible to include Unavailable workers to Workflows and Task Queues? The above scenario would most likely require 3 Task Queues: one for all Available Workers, one for Unavailable but with "work_hours" attributes where taskrouter.currentTime is between those hours and one for Voicemail.
Twilio Solutions Architect here!
I think that you may already found a solution for your problem, but in case someone else is having this problem, here's my solution:
The best way to do this is actually creating a new Activity on TaskRouter of type Unavailable with Work Hours that is is an available Activity. With that state created, you can set the worker availability to this state when they are on this use case, and with the Task Router Workflows, you can have specific queues for these agents and using the routing strategies, bring a task to this queue if necessary.
Regarding to call the agents on their personal phone numbers, you can create a conference between the original call and the agent's phone number and have them connected.
This is a bit tricky, but is completely possible.
We are using Twilio Task Router with Multitasking disabled Workspace and only default Task Channel set as Available for all Workers. After the Task Reservation is Accepted the Worker activity goes from Reserved to Busy, as expected. But finally when the Task status is updated to 'Completed', the Worker activity is not getting changed to Idle as expected, but instead it stays in Busy activity. Is this a bug or the expected behavior? Or are we missing any configuration?
Twilio engineer on the TaskRouter team here! Yes, this is expected behavior for single-tasking.
What you'll find is that when the Reservation is assigned, the Worker it's assigned to will move to the the "Busy" Activity for that TaskQueue (or whatever Activity is specified for assignment, which can be change via the API here, or you can set it via the Console here), as you've described.
When a Task completes, however, there is no guarantee in a single-tasking environment that the Worker is actually ready to take work again at that moment—they may be, but that depends on your workflow. So we need confirmation before assigning Tasks to them again. This is why the Worker's Activity needs to be manually set back to "Idle" before they will start receiving Tasks again.
One of the easiest ways to do this, if this is the workflow you want, is to listen for the task.completed event, either at your EventCallbackUrl or via the JS SDK, and issue an Activity update to "Idle" for the associated Worker at that time.
Hope this answers your question!
Considering the fileprocessing sample which executes download activity on any host from the pool, then converts the file and uploads the result on the same host as the first one, is there a way to route an activity task to preferably (not always) a specific worker in the SWF fleet based upon the worker's availability, reason is that the worker should not be overloaded with tasks which might affect the latency.
There are two use cases for not overloading host with tasks. The first is when a host just needs to limit a number of parallel activities running on it. It is done by setting the ActivityWorker.setTaskExecutorThreadPoolSize property.
The second is when a host needs to limit number of sequences of activities running on it. For example as in fileprocessing example limiting number of files to be processed at the same time. The solution is to use a special semaphore like activity that runs for the duration of the whole sequence. Here is the outline of the implementation:
Hosts listen for "semaphore" activity on a special common task list using a separate activity worker.
The number of parallel activities on this worker is limited through setTaskExecutorThreadPoolSize.
Once the "semaphore" activity starts executing on a host it sends a signal to its workflow with a host specific task list. Then it just keeps periodically heartbeating to SWF.
All other activities from the given workflow are dispatched to the host specific task list received through the signal sent by the "semaphore" activity.
After the last host specific activity is done the "semaphore" activity is cancelled.
The semaphore activity learns about cancellation on the next heartbeat. Then it rethrows cancellation exception which completes it with the worker and releases a place in the task executor thread pool.
A variation is to not use the cancellation but notify the semaphore activity in process by the last activity in a sequence.
I am new in Twilio and i have been facing an issue while designing outbound dialer currently preview dialing. If a worker rejects a task than the same task should not be offered to that worker again.
How do i handle this case?
Typically if a worker rejects the task, the worker should be moved to an unavailable activity. Otherwise, if the worker is the only available and qualified worker, TaskRouter will continue to create new reservations.
You can specify a new activitySid upon rejection, so that the worker is moved to an unavailable activity at the same time:
https://www.twilio.com/docs/api/taskrouter/worker-js#reservation-reject
Here, making the worker activity unavailable would simply mean the worker will not be able to get any task.
But let's look at a more complicated use case where a Worker can accept, reject or cancel tasks. They need to be available to make this choice.
If you have only that agent, and they are available, then there is no way to prevent that agent from receiving the Task, unless you manipulate the Task attributes or worker attributes so that TaskRouter doesn’t assign the Task. For example, you could update TaskAttributes to have a rejected worker SID list, and then in the workflow say that worker.sid NOT IN task.rejectedWorkerSids.
And the ability to do this Target Workers Expression just shipped as a bug fix today! It should look like:
worker.sid NOT IN task.rejectedWorkers
The image below shows that there are two workers installed - one active and the other not active (just installed).
Register a service worker
Make changes to service-worker.js and reload the page.
The logic is that Service Workers check binary diff and updates the versions of the workers.
So a new service worker is spawned with a new version ID. But why does the old one keeps running ? and How do I close it ?
The sw.js is here https://gist.github.com/boopathi/57b7e8b6d657d55bdc7d
By default, until all tabs that have a page controlled by that old service worker are closed/unloaded, the old service worker will stay running. The new service worker will, well, "wait" in the "waiting" state.
There are options that change this default behavior. They're skipWaiting() and clients.claim().
When skipWaiting() is called from an installing service worker, it will, well, skip the "waiting" state and immediately activate. However, it will not necessarily take control of pages despite being activated—that's what clients.claim() will accomplish.