summaryrefslogtreecommitdiffstats
path: root/lib/backgroundjob
diff options
context:
space:
mode:
authorRobin Appelman <icewind@owncloud.com>2013-04-20 23:27:46 +0200
committerRobin Appelman <icewind@owncloud.com>2013-04-20 23:27:46 +0200
commit7948341a86fb08d236bb53f8aece809ae10ba5f2 (patch)
tree61bf8cc11b2212953f5f87216d33a7744869385f /lib/backgroundjob
parentd0a5fe1f4a39f21c596293232be19d70ad30652e (diff)
downloadnextcloud-server-7948341a86fb08d236bb53f8aece809ae10ba5f2.tar.gz
nextcloud-server-7948341a86fb08d236bb53f8aece809ae10ba5f2.zip
Rework background job system
Diffstat (limited to 'lib/backgroundjob')
-rw-r--r--lib/backgroundjob/job.php45
-rw-r--r--lib/backgroundjob/joblist.php158
-rw-r--r--lib/backgroundjob/queuedjob.php28
-rw-r--r--lib/backgroundjob/queuedtask.php105
-rw-r--r--lib/backgroundjob/regulartask.php52
-rw-r--r--lib/backgroundjob/timedjob.php41
-rw-r--r--lib/backgroundjob/worker.php118
7 files changed, 272 insertions, 275 deletions
diff --git a/lib/backgroundjob/job.php b/lib/backgroundjob/job.php
new file mode 100644
index 00000000000..ff647c7329b
--- /dev/null
+++ b/lib/backgroundjob/job.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * 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 00000000000..7471f84153b
--- /dev/null
+++ b/lib/backgroundjob/joblist.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * 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 00000000000..1714182820d
--- /dev/null
+++ b/lib/backgroundjob/queuedjob.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * 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 b2ce6f39ed8..00000000000
--- a/lib/backgroundjob/queuedtask.php
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * 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 9976872ee13..00000000000
--- a/lib/backgroundjob/regulartask.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * 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 00000000000..ae9f33505ab
--- /dev/null
+++ b/lib/backgroundjob/timedjob.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * 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 e966ac9647c..00000000000
--- a/lib/backgroundjob/worker.php
+++ /dev/null
@@ -1,118 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * 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;
- }
-}