From 7948341a86fb08d236bb53f8aece809ae10ba5f2 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 20 Apr 2013 23:27:46 +0200 Subject: [PATCH] Rework background job system --- apps/user_ldap/appinfo/app.php | 2 +- apps/user_ldap/lib/jobs.php | 19 ++- cron.php | 11 +- lib/backgroundjob/job.php | 45 +++++++ lib/backgroundjob/joblist.php | 158 +++++++++++++++++++++++ lib/backgroundjob/queuedjob.php | 28 ++++ lib/backgroundjob/queuedtask.php | 105 --------------- lib/backgroundjob/regulartask.php | 52 -------- lib/backgroundjob/timedjob.php | 41 ++++++ lib/backgroundjob/worker.php | 118 ----------------- lib/base.php | 2 +- lib/cache/fileglobalgc.php | 8 ++ lib/public/backgroundjob.php | 71 +--------- tests/lib/backgroundjob/dummyjoblist.php | 114 ++++++++++++++++ tests/lib/backgroundjob/queuedjob.php | 42 ++++++ tests/lib/backgroundjob/timedjob.php | 68 ++++++++++ 16 files changed, 530 insertions(+), 354 deletions(-) create mode 100644 lib/backgroundjob/job.php create mode 100644 lib/backgroundjob/joblist.php create mode 100644 lib/backgroundjob/queuedjob.php delete mode 100644 lib/backgroundjob/queuedtask.php delete mode 100644 lib/backgroundjob/regulartask.php create mode 100644 lib/backgroundjob/timedjob.php delete mode 100644 lib/backgroundjob/worker.php create mode 100644 lib/cache/fileglobalgc.php create mode 100644 tests/lib/backgroundjob/dummyjoblist.php create mode 100644 tests/lib/backgroundjob/queuedjob.php create mode 100644 tests/lib/backgroundjob/timedjob.php diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index 89410b5ef0..5c8b3ddfb6 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -49,7 +49,7 @@ $entry = array( 'name' => 'LDAP' ); -OCP\Backgroundjob::addRegularTask('OCA\user_ldap\lib\Jobs', 'updateGroups'); +OCP\Backgroundjob::registerJob('OCA\user_ldap\lib\Jobs'); if(OCP\App::isEnabled('user_webdavauth')) { OCP\Util::writeLog('user_ldap', 'user_ldap and user_webdavauth are incompatible. You may experience unexpected behaviour', diff --git a/apps/user_ldap/lib/jobs.php b/apps/user_ldap/lib/jobs.php index 094d11db3d..60ecc0da33 100644 --- a/apps/user_ldap/lib/jobs.php +++ b/apps/user_ldap/lib/jobs.php @@ -23,20 +23,22 @@ namespace OCA\user_ldap\lib; -class Jobs { +class Jobs extends \OC\BackgroundJob\TimedJob { static private $groupsFromDB; static private $groupBE; static private $connector; + public function __construct(){ + $this->interval = self::getRefreshInterval(); + } + + public function run($argument){ + Jobs::updateGroups(); + } + static public function updateGroups() { \OCP\Util::writeLog('user_ldap', 'Run background job "updateGroups"', \OCP\Util::DEBUG); - $lastUpdate = \OCP\Config::getAppValue('user_ldap', 'bgjUpdateGroupsLastRun', 0); - if((time() - $lastUpdate) < self::getRefreshInterval()) { - \OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – last run too fresh, aborting.', \OCP\Util::DEBUG); - //komm runter Werner die Maurer geben ein aus - return; - } $knownGroups = array_keys(self::getKnownGroups()); $actualGroups = self::getGroupBE()->getGroups(); @@ -45,7 +47,6 @@ class Jobs { \OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – groups do not seem to be configured properly, aborting.', \OCP\Util::INFO); - \OCP\Config::setAppValue('user_ldap', 'bgjUpdateGroupsLastRun', time()); return; } @@ -53,8 +54,6 @@ class Jobs { self::handleCreatedGroups(array_diff($actualGroups, $knownGroups)); self::handleRemovedGroups(array_diff($knownGroups, $actualGroups)); - \OCP\Config::setAppValue('user_ldap', 'bgjUpdateGroupsLastRun', time()); - \OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – Finished.', \OCP\Util::DEBUG); } diff --git a/cron.php b/cron.php index 07ce45ac22..c8dd6fcc88 100644 --- a/cron.php +++ b/cron.php @@ -94,7 +94,11 @@ if (OC::$CLI) { touch(TemporaryCronClass::$lockfile); // Work - OC_BackgroundJob_Worker::doAllSteps(); + $jobList = new \OC\BackgroundJob\JobList(); + $jobs = $jobList->getAll(); + foreach ($jobs as $job) { + $job->execute($jobList); + } } else { // We call cron.php from some website if ($appmode == 'cron') { @@ -102,7 +106,10 @@ if (OC::$CLI) { OC_JSON::error(array('data' => array('message' => 'Backgroundjobs are using system cron!'))); } else { // Work and success :-) - OC_BackgroundJob_Worker::doNextStep(); + $jobList = new \OC\BackgroundJob\JobList(); + $job = $jobList->getNext(); + $job->execute($jobList); + $jobList->setLastJob($job); OC_JSON::success(); } } diff --git a/lib/backgroundjob/job.php b/lib/backgroundjob/job.php new file mode 100644 index 0000000000..ff647c7329 --- /dev/null +++ b/lib/backgroundjob/job.php @@ -0,0 +1,45 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\BackgroundJob; + +abstract class Job { + protected $id; + protected $lastRun; + protected $argument; + + /** + * @param JobList $jobList + */ + public function execute($jobList) { + $jobList->setLastRun($this); + $this->run($this->argument); + } + + abstract protected function run($argument); + + public function setId($id) { + $this->id = $id; + } + + public function setLastRun($lastRun) { + $this->lastRun = $lastRun; + } + + public function setArgument($argument) { + $this->argument = $argument; + } + + public function getId() { + return $this->id; + } + + public function getLastRun() { + return $this->lastRun(); + } +} diff --git a/lib/backgroundjob/joblist.php b/lib/backgroundjob/joblist.php new file mode 100644 index 0000000000..7471f84153 --- /dev/null +++ b/lib/backgroundjob/joblist.php @@ -0,0 +1,158 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\BackgroundJob; + +/** + * Class QueuedJob + * + * create a background job that is to be executed once + * + * @package OC\BackgroundJob + */ +class JobList { + /** + * @param Job|string $job + * @param mixed $argument + */ + public function add($job, $argument = null) { + if (!$this->has($job, $argument)) { + if ($job instanceof Job) { + $class = get_class($job); + } else { + $class = $job; + } + $argument = json_encode($argument); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*jobs`(`class`, `argument`, `last_run`) VALUES(?, ?, 0)'); + $query->execute(array($class, $argument)); + } + } + + /** + * @param Job|string $job + * @param mixed $argument + */ + public function remove($job, $argument = null) { + if ($job instanceof Job) { + $class = get_class($job); + } else { + $class = $job; + } + if (!is_null($argument)) { + $argument = json_encode($argument); + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*jobs` WHERE `class` = ? AND `argument` = ?'); + $query->execute(array($class, $argument)); + } else { + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*jobs` WHERE `class` = ?'); + $query->execute(array($class)); + } + } + + /** + * check if a job is in the list + * + * @param $job + * @param mixed $argument + * @return bool + */ + public function has($job, $argument) { + if ($job instanceof Job) { + $class = get_class($job); + } else { + $class = $job; + } + $argument = json_encode($argument); + $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*jobs` WHERE `class` = ? AND `argument` = ?'); + $result = $query->execute(array($class, $argument)); + return (bool)$result->fetchRow(); + } + + /** + * get all jobs in the list + * + * @return Job[] + */ + public function getAll() { + $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs`'); + $result = $query->execute(); + $jobs = array(); + while ($row = $result->fetchRow()) { + $jobs[] = $this->buildJob($row); + } + return $jobs; + } + + /** + * get the next job in the list + * + * @return Job + */ + public function getNext() { + $lastId = $this->getLastJob(); + $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` WHERE `id` > ? ORDER BY `id` ASC', 1); + $result = $query->execute(array($lastId)); + if ($row = $result->fetchRow()) { + return $this->buildJob($row); + } else { + //begin at the start of the queue + $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` ORDER BY `id` ASC', 1); + $result = $query->execute(); + if ($row = $result->fetchRow()) { + return $this->buildJob($row); + } else { + return null; //empty job list + } + } + } + + /** + * get the job object from a row in the db + * + * @param array $row + * @return Job + */ + private function buildJob($row) { + $class = $row['class']; + /** + * @var Job $job + */ + $job = new $class(); + $job->setId($row['id']); + $job->setLastRun($row['last_run']); + $job->setArgument(json_decode($row['argument'])); + return $job; + } + + /** + * set the job that was last ran + * + * @param Job $job + */ + public function setLastJob($job) { + \OC_Appconfig::setValue('backgroundjob', 'lastjob', $job->getId()); + } + + /** + * get the id of the last ran job + * + * @return int + */ + public function getLastJob() { + return \OC_Appconfig::getValue('backgroundjob', 'lastjob', 0); + } + + /** + * set the lastRun of $job to now + * + * @param Job $job + */ + public function setLastRun($job) { + $query = \OC_DB::prepare('UPDATE `*PREFIX*jobs` SET `last_run` = ? WHERE `id` = ?'); + $query->execute(array(time(), $job->getId())); + } +} diff --git a/lib/backgroundjob/queuedjob.php b/lib/backgroundjob/queuedjob.php new file mode 100644 index 0000000000..1714182820 --- /dev/null +++ b/lib/backgroundjob/queuedjob.php @@ -0,0 +1,28 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\BackgroundJob; + +/** + * Class QueuedJob + * + * create a background job that is to be executed once + * + * @package OC\BackgroundJob + */ +abstract class QueuedJob extends Job { + /** + * run the job, then remove it from the joblist + * + * @param JobList $jobList + */ + public function execute($jobList) { + $jobList->remove($this); + $this->run($this->argument); + } +} diff --git a/lib/backgroundjob/queuedtask.php b/lib/backgroundjob/queuedtask.php deleted file mode 100644 index b2ce6f39ed..0000000000 --- a/lib/backgroundjob/queuedtask.php +++ /dev/null @@ -1,105 +0,0 @@ -. -* -*/ - -/** - * This class manages our queued tasks. - */ -class OC_BackgroundJob_QueuedTask{ - /** - * @brief Gets one queued task - * @param $id ID of the task - * @return associative array - */ - public static function find( $id ) { - $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks` WHERE `id` = ?' ); - $result = $stmt->execute(array($id)); - return $result->fetchRow(); - } - - /** - * @brief Gets all queued tasks - * @return array with associative arrays - */ - public static function all() { - // Array for objects - $return = array(); - - // Get Data - $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks`' ); - $result = $stmt->execute(array()); - while( $row = $result->fetchRow()) { - $return[] = $row; - } - - return $return; - } - - /** - * @brief Gets all queued tasks of a specific app - * @param $app app name - * @return array with associative arrays - */ - public static function whereAppIs( $app ) { - // Array for objects - $return = array(); - - // Get Data - $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks` WHERE `app` = ?' ); - $result = $stmt->execute(array($app)); - while( $row = $result->fetchRow()) { - $return[] = $row; - } - - // Und weg damit - return $return; - } - - /** - * @brief queues a task - * @param $app app name - * @param $klass class name - * @param $method method name - * @param $parameters all useful data as text - * @return id of task - */ - public static function add( $app, $klass, $method, $parameters ) { - $stmt = OC_DB::prepare( 'INSERT INTO `*PREFIX*queuedtasks` (`app`, `klass`, `method`, `parameters`)' - .' VALUES(?,?,?,?)' ); - $result = $stmt->execute(array($app, $klass, $method, $parameters )); - - return OC_DB::insertid(); - } - - /** - * @brief deletes a queued task - * @param $id id of task - * @return true/false - * - * Deletes a report - */ - public static function delete( $id ) { - $stmt = OC_DB::prepare( 'DELETE FROM `*PREFIX*queuedtasks` WHERE `id` = ?' ); - $result = $stmt->execute(array($id)); - - return true; - } -} diff --git a/lib/backgroundjob/regulartask.php b/lib/backgroundjob/regulartask.php deleted file mode 100644 index 9976872ee1..0000000000 --- a/lib/backgroundjob/regulartask.php +++ /dev/null @@ -1,52 +0,0 @@ -. -* -*/ - -/** - * This class manages the regular tasks. - */ -class OC_BackgroundJob_RegularTask{ - static private $registered = array(); - - /** - * @brief creates a regular task - * @param $klass class name - * @param $method method name - * @return true - */ - static public function register( $klass, $method ) { - // Create the data structure - self::$registered["$klass-$method"] = array( $klass, $method ); - - // No chance for failure ;-) - return true; - } - - /** - * @brief gets all regular tasks - * @return associative array - * - * key is string "$klass-$method", value is array( $klass, $method ) - */ - static public function all() { - return self::$registered; - } -} diff --git a/lib/backgroundjob/timedjob.php b/lib/backgroundjob/timedjob.php new file mode 100644 index 0000000000..ae9f33505a --- /dev/null +++ b/lib/backgroundjob/timedjob.php @@ -0,0 +1,41 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\BackgroundJob; + +/** + * Class QueuedJob + * + * create a background job that is to be executed at an interval + * + * @package OC\BackgroundJob + */ +abstract class TimedJob extends Job { + protected $interval = 0; + + /** + * set the interval for the job + * + * @param int $interval + */ + public function setInterval($interval) { + $this->interval = $interval; + } + + /** + * run the job if + * + * @param JobList $jobList + */ + public function execute($jobList) { + if ((time() - $this->lastRun) > $this->interval) { + $jobList->setLastRun($this); + $this->run($this->argument); + } + } +} diff --git a/lib/backgroundjob/worker.php b/lib/backgroundjob/worker.php deleted file mode 100644 index e966ac9647..0000000000 --- a/lib/backgroundjob/worker.php +++ /dev/null @@ -1,118 +0,0 @@ -. -* -*/ - -/** - * This class does the dirty work. - * - * TODO: locking in doAllSteps - */ -class OC_BackgroundJob_Worker{ - /** - * @brief executes all tasks - * @return boolean - * - * This method executes all regular tasks and then all queued tasks. - * This method should be called by cli scripts that do not let the user - * wait. - */ - public static function doAllSteps() { - // Do our regular work - $lasttask = OC_Appconfig::getValue( 'core', 'backgroundjobs_task', '' ); - - $regular_tasks = OC_BackgroundJob_RegularTask::all(); - ksort( $regular_tasks ); - foreach( $regular_tasks as $key => $value ) { - if( strcmp( $key, $lasttask ) > 0 ) { - // Set "restart here" config value - OC_Appconfig::setValue( 'core', 'backgroundjobs_task', $key ); - call_user_func( $value ); - } - } - // Reset "start here" config value - OC_Appconfig::setValue( 'core', 'backgroundjobs_task', '' ); - - // Do our queued tasks - $queued_tasks = OC_BackgroundJob_QueuedTask::all(); - foreach( $queued_tasks as $task ) { - OC_BackgroundJob_QueuedTask::delete( $task['id'] ); - call_user_func( array( $task['klass'], $task['method'] ), $task['parameters'] ); - } - - return true; - } - - /** - * @brief does a single task - * @return boolean - * - * This method executes one task. It saves the last state and continues - * with the next step. This method should be used by webcron and ajax - * services. - */ - public static function doNextStep() { - $laststep = OC_Appconfig::getValue( 'core', 'backgroundjobs_step', 'regular_tasks' ); - - if( $laststep == 'regular_tasks' ) { - // get last app - $lasttask = OC_Appconfig::getValue( 'core', 'backgroundjobs_task', '' ); - - // What's the next step? - $regular_tasks = OC_BackgroundJob_RegularTask::all(); - ksort( $regular_tasks ); - $done = false; - - // search for next background job - foreach( $regular_tasks as $key => $value ) { - if( strcmp( $key, $lasttask ) > 0 ) { - OC_Appconfig::setValue( 'core', 'backgroundjobs_task', $key ); - $done = true; - call_user_func( $value ); - break; - } - } - - if( $done == false ) { - // Next time load queued tasks - OC_Appconfig::setValue( 'core', 'backgroundjobs_step', 'queued_tasks' ); - } - } - else{ - $tasks = OC_BackgroundJob_QueuedTask::all(); - if( count( $tasks )) { - $task = $tasks[0]; - // delete job before we execute it. This prevents endless loops - // of failing jobs. - OC_BackgroundJob_QueuedTask::delete($task['id']); - - // execute job - call_user_func( array( $task['klass'], $task['method'] ), $task['parameters'] ); - } - else{ - // Next time load queued tasks - OC_Appconfig::setValue( 'core', 'backgroundjobs_step', 'regular_tasks' ); - OC_Appconfig::setValue( 'core', 'backgroundjobs_task', '' ); - } - } - - return true; - } -} diff --git a/lib/base.php b/lib/base.php index 7b0967df9f..fda65a221c 100644 --- a/lib/base.php +++ b/lib/base.php @@ -561,7 +561,7 @@ class OC { */ public static function registerCacheHooks() { // register cache cleanup jobs - OC_BackgroundJob_RegularTask::register('OC_Cache_FileGlobal', 'gc'); + \OCP\BackgroundJob::registerJob('OC_Cache_FileGlobalGC'); OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener'); } diff --git a/lib/cache/fileglobalgc.php b/lib/cache/fileglobalgc.php new file mode 100644 index 0000000000..a29c31f906 --- /dev/null +++ b/lib/cache/fileglobalgc.php @@ -0,0 +1,8 @@ +add($job, $argument); } - /** - * @brief gets all regular tasks - * @return associative array - * - * key is string "$klass-$method", value is array( $klass, $method ) - */ - static public function allRegularTasks() { - return \OC_BackgroundJob_RegularTask::all(); - } - - /** - * @brief Gets one queued task - * @param $id ID of the task - * @return associative array - */ - public static function findQueuedTask( $id ) { - return \OC_BackgroundJob_QueuedTask::find( $id ); - } - - /** - * @brief Gets all queued tasks - * @return array with associative arrays - */ - public static function allQueuedTasks() { - return \OC_BackgroundJob_QueuedTask::all(); - } - - /** - * @brief Gets all queued tasks of a specific app - * @param $app app name - * @return array with associative arrays - */ - public static function queuedTaskWhereAppIs( $app ) { - return \OC_BackgroundJob_QueuedTask::whereAppIs( $app ); - } - - /** - * @brief queues a task - * @param $app app name - * @param $klass class name - * @param $method method name - * @param $parameters all useful data as text - * @return id of task - */ - public static function addQueuedTask( $app, $klass, $method, $parameters ) { - return \OC_BackgroundJob_QueuedTask::add( $app, $klass, $method, $parameters ); - } - - /** - * @brief deletes a queued task - * @param $id id of task - * @return true/false - * - * Deletes a report - */ - public static function deleteQueuedTask( $id ) { - return \OC_BackgroundJob_QueuedTask::delete( $id ); - } } diff --git a/tests/lib/backgroundjob/dummyjoblist.php b/tests/lib/backgroundjob/dummyjoblist.php new file mode 100644 index 0000000000..c4ccfc22c9 --- /dev/null +++ b/tests/lib/backgroundjob/dummyjoblist.php @@ -0,0 +1,114 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\BackgroundJob; + +class JobRun extends \Exception { +} + +/** + * Class DummyJobList + * + * in memory job list for testing purposes + */ +class DummyJobList extends \OC\BackgroundJob\JobList { + /** + * @var \OC\BackgroundJob\Job[] + */ + private $jobs = array(); + + private $last = 0; + + /** + * @param \OC\BackgroundJob\Job|string $job + */ + public function add($job) { + if (!$this->has($job)) { + $this->jobs[] = $job; + } + } + + /** + * @param \OC\BackgroundJob\Job|string $job + */ + public function remove($job) { + $index = array_search($job, $this->jobs); + if ($index !== false) { + unset($this->jobs[$index]); + } + } + + /** + * check if a job is in the list + * + * @param $job + * @return bool + */ + public function has($job) { + return array_search($job, $this->jobs) !== false; + } + + /** + * get all jobs in the list + * + * @return \OC\BackgroundJob\Job[] + */ + public function getAll() { + return $this->jobs; + } + + /** + * get the next job in the list + * + * @return \OC\BackgroundJob\Job + */ + public function getNext() { + if (count($this->jobs) > 0) { + if ($this->last < (count($this->jobs) - 1)) { + $i = $this->last + 1; + } else { + $i = 0; + } + return $this->jobs[$i]; + } else { + return null; + } + } + + /** + * set the job that was last ran + * + * @param \OC\BackgroundJob\Job $job + */ + public function setLastJob($job) { + $i = array_search($job, $this->jobs); + if ($i !== false) { + $this->last = $i; + } else { + $this->last = 0; + } + } + + /** + * get the id of the last ran job + * + * @return int + */ + public function getLastJob() { + return $this->last; + } + + /** + * set the lastRun of $job to now + * + * @param \OC\BackgroundJob\Job $job + */ + public function setLastRun($job) { + $job->setLastRun(time()); + } +} diff --git a/tests/lib/backgroundjob/queuedjob.php b/tests/lib/backgroundjob/queuedjob.php new file mode 100644 index 0000000000..62d631a3ef --- /dev/null +++ b/tests/lib/backgroundjob/queuedjob.php @@ -0,0 +1,42 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\BackgroundJob; + +class TestQueuedJob extends \OC\BackgroundJob\QueuedJob { + public function run() { + throw new JobRun(); //throw an exception so we can detect if this function is called + } +} + +class QueuedJob extends \PHPUnit_Framework_TestCase { + /** + * @var DummyJobList $jobList + */ + private $jobList; + /** + * @var \OC\BackgroundJob\TimedJob $job + */ + private $job; + + public function setup() { + $this->jobList = new DummyJobList(); + $this->job = new TestQueuedJob(); + $this->jobList->add($this->job); + } + + public function testJobShouldBeRemoved() { + try { + $this->assertTrue($this->jobList->has($this->job)); + $this->job->execute($this->jobList); + $this->fail("job should have been run"); + } catch (JobRun $e) { + $this->assertFalse($this->jobList->has($this->job)); + } + } +} diff --git a/tests/lib/backgroundjob/timedjob.php b/tests/lib/backgroundjob/timedjob.php new file mode 100644 index 0000000000..4147b82cbb --- /dev/null +++ b/tests/lib/backgroundjob/timedjob.php @@ -0,0 +1,68 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\BackgroundJob; + +class TestTimedJob extends \OC\BackgroundJob\TimedJob { + public function __construct() { + $this->setInterval(10); + } + + public function run() { + throw new JobRun(); //throw an exception so we can detect if this function is called + } +} + +class TimedJob extends \PHPUnit_Framework_TestCase { + /** + * @var DummyJobList $jobList + */ + private $jobList; + /** + * @var \OC\BackgroundJob\TimedJob $job + */ + private $job; + + public function setup() { + $this->jobList = new DummyJobList(); + $this->job = new TestTimedJob(); + $this->jobList->add($this->job); + } + + public function testShouldRunAfterInterval() { + $this->job->setLastRun(time() - 12); + try { + $this->job->execute($this->jobList); + $this->fail("job should have run"); + } catch (JobRun $e) { + } + } + + public function testShouldNotRunWithinInterval() { + $this->job->setLastRun(time() - 5); + try { + $this->job->execute($this->jobList); + } catch (JobRun $e) { + $this->fail("job should not have run"); + } + } + + public function testShouldNotTwice() { + $this->job->setLastRun(time() - 15); + try { + $this->job->execute($this->jobList); + $this->fail("job should have run the first time"); + } catch (JobRun $e) { + try { + $this->job->execute($this->jobList); + } catch (JobRun $e) { + $this->fail("job should not have run the second time"); + } + } + } +}