JavaScript용 AzureCommunicationRoutingService REST 클라이언트 라이브러리

Azure Communication Routing Service

이 라이브러리를 사용하려면 REST 클라이언트 문서에 크게 의존하세요.

주요 링크:

시작

현재 지원되는 환경

  • Node.js의 LTS 버전

사전 요구 사항

  • 이 패키지를 사용하려면 Azure 구독 이 있어야 합니다.

ACS 리소스 사용

Azure Portal에서 ACS 리소스를 만들거나 기존 리소스를 사용합니다.

@azure-rest/communication-job-router 패키지를 설치합니다.

를 사용하여 JavaScript용 AzureCommunicationRoutingService REST 클라이언트 REST 클라이언트 라이브러리를 npm설치합니다.

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

AzureCommunicationRoutingServiceClient 만들기 및 인증

AAD(Azure Active Directory) 토큰 자격 증명을 사용하려면 @azure/ID 라이브러리에서 가져온 원하는 자격 증명 형식의 instance 제공합니다.

AAD를 사용하여 인증하려면 먼저 npm 설치해야 합니다. @azure/identity

설치 후 사용할 자격 증명@azure/identity 유형을 선택할 수 있습니다. 예를 들어 DefaultAzureCredential을 사용하여 클라이언트를 인증할 수 있습니다.

AAD 애플리케이션의 클라이언트 ID, 테넌트 ID 및 클라이언트 암호 값을 환경 변수(AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET

자습서: ACS(Azure Communication Services) 작업 라우터 Rest SDK를 사용하여 작업자에게 작업 라우팅

이 자습서에서는 다음에 대해 알아봅니다.

  • 큐를 만드는 방법
  • 작업자를 만들고 큐에 할당하는 방법입니다.
  • 작업자에게 작업을 라우팅하는 방법.
  • 작업 라우터 이벤트를 구독하고 처리하는 방법입니다.
  • 작업을 완료하고 닫는 방법입니다.

NodeJS Express 서버 시작

셸(cmd, PowerShell, Bash 등)에서 라는 RouterQuickStart 폴더를 만들고 이 폴더 내에서 를 실행합니다 npx express-generator. 그러면 에서 port 3000수신 대기하는 간단한 Express 프로젝트가 생성됩니다.

예제

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

Azure ACS 작업 라우터 SDK 설치

폴더에서 RouterQuickStart 를 실행하여 ACS 작업 라우터 SDK를 설치합니다 npm install @azure-rest/communication-job-router --save.

라우팅 작업

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: {},
  }
});

작업자 만들기

이러한 작업자는 이전에 만든 "Sales" 큐에 할당되며 일부 레이블이 있습니다.

  • 를 로 설정 availableForOffers 하면 true 이러한 작업자가 작업 제안을 수락할 준비가 됨을 의미합니다.
  • 레이블 및 레이블 선택기를 더 잘 이해하려면 레이블 설명서를 참조하세요.
  // 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 Portal을 사용하는 것입니다.

  1. Azure Portal에서 ACS 리소스로 이동하여 "이벤트" 블레이드를 엽니다.
  2. "RouterWorkerOfferIssued" 이벤트에 대한 이벤트 구독을 추가합니다.
  3. 이벤트를 수신할 적절한 방법을 선택합니다(예: 웹후크, Azure Functions, Service Bus).

작업 라우터 이벤트 구독을 더 잘 이해하려면 "작업 라우터 이벤트 구독" 설명서를 참조하세요.

이벤트를 수신하는 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 package docs를 참조하세요.