Udostępnij za pośrednictwem


Klasyfikowanie zadania

Dowiedz się, jak używać zasad klasyfikacji w routerze zadań w celu dynamicznego rozpoznawania kolejki i priorytetu, a jednocześnie dołączania selektorów procesów roboczych do zadania.

Wymagania wstępne

Tworzenie zasad klasyfikacji

Poniższy przykład wykorzystuje wyrażenia PowerFx, aby wybrać zarówno kolejkę, jak i priorytet. Wyrażenie próbuje dopasować etykietę Zadania o nazwie Region równej, co NA powoduje umieszczenie zadania w obiekcie XBOX_NA_QUEUE. W przeciwnym razie zadanie jest wysyłane do kolejki XBOX_DEFAULT_QUEUE rezerwowej zgodnie z definicją w pliku fallbackQueueId. Ponadto priorytetem jest 10 , jeśli etykieta o nazwie Hardware_VIP została dopasowana, w przeciwnym razie jest to 1.

var classificationPolicy = await administrationClient.CreateClassificationPolicyAsync(
    new CreateClassificationPolicyOptions(classificationPolicyId: "XBOX_NA_QUEUE_Priority_1_10")
    {
        Name = "Select XBOX Queue and set priority to 1 or 10",
        QueueSelectorAttachments =
        {
            new ConditionalQueueSelectorAttachment(condition: new ExpressionRouterRule("job.Region = \"NA\""),
                queueSelectors: new List<RouterQueueSelector>
                {
                    new(key: "Id", labelOperator: LabelOperator.Equal, value: new RouterValue("XBOX_NA_QUEUE"))
                })
        },
        FallbackQueueId = "XBOX_DEFAULT_QUEUE",
        PrioritizationRule = new ExpressionRouterRule("If(job.Hardware_VIP = true, 10, 1)"),
    });
var classificationPolicy = await client.path("/routing/classificationPolicies/{classificationPolicyId}", 
        "XBOX_NA_QUEUE_Priority_1_10").patch({
    body: {
        name: "Select XBOX Queue and set priority to 1 or 10",
        queueSelectorAttachments: [{            
            kind: "conditional",
            condition: {
                kind: "expression",
                expression: 'job.Region = "NA"'
            },
            queueSelectors: [{
                key: "Id",
                labelOperator: "equal",
                value: "XBOX_NA_QUEUE"
            }]
        }],
        fallbackQueueId: "XBOX_DEFAULT_QUEUE",
        prioritizationRule: {
            kind: "expression",
            expression: "If(job.Hardware_VIP = true, 10, 1)"
        }
    },
    contentType: "application/merge-patch+json"
});
classification_policy: ClassificationPolicy = administration_client.upsert_classification_policy(
    classification_policy_id = "XBOX_NA_QUEUE_Priority_1_10",
    name = "Select XBOX Queue and set priority to 1 or 10",
    queue_selector_attachments = [
        ConditionalQueueSelectorAttachment(
            condition = ExpressionRouterRule(expression = 'job.Region = "NA"'),
            queue_selectors = [
                RouterQueueSelector(key = "Id", label_operator = LabelOperator.EQUAL, value = "XBOX_NA_QUEUE")
            ]
        )
    ],
    fallback_queue_id = "XBOX_DEFAULT_QUEUE",
    prioritization_rule = ExpressionRouterRule(expression = "If(job.Hardware_VIP = true, 10, 1)")))
ClassificationPolicy classificationPolicy = administrationClient.createClassificationPolicy(
    new CreateClassificationPolicyOptions("XBOX_NA_QUEUE_Priority_1_10")
        .setName("Select XBOX Queue and set priority to 1 or 10")
        .setQueueSelectors(List.of(new ConditionalQueueSelectorAttachment(
            new ExpressionRouterRule("job.Region = \"NA\""),
            List.of(new RouterQueueSelector("Id", LabelOperator.EQUAL, new RouterValue("XBOX_NA_QUEUE"))))))
        .setFallbackQueueId("XBOX_DEFAULT_QUEUE")
        .setPrioritizationRule(new ExpressionRouterRule().setExpression("If(job.Hardware_VIP = true, 10, 1)")));

Przesyłanie zadania

Poniższy przykład powoduje, że zasady klasyfikacji oceniają etykiety zadań. Wynik umieszcza zadanie w kolejce o nazwie XBOX_NA_QUEUE i ustawia priorytet na 1. Przed oceną zasad klasyfikacji stan zadania to pendingClassification. Po ocenie zasad klasyfikacji stan zadania zostanie zaktualizowany do queued.

var job = await client.CreateJobWithClassificationPolicyAsync(new CreateJobWithClassificationPolicyOptions(
    jobId: "job1",
    channelId: "voice",
    classificationPolicyId: classificationPolicy.Value.Id)
{
    Labels =
    {
        ["Region"] = new RouterValue("NA"),
        ["Caller_Id"] = new RouterValue("7805551212"),
        ["Caller_NPA_NXX"] = new RouterValue("780555"),
        ["XBOX_Hardware"] = new RouterValue(7)
    }
});
var job = await client.path("/routing/jobs/{jobId}", "job1").patch({
    body: {
        channelId: "voice",
        classificationPolicyId: "XBOX_NA_QUEUE_Priority_1_10",
        labels: {
            Region: "NA",
            Caller_Id: "7805551212",
            Caller_NPA_NXX: "780555",
            XBOX_Hardware: 7
        }
    },
    contentType: "application/merge-patch+json"
});
job = client.upsert_job(
    job_id = "job1",
    channel_id = "voice",
    classification_policy_id = "XBOX_NA_QUEUE_Priority_1_10",
    labels = {
        "Region": "NA",
        "Caller_Id": "7805551212",
        "Caller_NPA_NXX": "780555",
        "XBOX_Hardware": 7
    }
)
RouterJob job = client.createJob(new CreateJobWithClassificationPolicyOptions("job1", "voice", "XBOX_NA_QUEUE_Priority_1_10")
    .setLabels(Map.of(
        "Region", new RouterValue("NA"),
        "Caller_Id": new RouterValue("7805551212"),
        "Caller_NPA_NXX": new RouterValue("780555"),
        "XBOX_Hardware": new RouterValue(7)
    )));

Dołączanie selektorów procesów roboczych

Możesz użyć zasad klasyfikacji, aby dołączyć więcej selektorów procesów roboczych do zadania.

Załączniki statyczne

W tym przykładzie zasady klasyfikacji są konfigurowane ze statycznym załącznikiem, który zawsze dołącza określony selektor etykiet do zadania.

await administrationClient.CreateClassificationPolicyAsync(
    new CreateClassificationPolicyOptions("policy-1")
    {
        WorkerSelectorAttachments =
        {
            new StaticWorkerSelectorAttachment(new RouterWorkerSelector(
                key: "Foo", labelOperator: LabelOperator.Equal, value: new RouterValue("Bar")))
        }
    });
await client.path("/routing/classificationPolicies/{classificationPolicyId}", "policy-1").patch({
    body: {
        workerSelectorAttachments: [{
            kind: "static",
            workerSelector: { key: "Foo", labelOperator: "equal", value: "Bar" }
        }]
    },
    contentType: "application/merge-patch+json"
});
administration_client.upsert_classification_policy(
    classification_policy_id = "policy-1",
    worker_selector_attachments = [
        StaticWorkerSelectorAttachment(
            worker_selector = RouterWorkerSelector(key = "Foo", label_operator = LabelOperator.EQUAL, value = "Bar")
        )
    ])
administrationClient.createClassificationPolicy(new CreateClassificationPolicyOptions("policy-1")
    .setWorkerSelectorAttachments(List.of(
        new StaticWorkerSelectorAttachment(new RouterWorkerSelector("Foo", LabelOperator.EQUAL, new RouterValue("Bar"))))));

Załączniki warunkowe

W tym przykładzie zasady klasyfikacji są konfigurowane przy użyciu załącznika warunkowego. W związku z tym ocenia warunek względem etykiet zadań, aby określić, czy selektory etykiet powinny być dołączone do zadania.

await administrationClient.CreateClassificationPolicyAsync(
    new CreateClassificationPolicyOptions("policy-1")
    {
        WorkerSelectorAttachments =
        {
            new ConditionalRouterWorkerSelectorAttachment(
                condition: new ExpressionRouterRule("job.Urgent = true"),
                workerSelectors: new List<RouterWorkerSelector>
                {
                    new(key: "Foo", labelOperator: LabelOperator.Equal, value: new RouterValue("Bar"))
                })
        }
    });
await client.path("/routing/classificationPolicies/{classificationPolicyId}", "policy-1").patch({
    body: {
        workerSelectorAttachments: [{
            kind: "conditional",
            condition: { kind: "expression", expression: "job.Urgent = true" },
            workerSelectors: [{ key: "Foo", labelOperator: "equal", value: "Bar" }]
        }]
    },
    contentType: "application/merge-patch+json"
});
administration_client.upsert_classification_policy(
    classification_policy_id = "policy-1",
    worker_selector_attachments = [
        ConditionalWorkerSelectorAttachment(
            condition = ExpressionRouterRule(expression = "job.Urgent = true"),
            worker_selectors = [
                RouterWorkerSelector(key = "Foo", label_operator = LabelOperator.EQUAL, value = "Bar")
            ]
        )
    ])
administrationClient.createClassificationPolicy(new CreateClassificationPolicyOptions("policy-1")
    .setWorkerSelectorAttachments(List.of(new ConditionalRouterWorkerSelectorAttachment(
        new ExpressionRouterRule("job.Urgent = true"),
        List.of(new RouterWorkerSelector("Foo", LabelOperator.EQUAL, new RouterValue("Bar")))))));

Załączniki przekazywane

W tym przykładzie zasady klasyfikacji są skonfigurowane do dołączania selektora procesów roboczych ("Foo" = "<value comes from "Foo" label of the job>") do zadania.

await administrationClient.CreateClassificationPolicyAsync(
    new CreateClassificationPolicyOptions("policy-1")
    {
        WorkerSelectorAttachments =
        {
            new PassThroughWorkerSelectorAttachment(key: "Foo", labelOperator: LabelOperator.Equal)
        }
    });
await client.path("/routing/classificationPolicies/{classificationPolicyId}", "policy-1").patch({
    body: {
        workerSelectorAttachments: [{ kind: "passThrough", key: "Foo", labelOperator: "equal" }]
    },
    contentType: "application/merge-patch+json"
});
administration_client.upsert_classification_policy(
    classification_policy_id = "policy-1",
    worker_selector_attachments = [
        PassThroughWorkerSelectorAttachment(
            key = "Foo", label_operator = LabelOperator.EQUAL, value = "Bar")
    ])
administrationClient.createClassificationPolicy(new CreateClassificationPolicyOptions("policy-1")
    .setWorkerSelectorAttachments(List.of(new PassThroughWorkerSelectorAttachment("Foo", LabelOperator.EQUAL))));

Załączniki alokacji ważonej

W tym przykładzie zasady klasyfikacji są konfigurowane z załącznikiem alokacji ważonej. Te zasady dzielą zadania zgodnie z określonymi wagami i odpowiednio dołączają różne selektory. W tym miejscu 30% miejsc pracy powinno przejść do pracowników z etykietą Vendor ustawioną na A , a 70% powinno przejść do pracowników z etykietą Vendor ustawioną na B.

await administrationClient.CreateClassificationPolicyAsync(new CreateClassificationPolicyOptions("policy-1")
    {
        WorkerSelectorAttachments =
        {
            new WeightedAllocationWorkerSelectorAttachment(new List<WorkerWeightedAllocation>
            {
                new (weight: 0.3, workerSelectors: new List<RouterWorkerSelector>
                {
                    new (key: "Vendor", labelOperator: LabelOperator.Equal, value: new RouterValue("A"))
                }),
                new (weight: 0.7, workerSelectors: new List<RouterWorkerSelector>
                {
                    new (key: "Vendor", labelOperator: LabelOperator.Equal, value: new RouterValue("B"))
                })
            })
        }
    });
await client.path("/routing/classificationPolicies/{classificationPolicyId}", "policy-1").patch({
    body: {
        workerSelectorAttachments: [{
            kind: "weightedAllocation",
            allocations: [
            { 
                weight: 0.3,
                workerSelectors: [{ key: "Vendor", labelOperator: "equal", value: "A" }]
            },
            { 
                weight: 0.7,
                workerSelectors: [{ key: "Vendor", labelOperator: "equal", value: "B" }]
            }]
        }]
    },
    contentType: "application/merge-patch+json"
});
administration_client.upsert_classification_policy(
    classification_policy_id = "policy-1",
    worker_selector_attachments = [ 
        WeightedAllocationWorkerSelectorAttachment(allocations = [
            WorkerWeightedAllocation(weight = 0.3, worker_selectors = [
                RouterWorkerSelector(key = "Vendor", label_operator = LabelOperator.EQUAL, value = "A")
            ]),
            WorkerWeightedAllocation(weight = 0.7, worker_selectors = [
                RouterWorkerSelector(key = "Vendor", label_operator = LabelOperator.EQUAL, value = "B")
            ])
        ])
    ])
administrationClient.createClassificationPolicy(new CreateClassificationPolicyOptions("policy-1")
    .setWorkerSelectorAttachments(List.of(new WeightedAllocationWorkerSelectorAttachment(
        List.of(new WorkerWeightedAllocation(0.3, List.of(
            new RouterWorkerSelector("Vendor", LabelOperator.EQUAL, new RouterValue("A")),
            new RouterWorkerSelector("Vendor", LabelOperator.EQUAL, new RouterValue("B"))
        )))))));

Ponowne sklasyfikowanie zadania po przesłaniu

Po odebraniu i sklasyfikowaniu zadania przy użyciu zasad routera zadań można go ponownie sklasyfikować przy użyciu zestawu SDK. Poniższy przykład ilustruje jeden ze sposobów zwiększania priorytetu zadania na 10, po prostu określając identyfikator zadania, wywołując metodę i aktualizując identyfikator klasyfikacjiPolicyId i dołączając UpdateJobAsync etykietęHardware_VIP.

await client.UpdateJobAsync(new RouterJob("job1") {
    ClassificationPolicyId = classificationPolicy.Value.Id,
    Labels = { ["Hardware_VIP"] = new RouterValue(true) }});
var job = await client.path("/routing/jobs/{jobId}", "job1").patch({
    body: {
        classificationPolicyId: classificationPolicy.body.id,
        labels: { Hardware_VIP: true }
    },
    contentType: "application/merge-patch+json"
});
client.upsert_job(
    job_id = "job1",
    classification_policy_id = classification_policy.id,
    labels = { "Hardware_VIP": True }
)
client.updateJob(new RouterJob("job1")
    .setClassificationPolicyId(classificationPolicy.getId())
    .setLabels(Map.of("Hardware_VIP", new RouterValue(true))));

Uwaga

Jeśli zostaną zaktualizowane etykiety zadań, identyfikator kolejki, identyfikator channelId lub selektory procesów roboczych, wszystkie istniejące oferty w zadaniu zostaną odwołane i otrzymasz zdarzenie RouterWorkerOfferRevoked dla każdej oferty z usługi EventGrid. Zadanie jest ponownie kolejkowane i otrzymujesz zdarzenie RouterJobQueued . Oferty zadań można również odwołać, gdy łączna pojemność procesu roboczego zostanie zmniejszona lub kanały zostaną zaktualizowane.