public function doWork($ignoreErrors = false)
{
declare (ticks=1);
set_time_limit(0);
# Check if we are using Fork1.0 (php < 7)
if (class_exists('duncan3dc\\Helpers\\Fork')) {
$fork = new \duncan3dc\Helpers\Fork();
$fork->ignoreErrors = $ignoreErrors;
} else {
$fork = new Fork();
}
foreach ($this->workers as $tube => $worker) {
$that = clone $this;
// Run the worker in separate process.
$fork->call(function () use($tube, $worker, $that, $fork, $ignoreErrors) {
$that->connect();
do {
$job = $that->reserveFromTube($tube);
if ($job && $job instanceof Job) {
$fork->call(function () use($worker, $job) {
call_user_func($worker, $job);
});
try {
$fork->wait();
try {
$job->delete();
} catch (\Exception $e) {
if (null !== $this->logger) {
$this->logger->warning(sprintf('Exception thrown while deleting the job: %d — %s', $e->getCode(), $e->getMessage()));
}
}
} catch (\Exception $e) {
if (null !== $this->logger) {
$this->logger->warning(sprintf('Exception thrown while handling job #%s: %d — %s', $job->getId(), $e->getCode(), $e->getMessage()));
}
if (!$ignoreErrors) {
return;
}
}
} else {
// There is no jobs so let's sleep to not increase CPU usage
usleep(rand(7000, 10000));
}
} while (true);
exit(0);
});
}
try {
$fork->wait();
} catch (ForkException $e) {
if (!$ignoreErrors) {
throw $e;
}
}
}
/** * @depends testShouldGetTubes */ public function testShouldDoWork() { if (!class_exists('\\duncan3dc\\Helpers\\Fork')) { $this->markTestSkipped(sprintf('%s used as a dependency \\duncan3dc\\Helpers\\Fork. You can install it by using' . 'composer require "duncan3dc/fork-helper":"*"', get_class($this->client))); } $expected = ['test-tube-1' => '1', 'test-tube-2' => '2']; foreach ($expected as $tube => $value) { $this->client->addWorker($tube, function (Job $job) { // Store string "test-tube-%JOB_BODY%" in shared memory $memory = shmop_open($this->shmKey, 'c', 0644, $this->shmLimit); $output = trim(shmop_read($memory, 0, $this->shmLimit)); $output .= sprintf("\ntest-tube-%s", $job->getBody()); shmop_write($memory, $output, 0); shmop_close($memory); exit(1); }); $this->client->putInTube($tube, $value); } $this->client->doWork(); $memory = shmop_open($this->shmKey, 'a', 0, 0); $output = shmop_read($memory, 0, $this->shmLimit); $this->assertTrue(shmop_delete($memory)); shmop_close($memory); $this->assertNotEmpty($output); // Compare number of items in expected list with lines in shared memory $this->assertEquals(count($expected), count(array_unique(explode("\n", trim($output))))); }