Azure Communication Services (ACS) Job Router SDK for JavaScript
This package contains the JavaScript SDK for the Azure Communication Services (ACS) Job Router Service.
Getting Started
Key Concepts
Refer to our Job Router key concepts documentation to better understand Job Router.
Prerequisites
- An Azure subscription.
- An Azure Communication Services (ACS) resource.
- If you need to create an ACS resource, you can use the Azure Portal, Azure PowerShell, or the Azure CLI.
Installing
npm install @azure/communication-job-router
Browser support
To use Azure SDK libraries on a website, you need to convert your code to work inside the browser. You do this using a tool called a bundler. Refer to our bundling documentation to better understand bundling.
Tutorial: Route jobs to workers using the Azure Communication Services (ACS) Job Router SDK
In this tutorial, you will learn:
- How to create a queue.
- How to create workers and assign them to a queue.
- How to route jobs to workers.
- How to subscribe to and handle Job Router events.
- How to complete and close jobs.
Setting Up
(Optional) Install an IDE
Install an IDE such as VSCode or Webstorm.
Install NodeJS
Install NodeJS.
Start a NodeJS Express server
In a shell (cmd, PowerShell, Bash, etc.), create a folder called RouterQuickStart
and inside this folder execute npx express-generator
. This will generate a simple Express project that will listen on port 3000
.
Example
mkdir RouterQuickStart
cd RouterQuickStart
npx express-generator
npm install
DEBUG=routerquickstart:* npm start
Have an ACS Resource
Create an ACS resource in the Azure Portal or use an existing resource.
Install the Azure ACS Job Router SDK
In the RouterQuickStart
folder, install the ACS Job Router SDK by executing npm install @azure/communication-job-router --save
.
Routing Jobs
Construct Job Router Clients
First we need to construct a jobRouterAdministrationClient
and a jobRouterClient
.
jobRouterAdministrationClient
provides methods for Classification Policies, Distribution Policies, Exception Policies, and Queues.jobRouterClient
provides methods for Jobs and Workers.
const {
JobRouterClient,
JobRouterAdministrationClient,
} = require("@azure/communication-job-router");
const acsConnectionString =
"endpoint=https://<YOUR_ACS>.communication.azure.com/;accesskey=<YOUR_ACCESS_KEY>";
const jobRouterClient = new JobRouterClient(acsConnectionString);
const jobRouterAdministrationClient = new JobRouterAdministrationClient(acsConnectionString);
Create a Distribution Policy
This policy determines which workers will receive job offers as jobs are distributed off their queues.
const distributionPolicy = await jobRouterAdministrationClient.createDistributionPolicy(
"default-distribution-policy-id",
{
name: "Default Distribution Policy",
offerExpiresAfterSeconds: 30,
mode: {
objectType: "longest-idle",
minConcurrentOffers: 1,
maxConcurrentOffers: 3,
},
}
);
Create a Classification Policy
This policy classifies jobs upon creation.
- Refer to our rules documentation to better understand prioritization rules.
const classificationPolicy = await jobRouterAdministrationClient.createClassificationPolicy("default-classification-policy-id", {
name: "Default Classification Policy",
fallbackQueueId: salesQueueResponse.Id,
queueSelectors: [{
kind: "static",
labelSelector: { key: "department", labelOperator: "equal", value: "xbox" }
}],
workerSelectors: [{
kind: "static",
labelSelector: { key: "english", labelOperator: "greaterThan", value: 5 }
}],
prioritizationRule: {
kind: "expression-rule",
language: "powerFx";
expression: "If(job.department = \"xbox\", 2, 1)"
}
});
Create a Queue
This queue offers jobs to workers according to our previously created distribution policy.
const salesQueueResponse = await jobRouterAdministrationClient.createQueue("sales-queue-id", {
name: "Sales",
distributionPolicyId: distributionPolicy.Id,
labels: {
department: "xbox",
},
});
Create Workers
These workers are assigned to our previously created "Sales" queue and have some labels.
- setting
availableForOffers
totrue
means these workers are ready to accept job offers. - refer to our labels documentation to better understand labels and label selectors.
// Create worker "Alice".
const workerAliceId = "773accfb-476e-42f9-a202-b211b41a4ea4";
const workerAliceResponse = await jobRouterClient.createWorker(workerAliceId, {
totalCapacity: 120,
labels: {
Xbox: 5,
german: 4
name: "Alice",
},
queueAssignments: { [salesQueueResponse.Id]: {} },
availableForOffers: true
});
// Create worker "Bob".
const workerBobId = "21837c88-6967-4078-86b9-1207821a8392";
const workerBobResponse = await jobRouterClient.createWorker(workerBobId, {
totalCapacity: 100,
labels: {
xbox: 5,
english: 3
name: "Bob"
},
queueAssignments: { [salesQueueResponse]: {} },
availableForOffers: true
});
Job Lifecycle
Refer to our job lifecycle documentation to better understand the lifecycle of a job.
Create a Job
This job is enqueued on our previously created "Sales" queue.
const job = await jobRouterClient.createJob("job-id", {
// e.g. callId or chat threadId
channelReference: "66e4362e-aad5-4d71-bb51-448672ebf492",
channelId: "voice",
priority: 2,
queueId: salesQueueResponse.Id,
});
(Optional) Create Job With a Classification Policy
This job will be classified with our previously created classification policy. It also has a label.
const classificationJob = await JobRouterClient.createJob("classification-job-id", {
// e.g. callId or chat threadId
channelReference: "66e4362e-aad5-4d71-bb51-448672ebf492",
channelId: "voice",
classificationPolicyId: classificationPolicy.Id,
labels: {
department: "xbox",
},
});
Events
Job Router events are delivered via Azure Event Grid. Refer to our Azure Event Grid documentation to better understand Azure Event Grid.
In the previous example:
- The job gets enqueued to the “Sales" queue.
- A worker is selected to handle the job, a job offer is issued to that worker, and a
RouterWorkerOfferIssued
event is sent via Azure Event Grid.
Example RouterWorkerOfferIssued
JSON shape:
{
"id": "1027db4a-17fe-4a7f-ae67-276c3120a29f",
"topic": "/subscriptions/{subscription-id}/resourceGroups/{group-name}/providers/Microsoft.Communication/communicationServices/{communication-services-resource-name}",
"subject": "worker/{worker-id}/job/{job-id}",
"data": {
"workerId": "w100",
"jobId": "7f1df17b-570b-4ae5-9cf5-fe6ff64cc712",
"channelReference": "test-abc",
"channelId": "FooVoiceChannelId",
"queueId": "625fec06-ab81-4e60-b780-f364ed96ade1",
"offerId": "525fec06-ab81-4e60-b780-f364ed96ade1",
"offerTimeUtc": "2023-08-17T02:43:30.3847144Z",
"expiryTimeUtc": "2023-08-17T02:44:30.3847674Z",
"jobPriority": 5,
"jobLabels": {
"Locale": "en-us",
"Segment": "Enterprise",
"Token": "FooToken"
},
"jobTags": {
"Locale": "en-us",
"Segment": "Enterprise",
"Token": "FooToken"
}
},
"eventType": "Microsoft.Communication.RouterWorkerOfferIssued",
"dataVersion": "1.0",
"metadataVersion": "1",
"eventTime": "2023-08-17T00:55:25.1736293Z"
}
Subscribing to Events
One way to subscribe to ACS Job Router events is through the Azure Portal.
- Navigate to your ACS resource in the Azure Portal and open the “Events” blade.
- Add an event subscription for the “RouterWorkerOfferIssued” event.
- Select an appropriate means to receive the event (e.g. Webhook, Azure Functions, Service Bus).
Refer to our "subscribe to Job Router events" documentation to better understand subscribing to Job Router events.
The route in your NodeJS application that receives events may look something like this:
app.post('/event', (req, res) => {
req.body.forEach(eventGridEvent => {
// Deserialize the event data into the appropriate type
if (eventGridEvent.eventType === "Microsoft.EventGrid.SubscriptionValidationEvent") {
res.send({ validationResponse: eventGridEvent.data.validationCode };
} else if (eventGridEvent.eventType === "Microsoft.Azure.CommunicationServices.RouterWorkerOfferIssued") {
// RouterWorkerOfferIssued handling logic;
} else if ...
});
...
});
Accept or Decline the Job Offer
Once you receive a RouterWorkerOfferIssued
event you can accept or decline the job offer.
workerid
- The id of the worker accepting the job offer.offerId
- The id of the offer being accepted or declined.
const acceptResponse = await jobRouterClient.acceptJobOffer(workerId, offerId);
// or
const declineResponse = await jobRouterClient.declineJobOffer(workerId, offerId);
Complete the Job
The assignmentId
received from the previous step's response is required to complete the job.
await jobRouterClient.completeJob(jobId, assignmentId);
Close the Job
Once the worker has completed the wrap-up phase of the job the jobRouterClient
can close the job and attach a disposition code to it for future reference.
await jobRouterClient.closeJob(jobId, assignmentId, { dispositionCode: "Resolved" });
Next steps
Take a look at the samples directory for additional detailed examples of using this SDK.
Contributing
If you'd like to contribute to this SDK, please read the contributing guide to learn more about how to build and test the code.
Related projects
Azure SDK for JavaScript