From 74d4e7d50585db230cfe07464a1a4b662c04b409 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Sun, 28 Dec 2008 10:12:41 +0000 Subject: First round of a task framework. Tasks are job definitions stored in the database. They're started with admin/maintenance/start/[task_name] which sends down some JS/HTML which regularly pings the task at admin/maintenance/start/[task_id] until its done. The UI is still very rough. It works, though! --- core/controllers/admin_maintenance.php | 66 ++++++++++++++++++++++++++++++++++ core/helpers/core_installer.php | 14 ++++++-- core/helpers/core_menu.php | 2 +- core/helpers/graphics.php | 64 +++++++++++++++++++++++++++++---- core/models/task.php | 36 +++++++++++++++++++ core/views/admin_maintenance.html.php | 30 ++++++++++++++++ 6 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 core/controllers/admin_maintenance.php create mode 100644 core/models/task.php create mode 100644 core/views/admin_maintenance.html.php (limited to 'core') diff --git a/core/controllers/admin_maintenance.php b/core/controllers/admin_maintenance.php new file mode 100644 index 00000000..b695cfcb --- /dev/null +++ b/core/controllers/admin_maintenance.php @@ -0,0 +1,66 @@ + "rebuild_images", + "description" => _("Rebuild out of date thumbnails and resizes")), + ArrayObject::ARRAY_AS_PROPS)); + + $view->content = new View("admin_maintenance.html"); + $view->content->available_tasks = $available_tasks; + $view->content->running_tasks = ORM::factory("task")->find_all(); + print $view; + } + + public function start($task_name) { + $task = ORM::factory("task"); + $task->name = $task_name; + $task->percent_complete = 0; + $task->status = ""; + $task->context = serialize(array()); + $task->save(); + + $view = new View("admin_maintenance_task.html"); + $view->task = $task; + print $view; + } + + public function run($task_id) { + $task = ORM::factory("task", $task_id); + if (!$task->loaded) { + throw new Exception("@todo MISSING_TASK"); + } + + switch($task->name) { + case "rebuild_images": + graphics::rebuild_dirty_images($task); + } + + $task->save(); + + print json_encode( + array("status" => "success", + "task" => $task->as_array())); + } +} diff --git a/core/helpers/core_installer.php b/core/helpers/core_installer.php index d3147a02..46eb24c6 100644 --- a/core/helpers/core_installer.php +++ b/core/helpers/core_installer.php @@ -67,11 +67,11 @@ class core_installer { `parent_id` int(9) NOT NULL, `resize_height` int(9) default NULL, `resize_width` int(9) default NULL, - `resize_dirty` BOOLEAN default 1, + `resize_dirty` boolean default 1, `right` int(9) NOT NULL, `thumb_height` int(9) default NULL, `thumb_width` int(9) default NULL, - `thumb_dirty` BOOLEAN default 1, + `thumb_dirty` boolean default 1, `title` varchar(255) default NULL, `type` varchar(32) NOT NULL, `updated` int(9) default NULL, @@ -127,6 +127,16 @@ class core_installer { PRIMARY KEY (`session_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + $db->query("CREATE TABLE `tasks` ( + `context` text NOT NULL, + `done` boolean DEFAULT 0, + `id` int(9) NOT NULL auto_increment, + `name` varchar(255) default NULL, + `percent_complete` int(9) default 0, + `status` varchar(255) default NULL, + PRIMARY KEY (`id`)) + ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + $db->query("CREATE TABLE `vars` ( `id` int(9) NOT NULL auto_increment, `module_name` varchar(255) NOT NULL, diff --git a/core/helpers/core_menu.php b/core/helpers/core_menu.php index 0a28f21f..d6f7bc56 100644 --- a/core/helpers/core_menu.php +++ b/core/helpers/core_menu.php @@ -101,7 +101,7 @@ class core_menu_Core { ->append(Menu::factory("link") ->id("maintenance") ->label(_("Maintenance")) - ->url("#")) + ->url(url::site("admin/maintenance"))) ->append(Menu::factory("link") ->id("statistics") ->label(_("Statistics")) diff --git a/core/helpers/graphics.php b/core/helpers/graphics.php index ee8e91ac..68aacaca 100644 --- a/core/helpers/graphics.php +++ b/core/helpers/graphics.php @@ -128,6 +128,17 @@ class graphics_Core { ->save($output_file); } + /** + * Return a query result that locates all items with dirty images. + * @return Database_Result Query result + */ + private static function _find_dirty_images_query() { + return Database::instance()->query( + "SELECT `id` FROM `items` " . + "WHERE (`thumb_dirty` = 1 AND (`type` <> 'album' OR `right` - `left` > 1))" . + " OR (`resize_dirty` = 1 AND `type` = 'photo')"); + } + /** * Mark all thumbnails and resizes as dirty. They will have to be rebuilt. * @@ -136,16 +147,57 @@ class graphics_Core { $db = Database::instance(); $db->query("UPDATE `items` SET `thumb_dirty` = 1, `resize_dirty` = 1"); - $count = $db->query("SELECT COUNT(*) AS C FROM `items` " . - "WHERE `thumb_dirty` = 1 " . - " OR (`resize_dirty` = 1 AND `type` = 'photo')") - ->current() - ->C; + $count = self::_find_dirty_images_query()->count(); if ($count) { message::warning( sprintf(_("%d of your photos are out of date. %sClick here to fix them%s"), - $count, "", ""), + $count, "", ""), "graphics_dirty"); } } + + /** + * Task that rebuilds all dirty images. + * @param Task_Model the task + */ + public static function rebuild_dirty_images($task) { + $db = Database::instance(); + + $result = self::_find_dirty_images_query(); + $remaining = $result->count(); + $completed = $task->get("completed", 0); + + $i = 0; + foreach ($result as $row) { + $item = ORM::factory("item", $row->id); + if ($item->loaded) { + self::generate($item); + } + + $completed++; + $remaining--; + + if ($i++ == 3) { + break; + } + } + + $task->status = sprintf( + _("Updated %d out of %d images"), $completed, $remaining + $completed); + + if ($completed + $remaining > 0) { + $task->percent_complete = (int)(100 * $completed / ($completed + $remaining)); + } else { + $task->percent_complete = 100; + } + + $task->set("completed", $completed); + $task->done = ($remaining == 0); + + if ($task->done) { + message::clear_permanent("graphics_dirty"); + } + } } diff --git a/core/models/task.php b/core/models/task.php new file mode 100644 index 00000000..697ab7bc --- /dev/null +++ b/core/models/task.php @@ -0,0 +1,36 @@ +context); + if (array_key_exists($key, $context)) { + return $context[$key]; + } else { + return $default; + } + } + + public function set($key, $value) { + $context = unserialize($this->context); + $context[$key] = $value; + $this->context = serialize($context); + } +} \ No newline at end of file diff --git a/core/views/admin_maintenance.html.php b/core/views/admin_maintenance.html.php new file mode 100644 index 00000000..0d9f6adb --- /dev/null +++ b/core/views/admin_maintenance.html.php @@ -0,0 +1,30 @@ + +
+

+

+ +

+ +
+

+ + + + + + +
+ description ?> + + name") ?>" class="gDialogLink"> + + +
+
+ +
+

+ + Task list goes here +
+
-- cgit v1.2.3