From 4f90860001e1529fa288218933477de563b0bcaf Mon Sep 17 00:00:00 2001
From: Jakob Sack <mail@jakobsack.de>
Date: Wed, 8 Aug 2012 23:39:30 +0200
Subject: [PATCH] Add initial version of backgroundjobs library

---
 lib/backgroundjobs/regulartask.php   |  52 +++++++++++++
 lib/backgroundjobs/scheduledtask.php | 106 ++++++++++++++++++++++++++
 lib/backgroundjobs/worker.php        | 109 +++++++++++++++++++++++++++
 3 files changed, 267 insertions(+)
 create mode 100644 lib/backgroundjobs/regulartask.php
 create mode 100644 lib/backgroundjobs/scheduledtask.php
 create mode 100644 lib/backgroundjobs/worker.php

diff --git a/lib/backgroundjobs/regulartask.php b/lib/backgroundjobs/regulartask.php
new file mode 100644
index 0000000000..38c1255d76
--- /dev/null
+++ b/lib/backgroundjobs/regulartask.php
@@ -0,0 +1,52 @@
+<?php
+/**
+* ownCloud - Background Job
+*
+* @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_Backgroundjobs_RegularTask{
+	static private $registered = array();
+
+	/**
+	 * @brief creates a regular task
+	 * @param $klass class name
+	 * @param $method method name
+	 * @return true
+	 */
+	static public function create( $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/backgroundjobs/scheduledtask.php b/lib/backgroundjobs/scheduledtask.php
new file mode 100644
index 0000000000..48a863c906
--- /dev/null
+++ b/lib/backgroundjobs/scheduledtask.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+* ownCloud - Background Job
+*
+* @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 scheduled tasks.
+ */
+class OC_Backgroundjobs_ScheduledTask{
+	/**
+	 * @brief Gets one scheduled task
+	 * @param $id ID of the task
+	 * @return associative array
+	 */
+	public static function find( $id ){
+		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*scheduledtasks WHERE id = ?' );
+		$result = $stmt->execute(array($id));
+		return $result->fetchRow();
+	}
+
+	/**
+	 * @brief Gets all scheduled tasks
+	 * @return array with associative arrays
+	 */
+	public static function all(){
+		// Array for objects
+		$return = array();
+
+		// Get Data
+		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*scheduledtasks' );
+		$result = $stmt->execute(array());
+		while( $row = $result->fetchRow()){
+			$return[] = $row;
+		}
+
+		// Und weg damit
+		return $return;
+	}
+
+	/**
+	 * @brief Gets all scheduled 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*scheduledtasks WHERE app = ?' );
+		$result = $stmt->execute(array($app));
+		while( $row = $result->fetchRow()){
+			$return[] = $row;
+		}
+
+		// Und weg damit
+		return $return;
+	}
+
+	/**
+	 * @brief schedules 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( $task, $klass, $method, $parameters ){
+		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*scheduledtasks (app, klass, method, parameters) VALUES(?,?,?,?)' );
+		$result = $stmt->execute(array($app, $klass, $method, $parameters, time));
+
+		return OC_DB::insertid();
+	}
+
+	/**
+	 * @brief deletes a scheduled task
+	 * @param $id id of task
+	 * @return true/false
+	 *
+	 * Deletes a report
+	 */
+	public static function delete( $id ){
+		$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*scheduledtasks WHERE id = ?' );
+		$result = $stmt->execute(array($id));
+
+		return true;
+	}
+}
diff --git a/lib/backgroundjobs/worker.php b/lib/backgroundjobs/worker.php
new file mode 100644
index 0000000000..0a99c80ebd
--- /dev/null
+++ b/lib/backgroundjobs/worker.php
@@ -0,0 +1,109 @@
+<?php
+/**
+* ownCloud - Background Job
+*
+* @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_Backgroundjobs_Worker{
+	/**
+	 * @brief executes all tasks
+	 * @return boolean
+	 *
+	 * This method executes all regular tasks and then all scheduled tasks.
+	 * This method should be called by cli scripts that do not let the user
+	 * wait.
+	 */
+	public static function doAllSteps(){
+		// Do our regular work
+		$regular_tasks = OC_Backgroundjobs_RegularTask::all();
+		foreach( $regular_tasks as $key => $value ){
+			call_user_func( $value );
+		}
+
+		// Do our scheduled tasks
+		$scheduled_tasks = OC_Backgroundjobs_ScheduledTask::all();
+		foreach( $scheduled_tasks as $task ){
+			call_user_func( array( $task['klass'], $task['method'] ), $task['parameters'] );
+			OC_Backgroundjobs_ScheduledTask::delete( $task['id'] );
+		}
+		
+		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 doWebStep(){
+		$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_Backgroundjobs_RegularTask::all();
+			ksort( $regular_tasks );
+			$done = false;
+			
+			// search for next background job
+			foreach( $regular_tasks as $key => $value ){
+				if( strcmp( $lasttask, $key ) > 0 ){
+					OC_Appconfig::getValue( 'core', 'backgroundjobs_task', $key );
+					$done = true;
+					call_user_func( $value );
+					break;
+				}
+			}
+
+			if( $done == false ){
+				// Next time load scheduled tasks
+				OC_Appconfig::setValue( 'core', 'backgroundjobs_step', 'scheduled_tasks' );
+			}
+		}
+		else{
+			$tasks = OC_Backgroundjobs_ScheduledTask::all();
+			if( length( $tasks )){
+				$task = $tasks[0];
+				// delete job before we execute it. This prevents endless loops
+				// of failing jobs.
+				OC_Backgroundjobs_ScheduledTask::delete($task['id']);
+
+				// execute job
+				call_user_func( array( $task['klass'], $task['method'] ), $task['parameters'] );
+			}
+			else{
+				// Next time load scheduled tasks
+				OC_Appconfig::setValue( 'core', 'backgroundjobs_step', 'regular_tasks' );
+				OC_Appconfig::setValue( 'core', 'backgroundjobs_task', '' );
+			}
+		}
+		
+		return true;
+	}
+}
-- 
GitLab