Symfony Tasks wait for multiple tasks - php

I'm starting 10 processes asynchronously:
$procs = [];
for($i = 0; $i < 10; $i++) {
$proc = new Process('ls -lsa');
$proc->start();
$procs[$i] = $proc;
}
Now i want to wait asynchronous for every process to finish and print out state informations while waiting:
foreach($procs as $proc) {
$proc->wait(function ($type, $buffer) {
if (Process::ERR === $type) {
// Print out error ...
} else {
// Print out state informations ...
});
}
}
The Problem is at the wait function. It waits for the task to finish and then go on to the next tasks. But i want this to run asynchronous.
How can i do this?
Thanks !

As per the Symfony docs the wait method is blocking and therefore will wait until that process is finished before continuing.
If you don't want to wait you could refactor your code to use the run method:
for($i = 0; $i < 10; $i++) {
$process = new Process('ls -lsa');
$process->run(function ($type, $buffer) {
if (Process::ERR === $type) {
echo 'ERR > '.$buffer;
} else {
echo 'OUT > '.$buffer;
}
});
$procs[$i] = $proc;
}

Related

Pausing PHP process via command line

I am running this via the command line. When the loop is running, is there any way I can pause the execution of the code? Ideal case would be that I could press a key to pause and then another key to resume. If I don't press the pause key then the loop continues until $i == 1000
<?php
echo "How long should the code sleep between increments?\n";
echo ">> ";
$sleep = trim(fgets(STDIN));
for ($i = 1; $i <= 1000; $i++) {
echo "$i\n";
sleep($sleep);
}
This is a heavily simplified example of my actual need for the code.
I don't sure my code is best solution or not but it work.
function checkResume()
{
$r = false;
while (!$r) {
if (fgets(STDIN) == "r") {
$r = true;
}
}
}
function checkPause()
{
$input = fgets(STDIN);
if (!empty($input) && $input == "p") {
return true;
}
return false;
}
echo "How long should the code sleep between increments?\n";
echo ">> ";
$sleep = trim(fgets(STDIN));
echo "\nStart ...\n";
stream_set_blocking(STDIN, false);
for ($i = 1; $i <= 1000; $i++) {
if (checkPause()) {
echo "wait for resume \n";
checkResume();
}
echo "$i\n";
sleep($sleep);
}
Hope this help.

Foreach code working - but asking for optimalization

The below code works and does output exactly what i want. I made a foreach loop getting the values of a specific field ($CustomFields...) which is part of a framework variable. Then is only counts that field when the condition is "group".
After that i want to het the average price of all fields / count.
// ########### Get average hourly rate for group classes
$itemsperhour = array();
$countperhour = 0;
foreach($listings as $listing) {
if ($CustomFields->fieldValue('jr_typeoflesson',$listing,false,false) == 'group') {
$itemsperhour[] = $CustomFields->field('jr_hourlyrateus',$listing,false,false);
$countperhour = $countperhour + 1;
}
}
//print_r($items);
if ($countperhour > 0) {
$totalperhour = array_sum($itemsperhour);
$averageperhour =($totalperhour / $countperhour);
echo round($averageperhour,2);
} else {
echo "No data";
}
unset ($averageperhour);
As said, the snippet works. But may I ask how other people would write such a script related to optimise such a piece of code (for speed and readability?
PHP 5.6+
Jasper
Below is one way of optimizing:
$totalperhour = 0;
$countperhour = 0;
foreach($listings as $listing) {
if ($CustomFields->fieldValue('jr_typeoflesson',$listing,false,false) == 'group') {
$totalperhour += $CustomFields->field('jr_hourlyrateus',$listing,false,false);
$countperhour = $countperhour + 1;
}
}
if($countperhour > 0) {
$averageperhour =($totalperhour / $countperhour);
echo round($averageperhour,2);
$averageperhour = '';
} else {
echo "No data";
}
I would suppose to use array_reduce function for getting the average:
$averageperhour = array_reduce($listings, function($average, $listing) use (&$CustomFields)
{
static $sum = 0;
static $counter = 0;
if ($CustomFields->fieldValue('jr_typeoflesson', $listing, false, false) == 'group') {
$sum += $CustomFields->field('jr_hourlyrateus', $listing, false, false);
$counter ++;
$average = round(($sum / $counter), 2);
}
return $average;
}, 'No data');
echo $averageperhour;
Not sure about speed improvement (needs testing), but this variant seems to me like more readable.
How about this?
$itemsPerHour = [];
foreach($listings as $listing) {
if ($CustomFields->fieldValue('jr_typeoflesson', $listing, false, false) !== 'group') {
continue;
}
$itemsPerHour[] = $CustomFields->field('jr_hourlyrateus', $listing, false, false);
}
$countPerHour = count($itemsPerHour);
if ($countPerHour > 0) {
$averagePerHour = array_sum($itemsPerHour) / $countPerHour;
echo round($averagePerHour,2);
} else {
echo "No data";
}

PHP pthreads can't kill thread (& timeout realization)

I have an example code. What it does is visiting pages. I want to make timeout for thread execution and shut it down when it hangs too long. I thought that there is built-in methods to implement that. Also, i've tried to do it by my own with time() function. But there is another problem. At this point $workers[$i]->kill(); script hangs and kill() method returns false so i can't shutdown thread by force. What is happening and what am i doing wrong?
Thank you!
<?php
/**
* Author: Abu Ashraf Masnun
* URL: http://masnun.me
*/
//define("TMT",3);
class WorkerThreads extends Thread
{
private $workerId;
public function __construct($string)
{
$this->command_string = trim($string);
}
public function run()
{
echo $this->command_string." ".Thread::getCurrentThreadId()."\n";
//sleep(rand(0, 3));
$str = "C:\\Users\\Alex\\Desktop\\2web\\phantom\\phantomjs.exe C:\\Users\\Alex\\Desktop\\2web\\test.js ";
$url = $this->command_string;
$d = explode("://",$url);
$ex_str = $str." ".$url." > ".$d[1].".html";
//$ex_str = $str." ".$url;
//echo $ex_str;
//$ex_str = escapeshellarg($ex_str);
//echo $ex_str;
exec($ex_str, $out);
//print_r($out);
}
}
//$data = file('sites.txt');
$data_f = file('sites_x.txt');
print_r($data_f);
$data = array();
$data_size = count($data_f);
for($i = 0;$i<$data_size;$i++)
{
$info = explode(";",trim($data_f[$i]));
if($info[1] === 'y')
continue;
$data[] = $info[0];
}
print_r($data);
$data_size = count($data);
// Worker pool
$workers = [];
$t_count = 4;
$flag = 1;
$k = 0;
//echo "$data_size";
while($flag === 1)
{
/*
//echo "$k\n";
if($k >= $data_size)
{
//echo "111"; exit();
$flag = 0;
break 2;
}
*/
$c_w = count($workers);
if($c_w < $t_count)
{
for($i = $c_w; $i<$t_count - $c_w;$i++)
{
if($k >= $data_size)
{
$flag = 0;
break;
}
$workers[$i] = new WorkerThreads($data[$k]);
//echo $data[$k]."\n";
echo "worker $i started\n";
$workers[$i]->start();
$k++;
}
}
$c_w = count($workers);
for($i=0;$i<$c_w;$i++)
{
$workers[$i]->kill();
unset($workers[$i]);
echo "unset $i\n";
//var_dump($workers[$i]->isTerminated(), $workers[$i]->getTerminationInfo());
/*
if($workers[$i]->join())
{
//var_dump($workers[$i]->isTerminated(), $my->getTerminationInfo());
echo "joining $i\n";
unset($workers[$i]);
}
*/
}
}
?>
I ran into this problem today with pthreads 2.0.10.
After recompiling PHP from source to get ZTS support, I tried building pthreads (phpize, configure, make). Everything seemed OK until I ran make test. killed-info test failed after a 30 second timeout.
Solution for me was to compile the latest pthreads from the master branch on github.

How to start and end new php procces?

I am trying to use a pcntl extetntion for PHP to run some methods of my CLI class in a new thread. I wrote a small test method:
private function startProcess($data)
{
$this->log('Start a child process');
$pid = pcntl_fork();
if($pid == -1)
$this->log('Could not fork');
elseif($pid)
pcntl_wait($status);
else {
$this->process($data);
sleep(10);
posix_kill(posix_setsid(), SIGTERM);
}
}
This method is called 10 times. $this->process($data); just prints the data in the console. As i understood it should start 10 processes and print my data, after it exit. But instead i get to wait 10 seconds for each message. Where i'm wrong?
You are waiting for each process to complete immediately after starting it. If you really want to run 10 at a time, don't wait until you started all 10.
for($i = 0; $i < 10; $i++)
startProcess(...);
for($i = 0; $i < 10; $i++)
pcntl_wait($status);
private function startProcess($data)
{
$this->log('Start a child process');
$pid = pcntl_fork();
if($pid == -1)
$this->log('Could not fork');
elseif(!$pid) {
$this->process($data);
sleep(10);
posix_kill(posix_setsid(), SIGTERM);
}
}

PHP pinging, even 1 request timeout

I have been using the script below, however, I want it to ping 3-4 times, and within that 3-4 times if it has even a single request timeout, I want php to come back as failed.
Here's a script I'm using:
<?php
function pingAddressHasNeverFailed($tries) {
for ($i = 0; $i < $tries; $i++) {
$pingresult = shell_exec("ping -c 1 www.google.com", $outcome, $status);
if ($status != 0)
return false;
}
return true;
}
if (pingAddressHasNeverFailed(3)) {
echo "uoc gi";
}
?>
Please help if you can, thank you so much in advance!
If any ping fails (in a set) it will not have 0% in the output (i.e. 0% packet loss), which is the same for Linux and Windows:
function ping($host, $times = 3)
{
exec("/bin/ping -c 3 $host", $out, $status);
return $status === 0 && false !== strpos(join('', $out), '0%');
}
if (ping('www.google.com)) {
echo "yay\n";
} else {
echo "oh dear\n";
}
You may have to adjust the ping arguments to fit your environment and make sure that the host name is sanitized.
In that case you'll need to execute command n (n is a number of tries) times. E.g.:
function pingAddressHasNeverFailed($tries) {
$outcome = array();
$status = -1;
for ($i = 0; $i < $tries; $i++) {
$pingresult = exec("/bin/ping -n 1 www.google.com", $outcome, $status);
if ($status != 0)
return false;
}
return true;
}
Usage:
if (pingAddressHasNeverFailed(3)) {
//do something useful
}

Categories