Compartilhar via


Classificando um trabalho

Saiba como usar uma política de classificação no JobRouter para resolver dinamicamente a fila e a prioridade ao anexar seletores de trabalhador a um Trabalho.

Pré-requisitos

Criar uma política de classificação

O exemplo a seguir aproveita o PowerFx Expressions para selecionar a fila e a prioridade. A expressão tenta corresponder ao rótulo Job chamado Region igual a NA resultando no Job sendo colocado no XBOX_NA_QUEUE. Caso contrário, o trabalho será enviado para a fila XBOX_DEFAULT_QUEUE de fallback, conforme definido pelo fallbackQueueId. Além disso, a prioridade é 10 se um rótulo chamado Hardware_VIP foi correspondido, caso contrário, é 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)")));

Enviar o trabalho

O exemplo a seguir faz com que a política de classificação avalie os rótulos de trabalho. O resultado coloca o Trabalho na fila chamada XBOX_NA_QUEUE e define a prioridade como 1. Antes que a política de classificação seja avaliada, o estado do trabalho é pendingClassification. Depois que a política de classificação é avaliada, o estado do trabalho é atualizado para 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)
    )));

Anexando seletores de trabalhadores

Você pode usar a política de classificação para anexar mais seletores de trabalho a um trabalho.

Anexos estáticos

Neste exemplo, a Política de Classificação é configurada com um anexo estático, que sempre anexa o seletor de rótulo especificado a um trabalho.

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"))))));

Anexos condicionais

Neste exemplo, a Política de Classificação é configurada com um anexo condicional. Assim, ele avalia uma condição em relação aos rótulos de trabalho para determinar se os referidos seletores de rótulos devem ser anexados ao trabalho.

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")))))));

Anexos de passagem

Neste exemplo, a Política de Classificação é configurada para anexar um seletor de trabalho ("Foo" = "<value comes from "Foo" label of the job>") ao trabalho.

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

Anexos de alocação ponderada

Neste exemplo, a Política de Classificação é configurada com um anexo de alocação ponderada. Esta política divide os trabalhos de acordo com as ponderações especificadas e atribui diferentes selectores em conformidade. Aqui, 30% dos trabalhos devem ir para trabalhadores com o rótulo Vendor definido como A e 70% devem ir para trabalhadores com o rótulo Vendor definido como 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"))
        )))))));

Reclassificar um trabalho após o envio

Depois que o JobRouter tiver recebido e classificado um Trabalho usando uma política, você terá a opção de reclassificá-lo usando o SDK. O exemplo a seguir ilustra uma maneira de aumentar a prioridade do Job para 10, simplesmente especificando o Job ID, chamando o método e atualizando o classificationPolicyId e incluindo o UpdateJobAsyncHardware_VIP rótulo.

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

Observação

Se os rótulos de trabalho, queueId, channelId ou seletores de trabalho forem atualizados, todas as ofertas existentes no trabalho serão revogadas e você receberá um evento RouterWorkerOfferRevoked para cada oferta do EventGrid. O trabalho é enfileirado novamente e você recebe um evento RouterJobQueued . As ofertas de emprego também podem ser revogadas quando a capacidade total de um trabalhador é reduzida ou os canais são atualizados.