Come personalizzare la classificazione dei ruoli di lavoro per la migliore modalità di distribuzione del ruolo di lavoro
La best-worker
modalità di distribuzione seleziona i ruoli di lavoro che sono in grado di gestire prima il processo. La logica per classificare i ruoli di lavoro può essere personalizzata, con un'espressione o una funzione di Azure per confrontare due ruoli di lavoro. L'esempio seguente illustra come personalizzare questa logica con una funzione di Azure personalizzata.
Scenario: regola di assegnazione dei punteggi personalizzata in modalità di distribuzione del ruolo di lavoro ottimale
Si vogliono distribuire offerte tra i ruoli di lavoro associati a una coda. Ai ruoli di lavoro verrà assegnato un punteggio in base alle etichette e al set di competenze. Il ruolo di lavoro con il punteggio più alto dovrebbe ottenere la prima offerta (modalità di distribuzione BestWorker).
Situazione
- È stato creato e classificato un processo.
- Al processo sono associate le etichette seguenti
- ["CommunicationType"] = "Chat"
- ["IssueType"] = "XboxSupport"
- ["Language"] = "en"
- ["HighPriority"] = true
- ["SubIssueType"] = "ConsoleMalfunction"
- ["ConsoleType"] = "XBOX_edizione StandardRIES_X"
- ["Model"] = "XBOX_edizione StandardRIES_X_1TB"
- Al processo sono associati i seguenti WorkerSelectors
- ["Inglese"] >= 7
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- Al processo sono associate le etichette seguenti
- Il processo è attualmente in stato "In coda", accodato nella coda di supporto hardware Xbox in attesa di corrispondere a un ruolo di lavoro.
- Più lavoratori diventano disponibili contemporaneamente.
- Il ruolo di lavoro 1 è stato creato con le etichette seguenti
- ["HighPrioritySupport"] = true
- ["HardwareSupport"] = true
- ["Support_XBOX_edizione StandardRIES_X"] = true
- ["English"] = 10
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- Il ruolo di lavoro 2 è stato creato con le etichette seguenti
- ["HighPrioritySupport"] = true
- ["HardwareSupport"] = true
- ["Support_XBOX_edizione StandardRIES_X"] = true
- ["Support_XBOX_edizione StandardRIES_S"] = true
- ["English"] = 8
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- Il ruolo di lavoro 3 è stato creato con le etichette seguenti
- ["HighPrioritySupport"] = false
- ["HardwareSupport"] = true
- ["Support_XBOX"] = true
- ["English"] = 7
- ["ChatSupport"] = true
- ["XboxSupport"] = true
- Il ruolo di lavoro 1 è stato creato con le etichette seguenti
Aspettativa
Quando si classificano i ruoli di lavoro per selezionare il ruolo di lavoro che ottiene la prima offerta, è consigliabile eseguire il comportamento seguente.
Il flusso decisionale (come illustrato in precedenza) è il seguente:
Se un processo non è HighPriority:
- Ruoli di lavoro con etichetta: ["Support_XBOX"] = true; ottenere un punteggio pari a 100
- In caso contrario, ottenere un punteggio pari a 1
Se un processo è HighPriority:
- Ruoli di lavoro con etichetta: ["HighPrioritySupport"] = false; ottenere un punteggio pari a 1
- In caso contrario, se ["HighPrioritySupport"] = true:
- Ruolo di lavoro specializzato nel tipo di> console: il ruolo di lavoro è etichetta: ["Support_<jobLabels.ConsoleType>"] = true? Se true, il ruolo di lavoro ottiene il punteggio 200
- In caso contrario, ottenere un punteggio pari a 100
Creazione di una funzione di Azure
Prima di procedere ulteriormente nel processo, si definirà prima di tutto una funzione di Azure che assegna punteggi al ruolo di lavoro.
Nota
La funzione di Azure seguente usa JavaScript. Per altre informazioni, vedere Avvio rapido: Creare una funzione JavaScript in Azure con Visual Studio Code
Input di esempio per Worker 1
{
"job": {
"CommunicationType": "Chat",
"IssueType": "XboxSupport",
"Language": "en",
"HighPriority": true,
"SubIssueType": "ConsoleMalfunction",
"ConsoleType": "XBOX_SERIES_X",
"Model": "XBOX_SERIES_X_1TB"
},
"selectors": [
{
"key": "English",
"operator": "GreaterThanEqual",
"value": 7,
"expiresAfterSeconds": null
},
{
"key": "ChatSupport",
"operator": "Equal",
"value": true,
"expiresAfterSeconds": null
},
{
"key": "XboxSupport",
"operator": "Equal",
"value": true,
"expiresAfterSeconds": null
}
],
"worker": {
"Id": "e3a3f2f9-3582-4bfe-9c5a-aa57831a0f88",
"HighPrioritySupport": true,
"HardwareSupport": true,
"Support_XBOX_SERIES_X": true,
"English": 10,
"ChatSupport": true,
"XboxSupport": true
}
}
Implementazione di esempio:
module.exports = async function (context, req) {
context.log('Best Worker Distribution Mode using Azure Function');
let score = 0;
const jobLabels = req.body.job;
const workerLabels = req.body.worker;
const isHighPriority = !!jobLabels["HighPriority"];
context.log('Job is high priority? Status: ' + isHighPriority);
if(!isHighPriority) {
const isGenericXboxSupportWorker = !!workerLabels["Support_XBOX"];
context.log('Worker provides general xbox support? Status: ' + isGenericXboxSupportWorker);
score = isGenericXboxSupportWorker ? 100 : 1;
} else {
const workerSupportsHighPriorityJob = !!workerLabels["HighPrioritySupport"];
context.log('Worker provides high priority support? Status: ' + workerSupportsHighPriorityJob);
if(!workerSupportsHighPriorityJob) {
score = 1;
} else {
const key = `Support_${jobLabels["ConsoleType"]}`;
const workerSpecializeInConsoleType = !!workerLabels[key];
context.log(`Worker specializes in consoleType: ${jobLabels["ConsoleType"]} ? Status: ${workerSpecializeInConsoleType}`);
score = workerSpecializeInConsoleType ? 200 : 100;
}
}
context.log('Final score of worker: ' + score);
context.res = {
// status: 200, /* Defaults to 200 */
body: score
};
}
Output per worker 1
200
Con l'implementazione indicata in precedenza, per il processo specificato si otterranno i punteggi seguenti per i lavoratori:
Lavoro | Punteggio |
---|---|
Ruolo di lavoro 1 | 200 |
Ruolo di lavoro 2 | 200 |
Ruolo di lavoro 3 | 1 |
Distribuire le offerte in base alla migliore modalità di lavoro
Ora che l'app per le funzioni di Azure è pronta, è possibile creare un'istanza della modalità BestWorkerDistribution usando Router SDK.
var administrationClient = new JobRouterAdministrationClient("<YOUR_ACS_CONNECTION_STRING>");
// Setup Distribution Policy
var distributionPolicy = await administrationClient.CreateDistributionPolicyAsync(
new CreateDistributionPolicyOptions(
distributionPolicyId: "BestWorkerDistributionMode",
offerExpiresAfter: TimeSpan.FromMinutes(5),
mode: new BestWorkerMode(scoringRule: new FunctionRouterRule(new Uri("<insert function url>")))
) { Name = "XBox hardware support distribution" });
// Setup Queue
var queue = await administrationClient.CreateQueueAsync(
new CreateQueueOptions(
queueId: "XBox_Hardware_Support_Q",
distributionPolicyId: distributionPolicy.Value.Id
) { Name = "XBox Hardware Support Queue" });
// Create workers
var worker1 = await client.CreateWorkerAsync(new CreateWorkerOptions(workerId: "Worker_1", capacity: 100)
{
Queues = { queue.Value.Id },
Channels = { new RouterChannel(channelId: "Xbox_Chat_Channel", capacityCostPerJob: 10) },
Labels =
{
["English"] = new RouterValue(10),
["HighPrioritySupport"] = new RouterValue(true),
["HardwareSupport"] = new RouterValue(true),
["Support_XBOX_SERIES_X"] = new RouterValue(true),
["ChatSupport"] = new RouterValue(true),
["XboxSupport"] = new RouterValue(true)
}
});
var worker2 = await client.CreateWorkerAsync(new CreateWorkerOptions(workerId: "Worker_2", capacity: 100)
{
Queues = { queue.Value.Id },
Channels = { new RouterChannel(channelId: "Xbox_Chat_Channel", capacityCostPerJob: 10) },
Labels =
{
["English"] = new RouterValue(8),
["HighPrioritySupport"] = new RouterValue(true),
["HardwareSupport"] = new RouterValue(true),
["Support_XBOX_SERIES_X"] = new RouterValue(true),
["ChatSupport"] = new RouterValue(true),
["XboxSupport"] = new RouterValue(true)
}
});
var worker3 = await client.CreateWorkerAsync(new CreateWorkerOptions(workerId: "Worker_3", capacity: 100)
{
Queues = { queue.Value.Id },
Channels = { new RouterChannel(channelId: "Xbox_Chat_Channel", capacityCostPerJob: 10) },
Labels =
{
["English"] = new RouterValue(7),
["HighPrioritySupport"] = new RouterValue(true),
["HardwareSupport"] = new RouterValue(true),
["Support_XBOX_SERIES_X"] = new RouterValue(true),
["ChatSupport"] = new RouterValue(true),
["XboxSupport"] = new RouterValue(true)
}
});
// Create Job
var job = await client.CreateJobAsync(
new CreateJobOptions(jobId: "job1", channelId: "Xbox_Chat_Channel", queueId: queue.Value.Id)
{
Priority = 100,
ChannelReference = "ChatChannel",
RequestedWorkerSelectors =
{
new RouterWorkerSelector(key: "English", labelOperator: LabelOperator.GreaterThanEqual, value: new RouterValue(7)),
new RouterWorkerSelector(key: "ChatSupport", labelOperator: LabelOperator.Equal, value: new RouterValue(true)),
new RouterWorkerSelector(key: "XboxSupport", labelOperator: LabelOperator.Equal, value: new RouterValue(true))
},
Labels =
{
["CommunicationType"] = new RouterValue("Chat"),
["IssueType"] = new RouterValue("XboxSupport"),
["Language"] = new RouterValue("en"),
["HighPriority"] = new RouterValue(true),
["SubIssueType"] = new RouterValue("ConsoleMalfunction"),
["ConsoleType"] = new RouterValue("XBOX_SERIES_X"),
["Model"] = new RouterValue("XBOX_SERIES_X_1TB")
}
});
// Wait a few seconds and see which worker was matched
await Task.Delay(TimeSpan.FromSeconds(5));
var getJob = await client.GetJobAsync(job.Value.Id);
Console.WriteLine(getJob.Value.Assignments.Select(assignment => assignment.Value.WorkerId).First());
Output
Worker_1 // or Worker_2
Since both workers, Worker_1 and Worker_2, get the same score of 200,
the worker who has been idle the longest will get the first offer.