PHP 8.4.6 Released!

GearmanClient::addTaskBackground

(PECL gearman >= 0.5.0)

GearmanClient::addTaskBackgroundAdiciona uma tarefa em segundo plano para ser executada em paralelo

Descrição

public GearmanClient::addTaskBackground(
    string $function_name,
    string|int|float $workload,
    mixed $context = null,
    ?string $unique_key = null
): GearmanTask|false

Adiciona uma tarefa em segundo plano para ser executada em paralelo com outras tarefas. Chame este método para todas as tarefas a serem executadas em paralelo, então chame GearmanClient::runTasks() para executar a tarefa.

Parâmetros

function_name

Uma função registrada que o trabalhador deve executar

workload

Dados serializados a serem processados

context

Contexto da aplicação para associar a uma tarefa

unique_key

Um identificador único usado para identificar uma tarefa específica

Valor Retornado

Um objeto GearmanTask ou false se a tarefa não pôde ser adicionada.

Exemplos

Exemplo #1 Duas tarefas, uma em segundo plano e outra não

Este exemplo ilustra a diferença entre executar uma tarefa em segundo plano e uma tarefa normal. O cliente adiciona duas tarefas para executar a mesma função, mas uma é adicionada com addTaskBackground(). Uma função de retorno é definida para que o progresso da tarefa possa ser rastreado. Um trabalhador simples com um atraso artificial relata o progresso da tarefa e o cliente pega isso por meio da função de retorno. Dois trabalhadores são executados para este exemplo. Observe que a tarefa em segundo plano não é exibida na saída do cliente.

<?php

# O script do cliente

# Cria o cliente gearman
$gmc= new GearmanClient();

# Adiciona o servidor de tarefa padrão
$gmc->addServer();

# Define algumas funções de retorno para que possamos monitorar o progresso
$gmc->setCompleteCallback("reverse_complete");
$gmc->setStatusCallback("reverse_status");

# Adiciona uma tarefa para a função "reverse"
$task= $gmc->addTask("reverse", "Hello World!", null, "1");

# Adiciona outra tarefa, mas esta para ser executada em segundo plano
$task= $gmc->addTaskBackground("reverse", "!dlroW olleH", null, "2");

if (!
$gmc->runTasks())
{
echo
"ERRO " . $gmc->error() . "\n";
exit;
}

echo
"PRONTO\n";

function
reverse_status($task)
{
echo
"STATUS: " . $task->unique() . ", " . $task->jobHandle() . " - " . $task->taskNumerator() .
"/" . $task->taskDenominator() . "\n";
}

function
reverse_complete($task)
{
echo
"CONCLUÍDO: " . $task->unique() . ", " . $task->data() . "\n";
}

?>
<?php

# O script do trabalhador

echo "Começando\n";

# Cria nosso objeto trabalhador.
$gmworker= new GearmanWorker();

# Adiciona servidor padrão (localhost).
$gmworker->addServer();

# Registra a função "reversa" com o servidor.
$gmworker->addFunction("reverse", "reverse_fn");

print
"Esperando tarefa...\n";
while(
$gmworker->work())
{
if (
$gmworker->returnCode() != GEARMAN_SUCCESS)
{
echo
"Código de retorno:" . $gmworker->returnCode() . "\n";
break;
}
}

function
reverse_fn($job)
{
echo
"Tarefa recebida: " . $job->handle() . "\n";

$workload = $job->workload();
$workload_size = $job->workloadSize();

echo
"Carga de trabalho: $workload ($workload_size)\n";

# Este laço de status não é necessário, apenas mostra como ele funciona
for ($x= 0; $x < $workload_size; $x++)
{
echo
"Status de envio: " . ($x + 1) . "/$workload_size concluído\n";
$job->sendStatus($x+1, $workload_size);
$job->sendData(substr($workload, $x, 1));
sleep(1);
}

$result= strrev($workload);
echo
"Resultado: $result\n";

# Retorna o que queremos enviar de volta ao cliente.
return $result;
}

?>

Worker output for two workers running:

Tarefa recebida: H:foo.local:65
Carga de trabalho: !dlroW olleH (12)
1/12 concluído
Tarefa recebida: H:foo.local:66
Carga de trabalho: Hello World! (12)
Status de envio: 1/12 concluído
Status de envio: 2/12 concluído
Status de envio: 2/12 concluído
Status de envio: 3/12 concluído
Status de envio: 3/12 concluído
Status de envio: 4/12 concluído
Status de envio: 4/12 concluído
Status de envio: 5/12 concluído
Status de envio: 5/12 concluído
Status de envio: 6/12 concluído
Status de envio: 6/12 concluído
Status de envio: 7/12 concluído
Status de envio: 7/12 concluído
Status de envio: 8/12 concluído
Status de envio: 8/12 concluído
Status de envio: 9/12 concluído
Status de envio: 9/12 concluído
Status de envio: 10/12 concluído
Status de envio: 10/12 concluído
Status de envio: 11/12 concluído
Status de envio: 11/12 concluído
Status de envio: 12/12 concluído
Status de envio: 12/12 concluído
Resultado: !dlroW olleH
Resultado: Hello World!

Client output:

STATUS: 1, H:foo.local:66 - 1/12
STATUS: 1, H:foo.local:66 - 2/12
STATUS: 1, H:foo.local:66 - 3/12
STATUS: 1, H:foo.local:66 - 4/12
STATUS: 1, H:foo.local:66 - 5/12
STATUS: 1, H:foo.local:66 - 6/12
STATUS: 1, H:foo.local:66 - 7/12
STATUS: 1, H:foo.local:66 - 8/12
STATUS: 1, H:foo.local:66 - 9/12
STATUS: 1, H:foo.local:66 - 10/12
STATUS: 1, H:foo.local:66 - 11/12
STATUS: 1, H:foo.local:66 - 12/12
CONCLUÍDO: 1, !dlroW olleH
PRONTO

Veja Também

adicione uma nota

Notas Enviadas por Usuários (em inglês) 3 notes

up
18
Anonymous
9 years ago
It is unlikely this example works quite as advertised.

The foreground job will block, however the background job should not.. (and if it does that's not documented Gearman behaviour far as I know and would not make sense for a Background job).

So, if the foreground job completes, then we would expect runTasks() to return at that moment, regardless of the status of the background job(s). With nothing else to do, the php script (the client) in this example would exit at that point.

To fully-utilize background jobs, it's reasonable to assume that we still wish to know their status. To do that, you need a polling loop that "checks up on them" and waits until their completion.

That eliminates the point of background jobs of course - because the client would still be Blocking (in a polling loop) more or less occupied, and unable to exit/finish.

So, in practice, background jobs mean you are decoupled from the client upon execution (because the main point is to free up the client, otherwise just use foreground execution), which means the client is likely going to exit, meaning the jobs themselves should be reporting their status and final result independently, not leaving it up to the client.

It's a significantly different setup compared to foreground jobs. In fact this example is kind of silly to even mix the two.

Nobody will ever see this post, because apparently nobody in the world has ever commented on the php gearman client, but it's a good post never the less.
up
2
iunknowvb at gmail dot com
7 years ago
function run_process($cmd,$outputFile = '/dev/null', $append = false){
$pid=0;
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
$cmd = 'wmic process call create "'.$cmd.'" | find "ProcessId"';
$handle = popen("start /B ". $cmd, "r");
$read = fread($handle, 200); //Read the output
$pid=substr($read,strpos($read,'=')+1);
$pid=substr($pid,0,strpos($pid,';') );
$pid = (int)$pid;
pclose($handle); //Close
}else{
$pid = (int)shell_exec(sprintf('%s %s %s 2>&1 & echo $!', $cmd, ($append) ? '>>' : '>', $outputFile));
}
return $pid;
}
function is_process_running($pid){
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
//tasklist /FI "PID eq 6480"
$result = shell_exec('tasklist /FI "PID eq '.$pid.'"' );
if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
return true;
}
}else{
$result = shell_exec(sprintf('ps %d 2>&1', $pid));
if (count(preg_split("/\n/", $result)) > 2 && !preg_match('/ERROR: Process ID out of range/', $result)) {
return true;
}
}
return false;
}
function stop_process($pid){
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
$result = shell_exec('taskkill /PID '.$pid );
if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
return true;
}
}else{
$result = shell_exec(sprintf('kill %d 2>&1', $pid));
if (!preg_match('/No such process/', $result)) {
return true;
}
}
}
$cmd='';
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
$cmd= $php_path.'\php.exe '.$path.'\long_process.php' ;
}else{
$cmd='/usr/bin/php -f /var/www/example.com/public/long_process.php';
}

$pid=run_process($cmd);
up
-2
raitech at gmail dot com
9 years ago
This method seems only useful when you doesn't need to know something about the worker, when you can let runTasks() finishes its code and destroy the GearmanClient object without a problem.

If you need to get data from worker via callbacks, forget it after runTasks() finishes.

You have to block your execution in the GearmanClient "main loop", so it can call the callbacks. It seems that runTasks() is that "main loop".
To Top