/**
  * @inheritdoc
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->input = $input;
     $this->output = $output;
     $passwd = new Passwd();
     $users = $passwd->getUsersByGroup($input->getOption("group"));
     $pools = $this->divideUsersIntoPools($users);
     $fork = new duncan3dc\Helpers\Fork();
     foreach ($pools as $pool) {
         $fork->call(function () use($pool) {
             foreach ($pool as $user) {
                 $this->indexFilesForUser($user);
             }
         });
     }
     $fork->wait();
 }
 private function runjobs()
 {
     if (!$this->storePath) {
         $this->storePath = TMP;
     }
     // look for a store of the previous run
     $store = "";
     $storeFilePath = $this->storePath . $this->storeFile;
     if (file_exists($storeFilePath)) {
         $store = file_get_contents($storeFilePath);
     }
     $this->out(date(DATE_SQL) . ' Reading from: ' . $storeFilePath);
     // build or rebuild the store
     if ($store != '') {
         $store = json_decode($store, true);
     } else {
         $store = $this->schedule;
     }
     App::import('Vendor', 'Fork', array('file' => 'duncan3dc/fork-helper/src/Fork.php'));
     $fork = new \duncan3dc\Helpers\Fork();
     //debug($this->schedule);
     //debug($store);
     // run the jobs that need to be run, record the time
     foreach ($this->schedule as $name => $job) {
         $now = new DateTime();
         $task = $job['task'];
         $action = $job['action'];
         // if the job has never been run before, create it
         if (!isset($store[$name])) {
             $store[$name] = $job;
         }
         // figure out the last run date
         $tmptime = $store[$name]['lastRun'];
         if ($tmptime == null) {
             $tmptime = new DateTime("1969-01-01 00:00:00");
         } elseif (is_array($tmptime)) {
             $tmptime = new DateTime($tmptime['date'], new DateTimeZone($tmptime['timezone']));
         } elseif (is_string($tmptime)) {
             $tmptime = new DateTime($tmptime);
         }
         $runNow = false;
         // determine the next run time based on the last
         if (substr($job['interval'], 0, 1) === 'P') {
             $tmptime->add(new DateInterval($job['interval']));
             // "P10DT4H" http://www.php.net/manual/en/class.dateinterval.php
             $runNow = $tmptime <= $now;
         } elseif (strtotime($job['interval']) !== false) {
             $tmptime->modify($job['interval']);
             // "next day 10:30" http://www.php.net/manual/en/datetime.formats.relative.php
             $runNow = $tmptime <= $now;
         } else {
             //cron expression
             //https://github.com/mtdowling/cron-expression
             $cron = Cron\CronExpression::factory($job['interval']);
             $runNow = $cron->getNextRunDate($tmptime) <= $now;
             $tmptime = $cron->getNextRunDate();
             //override for beter log readingz
         }
         $this->out('JOB ' . $job['name'] . ' next run time: ' . $tmptime->format(DATE_SQL));
         // is it time to run? has it never been run before? //aditionaly, is it currently running
         if ($runNow && empty($store[$name]['runningPID'])) {
             $this->out(date(DATE_SQL) . " Running {$name} --------------------------------------- ");
             if (!isset($this->{$task})) {
                 $this->{$task} = $this->Tasks->load($task);
                 // load models if they aren't already
                 foreach ($this->{$task}->uses as $mk => $mv) {
                     if (!isset($this->{$task}->{$mv})) {
                         App::uses('AppModel', 'Model');
                         App::uses($mv, 'Model');
                         $this->{$task}->{$mv} = new $mv();
                     }
                 }
             }
             // grab the entire schedule record incase it was updated..
             $store[$name] = $this->schedule[$name];
             // execute the task and store the result
             //$store[$name]['lastResult'] = call_user_func_array(array($this->$task, $action), $job['args']);
             //$reportInvoicesTask = $this->Tasks->load('ReportInvoices');
             //$fork->call(array($reportInvoicesTask,"execute"),array('2014-01-01 00:00:00','2016-01-01 00:00:00',"invoiceDaily"));
             //$store[$name]['lastResult'] = $fork->call(array($this->$task, $action), $job['args']);
             $store[$name]['runningPID'] = $fork->call(array($this->{$task}, $action), $job['args']);
             $this->out(date(DATE_SQL) . " Started {$name} as PID: " . $store[$name]['runningPID']);
             $this->activeThreads[] = $store[$name]['runningPID'];
             //unset($reportInvoicesTask);
             // assign it the current time
             $now = new DateTime();
             $store[$name]['lastRun'] = $now->format('Y-m-d H:i:s');
         }
     }
     // write the store back to the file
     file_put_contents($this->storePath . $this->storeFile, json_encode($store));
     $this->out(date(DATE_SQL) . ' All pending tasks are no longer pending');
     //$runningProcesses=Hash::extract($store,"{s}.runningPID");
     //debug($runningProcesses);
     for ($pcnt = 0; $pcnt < count($this->activeThreads); $pcnt++) {
         try {
             $endedPID = $fork->waitAny();
             $store = file_get_contents($storeFilePath);
             $store = json_decode($store, true);
             foreach ($store as $v) {
                 if ($v['runningPID'] == $endedPID) {
                     $finishedTask = $v;
                     break;
                 }
             }
             $this->out(date(DATE_SQL) . " Ended " . $finishedTask['name'] . " as PID: " . $endedPID);
             $store[$finishedTask['name']]['runningPID'] = null;
             file_put_contents($this->storePath . $this->storeFile, json_encode($store));
         } catch (Exception $e) {
             $message = $e->getMessage();
             $endedPID = $e->getCode();
             $store = file_get_contents($storeFilePath);
             $store = json_decode($store, true);
             foreach ($store as $v) {
                 if ($v['runningPID'] == $endedPID) {
                     $finishedTask = $v;
                     break;
                 }
             }
             $this->out(date(DATE_SQL) . " Ended " . $finishedTask['name'] . " as PID: " . $endedPID . " with EXCEPTION: \n" . $message);
             $store[$finishedTask['name']]['runningPID'] = null;
             $store[$finishedTask['name']]['lastResult'] = $message;
             file_put_contents($this->storePath . $this->storeFile, json_encode($store));
         }
     }
 }
Example #3
0
<?php

require 'vendor/autoload.php';
$fork = new \duncan3dc\Helpers\Fork();
$fork->call(function () {
    for ($i = 1; $i <= 3; $i++) {
        echo "Process A - " . $i . "\n";
        sleep(1);
    }
});
Example #4
0
 /**
  * @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)));
     }
     $memory = shmop_open($this->shmKey, 'c', 0644, $this->shmLimit);
     if (false === $memory) {
         $this->markTestSkipped('Cannot create shared memory block');
     } else {
         shmop_close($memory);
     }
     $expected = ['test-tube-1' => '1', 'test-tube-2' => '2'];
     $fork = new \duncan3dc\Helpers\Fork();
     $fork->call(function () use($expected) {
         foreach ($expected as $tube => $value) {
             $this->client->addWorker($tube, function (Job $job) {
                 // Store string "test-tube-%JOB_BODY%" in a 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);
                 throw new \RuntimeException('Forced exception to stop worker');
             });
             $this->assertNotEquals(false, $this->client->putInTube($tube, $value));
         }
         $this->client->doWork();
         exit(0);
     });
     $reflectionFork = new \ReflectionClass($fork);
     $reflectionThreads = $reflectionFork->getProperty('threads');
     $reflectionThreads->setAccessible(true);
     sleep(2);
     $reflectionThreads->setValue($fork, []);
     unset($fork);
     $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);
     $actual = explode("\n", trim($output));
     // Compare number of items in expected list with lines in shared memory
     $this->assertEquals(count($expected), count($actual));
     foreach ($actual as $value) {
         $this->assertArrayHasKey($value, $expected);
     }
 }