你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 JavaScript 的 AzureCommunicationRoutingService REST 客户端库

Azure 通信路由服务

请严重依赖我们的 REST 客户端文档 来使用此库

关键链接:

入门

目前支持的环境

  • LTS 版本的 Node.js

先决条件

具有 ACS 资源

Azure 门户中 创建 ACS 资源或使用现有资源。

安装 @azure-rest/communication-job-router

使用 npm安装适用于 JavaScript 的 AzureCommunicationRoutingService REST 客户端 REST 客户端库:

npm install @azure-rest/communication-job-router

创建 AzureCommunicationRoutingServiceClient 并对其进行身份验证

若要使用 Azure Active Directory (AAD) 令牌凭据,请提供从 @azure/标识 库获取的所需凭据类型的实例。

若要使用 AAD 进行身份验证,必须先 npm 安装 @azure/identity

设置后,可以选择要使用的@azure/identity凭据类型。 例如, DefaultAzureCredential 可用于对客户端进行身份验证。

将 AAD 应用程序的客户端 ID、租户 ID 和客户端密码的值设置为环境变量:AZURE_CLIENT_ID、AZURE_TENANT_ID、AZURE_CLIENT_SECRET

教程:使用 Azure 通信服务 (ACS) 作业路由器 Rest SDK 将作业路由到辅助角色

本教程介绍:

  • 如何创建队列。
  • 如何创建辅助角色并将其分配到队列。
  • 如何将作业路由到辅助角色。
  • 如何订阅和处理作业路由器事件。
  • 如何完成和关闭作业。

启动 NodeJS Express 服务器

在 shell (cmd、PowerShell、Bash 等 ) 中创建名为 RouterQuickStart 的文件夹,并在此文件夹中执行 npx express-generator。 这将生成一个简单的 Express 项目,该项目将侦听 port 3000

示例

mkdir RouterQuickStart
cd RouterQuickStart
npx express-generator
npm install
DEBUG=routerquickstart:* npm start

安装 Azure ACS 作业路由器 SDK

RouterQuickStart 文件夹中,通过执行 npm install @azure-rest/communication-job-router --save安装 ACS 作业路由器 SDK。

路由作业

构造 AzureCommunicationRoutingServiceClient

首先,我们需要构造 。AzureCommunicationRoutingServiceClient

const JobRouterClient = require("@azure-rest/communication-job-router").default;

const connectionString = "endpoint=https://<YOUR_ACS>.communication.azure.com/;accesskey=<YOUR_ACCESS_KEY>";
const routerClient = JobRouterClient(connectionString);

创建分发策略

此策略确定当作业从队列中分发时,哪些辅助角色将收到作业优惠。

const distributionPolicy = await routerClient.path("/routing/distributionPolicies/{id}", "distributionPolicy-1").patch({
  contentType: "application/merge-patch+json",
  body: {
    name: "distribution-policy-123",
    offerExpiresAfterSeconds: 30,
    mode: {
      kind: "longestIdle",
      minConcurrentOffers: 1,
      maxConcurrentOffers: 3,
    },
  }
});

创建队列

此队列根据我们之前创建的分发策略向辅助角色提供作业。

const salesQueueId = "queue-123";
await routerClient.path("/routing/queues/{id}", salesQueueId).patch({
  contentType: "application/merge-patch+json",
  body: {
    distributionPolicyId: distributionPolicy.body.id,
    name: "Main",
    labels: {},
  }
});

创建辅助角色

这些辅助角色被分配到我们之前创建的“销售”队列,并具有一些标签。

  • true设置为 availableForOffers 表示这些工作人员已准备好接受工作机会。
  • 请参阅 标签文档 ,更好地了解标签和标签选择器。
  // Create worker "Alice".
const workerAliceId = "773accfb-476e-42f9-a202-b211b41a4ea4";
const workerAliceResponse = await routerClient.path("/routing/workers/{workerId}", workerAliceId).patch({
  contentType: "application/merge-patch+json",
  body: {
    capacity: 120,
    queues: [salesQueueId],
    labels: {
      Xbox: 5,
      german: 4,
      name: "Alice"
    },
    channels: [
      {
        channelId: "CustomChatChannel",
        capacityCostPerJob: 10,
      },
      {
        channelId: "CustomVoiceChannel",
        capacityCostPerJob: 100,
      },
    ],
  }
});

// Create worker "Bob".
const workerBobId = "21837c88-6967-4078-86b9-1207821a8392";
const workerBobResponse = await routerClient.path("/routing/workers/{workerId}", workerBobId).patch({
  contentType: "application/merge-patch+json",
  body: {
    capacity: 100,
    queues: [salesQueueId],
    labels: {
      Xbox: 5,
      english: 3,
      name: "Alice"
    },
    channels: [
      {
        channelId: "CustomChatChannel",
        capacityCostPerJob: 10,
      },
      {
        channelId: "CustomVoiceChannel",
        capacityCostPerJob: 100,
      },
    ],
  }
});

作业生命周期

请参阅 我们的作业生命周期文档 ,以更好地了解作业的生命周期。

创建作业

此作业在之前创建的“Sales”队列中排队。

const jobId = "router-job-123";
const result = await routerClient.path("/routing/jobs/{id}", jobId).patch({
  contentType: "application/merge-patch+json",
  body: {
    channelReference: "66e4362e-aad5-4d71-bb51-448672ebf492",
    channelId: "voice",
    priority: 2,
    queueId: "salesQueueId",
    labels: {},
  }
});

(可选) 使用分类策略创建作业

创建分类策略

此策略在创建时对作业进行分类。

  • 请参阅 规则文档 ,更好地了解优先顺序规则。
const classificationPolicyId = "classification-policy-123";
const result = await routerClient.path("/routing/classificationPolicies/{id}", classificationPolicyId).patch({
  contentType: "application/merge-patch+json",
  body: {
    name: "Default Classification Policy",
    fallbackQueueId: salesQueueId,
    queueSelectorAttachments: [
      {
        kind: "static",
        queueSelector: { key: "department", labelOperator: "equal", value: "xbox" }
      },
    ],
    workerSelectorAttachments: [{
      kind: "static",
      workerSelector: { key: "english", labelOperator: "greaterThan", value: 5 }
    }],
    prioritizationRule: {
      kind: "expression",
      language: "powerFx",
      expression: "If(job.department = \"xbox\", 2, 1)"
    }
  }
});

创建作业并对其进行分类

此作业将使用我们之前创建的分类策略进行分类。 它还具有标签。

const result = await routerClient.path("/routing/jobs/{id}", jobId).patch({
  contentType: "application/merge-patch+json",
  body: {
    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](/azure/event-grid/overview) 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:

```json
{
  "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"
}

订阅事件

订阅 ACS 作业路由器事件的一种方法是通过 Azure 门户。

  1. 在 Azure 门户中导航到 ACS 资源,并打开“事件”边栏选项卡。
  2. 为“RouterWorkerOfferIssued”事件添加事件订阅。
  3. 选择适当的方法来接收事件 (例如 Webhook、Azure Functions、服务总线) 。

请参阅 我们的“订阅作业路由器事件”文档 ,更好地了解订阅作业路由器事件。

NodeJS 应用程序中接收事件的路由可能如下所示:

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 ...
    });
    ...
});

接受或拒绝工作机会

收到事件后 RouterWorkerOfferIssued ,可以接受或拒绝工作机会。

  • workerid - 接受工作机会的工作线程的 ID。
  • offerId - 接受或拒绝的产品/服务的 ID。
const acceptResponse = await routerClient.path("/routing/workers/{workerId}/offers/{offerId}:accept", workerId, offerId).post();
// or
const declineResponse = await routerClient.path("/routing/workers/{workerId}/offers/{offerId}:decline", workerId, offerId).post();

完成作业

assignmentId需要从上一步的响应收到的 才能完成作业。

const completeJob = await routerClient.path("/routing/jobs/{id}/assignments/{assignmentId}:complete", jobId, acceptResponse.body.assignmentId).post({
  body: {
    note: `Job has been completed by ${workerId} at ${new Date()}`
  }
});

关闭作业

辅助角色完成作业的结束阶段后, jobRouterClient 可以关闭作业并向其附加处置代码以供将来参考。

const closeJob = await routerClient.path("/routing/jobs/{id}/assignments/{assignmentId}:close", jobId, acceptResponse.body.assignmentId).post({
  body: {
    note: `Job has been closed by ${workerId} at ${new Date()}`
  }
});

疑难解答

日志记录

启用日志记录可能有助于发现有关故障的有用信息。 若要查看 HTTP 请求和响应的日志,请将 AZURE_LOG_LEVEL 环境变量设置为 info。 或者,可以在运行时通过调用 @azure/logger 中的 setLogLevel 来启用日志记录:

const { setLogLevel } = require("@azure/logger");

setLogLevel("info");

有关如何启用日志的更详细说明,请查看 @azure/logger 包文档