Skip to content
Permalink
Browse files

MDL-42039 Restore: Add progress tracking in restore controller load

In the case of a very large backup with many activities, simply loading
the restore controller (specifically, building the plan) can take a long
time and cause timeouts. This change adds progress reporting while the
restore controller is being loaded.

(This also reduces the time between first going to the page, and the
progress bar appearing, making a slightly better user experience.)

Conflicts:

	backup/restore.php
  • Loading branch information...
sammarshallou authored and damyon committed Oct 1, 2013
1 parent a658b73 commit bf2a039e9adc79e61a155aab5622e6fff34102fe
@@ -58,15 +58,22 @@ class restore_controller extends base_controller {
protected $checksum; // Cache @checksumable results for lighter @is_checksum_correct() uses
/**
* Constructor.
*
* If you specify a progress monitor, this will be used to report progress
* while loading the plan, as well as for future use. (You can change it
* for a different one later using set_progress.)
*
* @param string $tempdir Directory under tempdir/backup awaiting restore
* @param int $courseid Course id where restore is going to happen
* @param bool $interactive backup::INTERACTIVE_YES[true] or backup::INTERACTIVE_NO[false]
* @param int $mode backup::MODE_[ GENERAL | HUB | IMPORT | SAMESITE ]
* @param int $userid
* @param int $target backup::TARGET_[ NEW_COURSE | CURRENT_ADDING | CURRENT_DELETING | EXISTING_ADDING | EXISTING_DELETING ]
* @param core_backup_progress $progress Optional progress monitor
*/
public function __construct($tempdir, $courseid, $interactive, $mode, $userid, $target){
public function __construct($tempdir, $courseid, $interactive, $mode, $userid, $target,
core_backup_progress $progress = null) {
$this->tempdir = $tempdir;
$this->courseid = $courseid;
$this->interactive = $interactive;
@@ -99,9 +106,14 @@ public function __construct($tempdir, $courseid, $interactive, $mode, $userid, $
// Default logger chain (based on interactive/execution)
$this->logger = backup_factory::get_logger_chain($this->interactive, $this->execution, $this->restoreid);
// By default there is no progress reporter. Interfaces that wish to
// display progress must set it.
$this->progress = new core_backup_null_progress();
// By default there is no progress reporter unless you specify one so it
// can be used during loading of the plan.
if ($progress) {
$this->progress = $progress;
} else {
$this->progress = new core_backup_null_progress();
}
$this->progress->start_progress('Constructing restore_controller');
// Instantiate the output_controller singleton and active it if interactive and inmediate
$oc = output_controller::get_instance();
@@ -135,6 +147,9 @@ public function __construct($tempdir, $courseid, $interactive, $mode, $userid, $
$this->set_status(backup::STATUS_NEED_PRECHECK);
}
}
// Tell progress monitor that we finished loading.
$this->progress->end_progress();
}
/**
@@ -97,6 +97,7 @@ static public function build_plan($controller) {
// preloading information to temp table
// and other init tasks
$plan->add_task(new restore_root_task('root_task'));
$controller->get_progress()->progress();
switch ($controller->get_type()) {
case backup::TYPE_1ACTIVITY:
@@ -115,6 +116,7 @@ static public function build_plan($controller) {
// conversion...)
// and perform other various final actions.
$plan->add_task(new restore_final_task('final_task'));
$controller->get_progress()->progress();
}
@@ -134,13 +136,15 @@ static protected function build_activity_plan($controller, $activityid) {
// as far as the module can be missing on restore
if ($task = restore_factory::get_restore_activity_task($infoactivity)) { // can be missing
$plan->add_task($task);
$controller->get_progress()->progress();
// For the given activity path, add as many block tasks as necessary
// TODO: Add blocks, we need to introspect xml here
$blocks = backup_general_helper::get_blocks_from_path($task->get_taskbasepath());
foreach ($blocks as $basepath => $name) {
if ($task = restore_factory::get_restore_block_task($name, $basepath)) {
$plan->add_task($task);
$controller->get_progress()->progress();
} else {
// TODO: Debug information about block not supported
}
@@ -163,6 +167,7 @@ static protected function build_section_plan($controller, $sectionid) {
// Add the section task, responsible for restoring
// all the section related information
$plan->add_task(restore_factory::get_restore_section_task($infosection));
$controller->get_progress()->progress();
// For the given section, add as many activity tasks as necessary
foreach ($info->activities as $activityid => $activity) {
if ($activity->sectionid != $infosection->sectionid) {
@@ -188,13 +193,15 @@ static protected function build_course_plan($controller, $courseid) {
// all the course related information
$task = restore_factory::get_restore_course_task($info->course, $courseid);
$plan->add_task($task);
$controller->get_progress()->progress();
// For the given course path, add as many block tasks as necessary
// TODO: Add blocks, we need to introspect xml here
$blocks = backup_general_helper::get_blocks_from_path($task->get_taskbasepath());
foreach ($blocks as $basepath => $name) {
if ($task = restore_factory::get_restore_block_task($name, $basepath)) {
$plan->add_task($task);
$controller->get_progress()->progress();
} else {
// TODO: Debug information about block not supported
}
@@ -17,6 +17,23 @@
require_login($course, null, $cm);
require_capability('moodle/restore:restorecourse', $context);
// Show page header.
$PAGE->set_title($course->shortname . ': ' . get_string('restore'));
$PAGE->set_heading($course->fullname);
$renderer = $PAGE->get_renderer('core','backup');
echo $OUTPUT->header();
// Prepare a progress bar which can display optionally during long-running
// operations while setting up the UI.
$slowprogress = new core_backup_display_progress_if_slow(get_string('preparingui', 'backup'));
// Overall, allow 10 units of progress.
$slowprogress->start_progress('', 10);
// This progress section counts for loading the restore controller.
$slowprogress->start_progress('', 1, 1);
// Restore of large courses requires extra memory. Use the amount configured
// in admin settings.
raise_memory_limit(MEMORY_EXTRA);
@@ -43,15 +60,12 @@
}
}
$PAGE->set_title($course->shortname . ': ' . get_string('restore'));
$PAGE->set_heading($course->fullname);
// End progress section for loading restore controller.
$slowprogress->end_progress();
$renderer = $PAGE->get_renderer('core','backup');
echo $OUTPUT->header();
// This progress section is for the 'process' function below.
$slowprogress->start_progress('', 1, 9);
// Prepare a progress bar which can display optionally during long-running
// operations while setting up the UI.
$slowprogress = new core_backup_display_progress_if_slow(get_string('preparingui', 'backup'));
// Depending on the code branch above, $restore may be a restore_ui or it may
// be a restore_ui_independent_stage. Either way, this function exists.
$restore->set_progress_reporter($slowprogress);
@@ -62,6 +76,10 @@
}
$loghtml = '';
// Finish the 'process' progress reporting section, and the overall count.
$slowprogress->end_progress();
$slowprogress->end_progress();
if (!$restore->is_independent()) {
// Use a temporary (disappearing) progress bar to show the precheck progress if any.
$precheckprogress = new core_backup_display_progress_if_slow(get_string('preparingdata', 'backup'));

0 comments on commit bf2a039

Please sign in to comment.
You can’t perform that action at this time.