diff --git a/docs/apis/subsystems/output/index.md b/docs/apis/subsystems/output/index.md index af26155198..01599ed26e 100644 --- a/docs/apis/subsystems/output/index.md +++ b/docs/apis/subsystems/output/index.md @@ -488,15 +488,15 @@ class stored_progress_scheduled_task_example extends \core\task\scheduled_task { for ($i = 1; $i <= $iterations; $i++) { // Here we just update and tell it which one we are on and it will work out % from those. - $this->progress->update($i, $iterations, 'i am at ' . $i . ' of ' . $iterations); + $this->progress->update($i, $iterations, get_string('processingitem', 'mod_yourplugin', [ + 'current' => $i, + 'total' => $iterations, + ])); sleep(1); - } return true; - } - } $task = new stored_progress_scheduled_task_example(); @@ -505,6 +505,8 @@ $task->initialise_stored_progress(); // Creates a stored progress record, so the With the stored progress bars, you can update the progress either via iterations, by passing in the total amount expected and then the current iteration, using `->update()`(see: previous example), this will calculate the percentage complete for you. Or you can use `->update_full()` to manually set the percentage complete. +The web page polls for updates via the `core_output_poll_stored_progress` web service, at an interval controlled by the `$CFG->progresspollinterval` setting (in seconds, default `5`). A scheduled task, `\core\task\stored_progress_bar_cleanup_task`, runs daily to delete stored progress records with a `lastupdate` older than 24 hours. + ## Reusing Output Classes in Web Services {/* #reusing-output-classes-in-web-services */} diff --git a/docs/apis/subsystems/task/index.md b/docs/apis/subsystems/task/index.md index 4689e0e5aa..b254523271 100644 --- a/docs/apis/subsystems/task/index.md +++ b/docs/apis/subsystems/task/index.md @@ -103,6 +103,86 @@ class my_task extends \core\task\scheduled_task { } ``` +### Reporting live progress {/* #reporting-live-progress */} + + + +For long-running scheduled or adhoc tasks, you can report live progress by using the `\core\task\stored_progress_task_trait` trait. This stores the task's progress in the database, and allows it to be polled for and rendered as a progress bar on any page in Moodle (for example, on the [`admin/tool/task`](https://github.com/moodle/moodle/tree/main/public/admin/tool/task) "Tasks running now" page), via the `core_output_poll_stored_progress` web service. + +```php +class my_task extends \core\task\scheduled_task { + + use \core\task\stored_progress_task_trait; + + public function execute() { + + // This simulates a specific count of iterations the task will do, e.g. x number of courses to loop through and do something. + $iterations = 100; + + // Updates the stored progress record with a start time. + $this->start_stored_progress(); + + for ($i = 1; $i <= $iterations; $i++) { + + // Here we just update and tell it which one we are on, and it will work out the percentage from those. + $this->progress->update($i, $iterations, get_string('processingitem', 'mod_yourplugin', [ + 'current' => $i, + 'total' => $iterations, + ])); + } + } +} +``` + +Before the task has started running (for example, immediately after an adhoc task has been queued), you can call `initialise_stored_progress()` on the task instance to create the stored progress record in a "pending" state, so that it can be displayed on screen straight away. Note that an adhoc task has no database ID until it has been queued, so the task must be queued, and the returned ID set back on the task, before `initialise_stored_progress()` is called - otherwise its progress name won't match the one used when the task actually runs: + +```php +$task = new my_adhoc_task(); +$task->set_custom_data(['courseid' => $courseid]); + +$taskid = \core\task\manager::queue_adhoc_task($task); +if ($taskid) { + // The task's ID must be set before initialising the stored progress record, so + // that both use the same idnumber when the task later calls start_stored_progress(). + $task->set_id($taskid); + + // Creates a stored progress record, so the progress can be displayed in a "pending" state, before the task has actually run. + $task->initialise_stored_progress(); +} +``` + +#### Displaying the progress on a page {/* #displaying-the-progress-on-a-page */} + +Once a task has created a stored progress record (either via `start_stored_progress()` or `initialise_stored_progress()`), any page can load it by its unique idnumber and render it. The idnumber is generated by `stored_progress_bar::convert_to_idnumber()`, using the task's class name and, for adhoc tasks, its record ID. This is exactly the approach used by the "Tasks running now" report in [`admin/tool/task`](https://github.com/moodle/moodle/blob/main/public/admin/tool/task/classes/running_tasks_table.php), which shows the live progress of every currently-running scheduled and adhoc task. + +```php +if ($task instanceof \core\task\adhoc_task) { + // For an adhoc task, the idnumber includes the task's record ID, so that concurrent + // executions of the same adhoc task each have their own progress bar. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_adhoc_task::class, $task->get_id()); +} else { + // For a scheduled task, there is only ever one instance running at a time, so the + // idnumber is based on the class name alone. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_task::class); +} + +$bar = \core\output\stored_progress_bar::get_by_idnumber($idnumber); +if ($bar) { + // Renders the progress bar HTML, and queues up the `core/stored_progress` AMD + // module which polls the `core_output_poll_stored_progress` web service and + // updates the bar on screen until the task completes. + echo $bar->get_content(); +} else { + // There is no stored progress record, e.g. because the task has not started, or + // has already finished and been cleaned up. + echo get_string('nothingtodisplay'); +} +``` + +`get_content()` can be called from any page, at any time after the record has been created, including in a completely different request to the one that queued or ran the task - for example, an admin page which is refreshed and simply checks for the presence of a stored progress record matching a known idnumber. + +See the [Stored Progress Bars](../output/index.md#stored-progress-bars) section of the Output API documentation for more information, including how to poll and render the progress bar, and how to configure the polling interval. + ## For Administrators {/* #for-administrators */} Several tools exist for administrators: diff --git a/versioned_docs/version-4.5/apis/subsystems/output/index.md b/versioned_docs/version-4.5/apis/subsystems/output/index.md index efea08e417..d9470f0d48 100644 --- a/versioned_docs/version-4.5/apis/subsystems/output/index.md +++ b/versioned_docs/version-4.5/apis/subsystems/output/index.md @@ -466,6 +466,8 @@ class stored_progress_scheduled_task_example extends \core\task\scheduled_task { With the stored progress bars, you can update the progress either via iterations, by passing in the total amount expected and then the current iteration, using `->update()`(see: previous example), this will calculate the percentage complete for you. Or you can use `->update_full()` to manually set the percentage complete. +The web page polls for updates via the `core_output_poll_stored_progress` web service, at an interval controlled by the `$CFG->progresspollinterval` setting (in seconds, default `5`). A scheduled task, `\core\task\stored_progress_bar_cleanup_task`, runs daily to delete stored progress records with a `lastupdate` older than 24 hours. + ## See also {/* #see-also */} - [HTML Guidelines](https://docs.moodle.org/dev/HTML_Guidelines) diff --git a/versioned_docs/version-4.5/apis/subsystems/task/index.md b/versioned_docs/version-4.5/apis/subsystems/task/index.md index 4689e0e5aa..624fcca333 100644 --- a/versioned_docs/version-4.5/apis/subsystems/task/index.md +++ b/versioned_docs/version-4.5/apis/subsystems/task/index.md @@ -103,6 +103,69 @@ class my_task extends \core\task\scheduled_task { } ``` +### Reporting live progress {/* #reporting-live-progress */} + + + +For long-running scheduled or adhoc tasks, you can report live progress by using the `\core\task\stored_progress_task_trait` trait. This stores the task's progress in the database, and allows it to be polled for and rendered as a progress bar on any page in Moodle (for example, on the [`admin/tool/task`](https://github.com/moodle/moodle/tree/MOODLE_405_STABLE/admin/tool/task) "Tasks running now" page), via the `core_output_poll_stored_progress` web service. + +```php +class my_task extends \core\task\scheduled_task { + + use \core\task\stored_progress_task_trait; + + public function execute() { + + // This simulates a specific count of iterations the task will do, e.g. x number of courses to loop through and do something. + $iterations = 100; + + // This creates the stored progress record for the named task. + $this->start_stored_progress(); + + for ($i = 1; $i <= $iterations; $i++) { + + // Here we just update and tell it which one we are on, and it will work out the percentage from those. + $this->progress->update($i, $iterations, get_string('processingitem', 'mod_yourplugin', [ + 'current' => $i, + 'total' => $iterations, + ])); + } + } +} +``` + +#### Displaying the progress on a page {/* #displaying-the-progress-on-a-page */} + +Once a task has created a stored progress record (via `start_stored_progress()`), any page can load it by its unique idnumber and render it. The idnumber is generated by `stored_progress_bar::convert_to_idnumber()`, using the task's class name and, for adhoc tasks, its record ID. This is exactly the approach used by the "Tasks running now" report in [`admin/tool/task`](https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/admin/tool/task/classes/running_tasks_table.php), which shows the live progress of every currently-running scheduled and adhoc task. + +```php +if ($task instanceof \core\task\adhoc_task) { + // For an adhoc task, the idnumber includes the task's record ID, so that concurrent + // executions of the same adhoc task each have their own progress bar. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_adhoc_task::class, $task->get_id()); +} else { + // For a scheduled task, there is only ever one instance running at a time, so the + // idnumber is based on the class name alone. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_task::class); +} + +$bar = \core\output\stored_progress_bar::get_by_idnumber($idnumber); +if ($bar) { + // Renders the progress bar HTML, and queues up the `core/stored_progress` AMD + // module which polls the `core_output_poll_stored_progress` web service and + // updates the bar on screen until the task completes. + echo $bar->get_content(); +} else { + // There is no stored progress record, e.g. because the task has not started, or + // has already finished and been cleaned up. + echo get_string('nothingtodisplay'); +} +``` + +`get_content()` can be called from any page, at any time after the record has been created, including in a completely different request to the one that queued or ran the task - for example, an admin page which is refreshed and simply checks for the presence of a stored progress record matching a known idnumber. + +See the [Stored Progress Bars](../output/index.md#stored-progress-bars) section of the Output API documentation for more information, including how to poll and render the progress bar, and how to configure the polling interval. + ## For Administrators {/* #for-administrators */} Several tools exist for administrators: diff --git a/versioned_docs/version-5.0/apis/subsystems/output/index.md b/versioned_docs/version-5.0/apis/subsystems/output/index.md index 92a93e487d..20200b0734 100644 --- a/versioned_docs/version-5.0/apis/subsystems/output/index.md +++ b/versioned_docs/version-5.0/apis/subsystems/output/index.md @@ -505,6 +505,8 @@ $task->initialise_stored_progress(); // Creates a stored progress record, so the With the stored progress bars, you can update the progress either via iterations, by passing in the total amount expected and then the current iteration, using `->update()`(see: previous example), this will calculate the percentage complete for you. Or you can use `->update_full()` to manually set the percentage complete. +The web page polls for updates via the `core_output_poll_stored_progress` web service, at an interval controlled by the `$CFG->progresspollinterval` setting (in seconds, default `5`). A scheduled task, `\core\task\stored_progress_bar_cleanup_task`, runs daily to delete stored progress records with a `lastupdate` older than 24 hours. + ## See also {/* #see-also */} - [HTML Guidelines](https://docs.moodle.org/dev/HTML_Guidelines) diff --git a/versioned_docs/version-5.0/apis/subsystems/task/index.md b/versioned_docs/version-5.0/apis/subsystems/task/index.md index 4689e0e5aa..cbc5fe8fad 100644 --- a/versioned_docs/version-5.0/apis/subsystems/task/index.md +++ b/versioned_docs/version-5.0/apis/subsystems/task/index.md @@ -103,6 +103,86 @@ class my_task extends \core\task\scheduled_task { } ``` +### Reporting live progress {/* #reporting-live-progress */} + + + +For long-running scheduled or adhoc tasks, you can report live progress by using the `\core\task\stored_progress_task_trait` trait. This stores the task's progress in the database, and allows it to be polled for and rendered as a progress bar on any page in Moodle (for example, on the [`admin/tool/task`](https://github.com/moodle/moodle/tree/MOODLE_500_STABLE/admin/tool/task) "Tasks running now" page), via the `core_output_poll_stored_progress` web service. + +```php +class my_task extends \core\task\scheduled_task { + + use \core\task\stored_progress_task_trait; + + public function execute() { + + // This simulates a specific count of iterations the task will do, e.g. x number of courses to loop through and do something. + $iterations = 100; + + // Updates the stored progress record with a start time. + $this->start_stored_progress(); + + for ($i = 1; $i <= $iterations; $i++) { + + // Here we just update and tell it which one we are on, and it will work out the percentage from those. + $this->progress->update($i, $iterations, get_string('processingitem', 'mod_yourplugin', [ + 'current' => $i, + 'total' => $iterations, + ])); + } + } +} +``` + +Before the task has started running (for example, immediately after an adhoc task has been queued), you can call `initialise_stored_progress()` on the task instance to create the stored progress record in a "pending" state, so that it can be displayed on screen straight away. Note that an adhoc task has no database ID until it has been queued, so the task must be queued, and the returned ID set back on the task, before `initialise_stored_progress()` is called - otherwise its progress name won't match the one used when the task actually runs: + +```php +$task = new my_adhoc_task(); +$task->set_custom_data(['courseid' => $courseid]); + +$taskid = \core\task\manager::queue_adhoc_task($task); +if ($taskid) { + // The task's ID must be set before initialising the stored progress record, so + // that both use the same idnumber when the task later calls start_stored_progress(). + $task->set_id($taskid); + + // Creates a stored progress record, so the progress can be displayed in a "pending" state, before the task has actually run. + $task->initialise_stored_progress(); +} +``` + +#### Displaying the progress on a page {/* #displaying-the-progress-on-a-page */} + +Once a task has created a stored progress record (either via `start_stored_progress()` or `initialise_stored_progress()`), any page can load it by its unique idnumber and render it. The idnumber is generated by `stored_progress_bar::convert_to_idnumber()`, using the task's class name and, for adhoc tasks, its record ID. This is exactly the approach used by the "Tasks running now" report in [`admin/tool/task`](https://github.com/moodle/moodle/blob/MOODLE_500_STABLE/admin/tool/task/classes/running_tasks_table.php), which shows the live progress of every currently-running scheduled and adhoc task. + +```php +if ($task instanceof \core\task\adhoc_task) { + // For an adhoc task, the idnumber includes the task's record ID, so that concurrent + // executions of the same adhoc task each have their own progress bar. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_adhoc_task::class, $task->get_id()); +} else { + // For a scheduled task, there is only ever one instance running at a time, so the + // idnumber is based on the class name alone. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_task::class); +} + +$bar = \core\output\stored_progress_bar::get_by_idnumber($idnumber); +if ($bar) { + // Renders the progress bar HTML, and queues up the `core/stored_progress` AMD + // module which polls the `core_output_poll_stored_progress` web service and + // updates the bar on screen until the task completes. + echo $bar->get_content(); +} else { + // There is no stored progress record, e.g. because the task has not started, or + // has already finished and been cleaned up. + echo get_string('nothingtodisplay'); +} +``` + +`get_content()` can be called from any page, at any time after the record has been created, including in a completely different request to the one that queued or ran the task - for example, an admin page which is refreshed and simply checks for the presence of a stored progress record matching a known idnumber. + +See the [Stored Progress Bars](../output/index.md#stored-progress-bars) section of the Output API documentation for more information, including how to poll and render the progress bar, and how to configure the polling interval. + ## For Administrators {/* #for-administrators */} Several tools exist for administrators: diff --git a/versioned_docs/version-5.1/apis/subsystems/output/index.md b/versioned_docs/version-5.1/apis/subsystems/output/index.md index af26155198..2fab3e29e2 100644 --- a/versioned_docs/version-5.1/apis/subsystems/output/index.md +++ b/versioned_docs/version-5.1/apis/subsystems/output/index.md @@ -505,6 +505,8 @@ $task->initialise_stored_progress(); // Creates a stored progress record, so the With the stored progress bars, you can update the progress either via iterations, by passing in the total amount expected and then the current iteration, using `->update()`(see: previous example), this will calculate the percentage complete for you. Or you can use `->update_full()` to manually set the percentage complete. +The web page polls for updates via the `core_output_poll_stored_progress` web service, at an interval controlled by the `$CFG->progresspollinterval` setting (in seconds, default `5`). A scheduled task, `\core\task\stored_progress_bar_cleanup_task`, runs daily to delete stored progress records with a `lastupdate` older than 24 hours. + ## Reusing Output Classes in Web Services {/* #reusing-output-classes-in-web-services */} diff --git a/versioned_docs/version-5.1/apis/subsystems/task/index.md b/versioned_docs/version-5.1/apis/subsystems/task/index.md index 4689e0e5aa..ec1427dd17 100644 --- a/versioned_docs/version-5.1/apis/subsystems/task/index.md +++ b/versioned_docs/version-5.1/apis/subsystems/task/index.md @@ -103,6 +103,86 @@ class my_task extends \core\task\scheduled_task { } ``` +### Reporting live progress {/* #reporting-live-progress */} + + + +For long-running scheduled or adhoc tasks, you can report live progress by using the `\core\task\stored_progress_task_trait` trait. This stores the task's progress in the database, and allows it to be polled for and rendered as a progress bar on any page in Moodle (for example, on the [`admin/tool/task`](https://github.com/moodle/moodle/tree/MOODLE_501_STABLE/public/admin/tool/task) "Tasks running now" page), via the `core_output_poll_stored_progress` web service. + +```php +class my_task extends \core\task\scheduled_task { + + use \core\task\stored_progress_task_trait; + + public function execute() { + + // This simulates a specific count of iterations the task will do, e.g. x number of courses to loop through and do something. + $iterations = 100; + + // Updates the stored progress record with a start time. + $this->start_stored_progress(); + + for ($i = 1; $i <= $iterations; $i++) { + + // Here we just update and tell it which one we are on, and it will work out the percentage from those. + $this->progress->update($i, $iterations, get_string('processingitem', 'mod_yourplugin', [ + 'current' => $i, + 'total' => $iterations, + ])); + } + } +} +``` + +Before the task has started running (for example, immediately after an adhoc task has been queued), you can call `initialise_stored_progress()` on the task instance to create the stored progress record in a "pending" state, so that it can be displayed on screen straight away. Note that an adhoc task has no database ID until it has been queued, so the task must be queued, and the returned ID set back on the task, before `initialise_stored_progress()` is called - otherwise its progress name won't match the one used when the task actually runs: + +```php +$task = new my_adhoc_task(); +$task->set_custom_data(['courseid' => $courseid]); + +$taskid = \core\task\manager::queue_adhoc_task($task); +if ($taskid) { + // The task's ID must be set before initialising the stored progress record, so + // that both use the same idnumber when the task later calls start_stored_progress(). + $task->set_id($taskid); + + // Creates a stored progress record, so the progress can be displayed in a "pending" state, before the task has actually run. + $task->initialise_stored_progress(); +} +``` + +#### Displaying the progress on a page {/* #displaying-the-progress-on-a-page */} + +Once a task has created a stored progress record (either via `start_stored_progress()` or `initialise_stored_progress()`), any page can load it by its unique idnumber and render it. The idnumber is generated by `stored_progress_bar::convert_to_idnumber()`, using the task's class name and, for adhoc tasks, its record ID. This is exactly the approach used by the "Tasks running now" report in [`admin/tool/task`](https://github.com/moodle/moodle/blob/MOODLE_501_STABLE/public/admin/tool/task/classes/running_tasks_table.php), which shows the live progress of every currently-running scheduled and adhoc task. + +```php +if ($task instanceof \core\task\adhoc_task) { + // For an adhoc task, the idnumber includes the task's record ID, so that concurrent + // executions of the same adhoc task each have their own progress bar. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_adhoc_task::class, $task->get_id()); +} else { + // For a scheduled task, there is only ever one instance running at a time, so the + // idnumber is based on the class name alone. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_task::class); +} + +$bar = \core\output\stored_progress_bar::get_by_idnumber($idnumber); +if ($bar) { + // Renders the progress bar HTML, and queues up the `core/stored_progress` AMD + // module which polls the `core_output_poll_stored_progress` web service and + // updates the bar on screen until the task completes. + echo $bar->get_content(); +} else { + // There is no stored progress record, e.g. because the task has not started, or + // has already finished and been cleaned up. + echo get_string('nothingtodisplay'); +} +``` + +`get_content()` can be called from any page, at any time after the record has been created, including in a completely different request to the one that queued or ran the task - for example, an admin page which is refreshed and simply checks for the presence of a stored progress record matching a known idnumber. + +See the [Stored Progress Bars](../output/index.md#stored-progress-bars) section of the Output API documentation for more information, including how to poll and render the progress bar, and how to configure the polling interval. + ## For Administrators {/* #for-administrators */} Several tools exist for administrators: diff --git a/versioned_docs/version-5.2/apis/subsystems/output/index.md b/versioned_docs/version-5.2/apis/subsystems/output/index.md index af26155198..2fab3e29e2 100644 --- a/versioned_docs/version-5.2/apis/subsystems/output/index.md +++ b/versioned_docs/version-5.2/apis/subsystems/output/index.md @@ -505,6 +505,8 @@ $task->initialise_stored_progress(); // Creates a stored progress record, so the With the stored progress bars, you can update the progress either via iterations, by passing in the total amount expected and then the current iteration, using `->update()`(see: previous example), this will calculate the percentage complete for you. Or you can use `->update_full()` to manually set the percentage complete. +The web page polls for updates via the `core_output_poll_stored_progress` web service, at an interval controlled by the `$CFG->progresspollinterval` setting (in seconds, default `5`). A scheduled task, `\core\task\stored_progress_bar_cleanup_task`, runs daily to delete stored progress records with a `lastupdate` older than 24 hours. + ## Reusing Output Classes in Web Services {/* #reusing-output-classes-in-web-services */} diff --git a/versioned_docs/version-5.2/apis/subsystems/task/index.md b/versioned_docs/version-5.2/apis/subsystems/task/index.md index 4689e0e5aa..70b7a1a904 100644 --- a/versioned_docs/version-5.2/apis/subsystems/task/index.md +++ b/versioned_docs/version-5.2/apis/subsystems/task/index.md @@ -103,6 +103,86 @@ class my_task extends \core\task\scheduled_task { } ``` +### Reporting live progress {/* #reporting-live-progress */} + + + +For long-running scheduled or adhoc tasks, you can report live progress by using the `\core\task\stored_progress_task_trait` trait. This stores the task's progress in the database, and allows it to be polled for and rendered as a progress bar on any page in Moodle (for example, on the [`admin/tool/task`](https://github.com/moodle/moodle/tree/MOODLE_502_STABLE/public/admin/tool/task) "Tasks running now" page), via the `core_output_poll_stored_progress` web service. + +```php +class my_task extends \core\task\scheduled_task { + + use \core\task\stored_progress_task_trait; + + public function execute() { + + // This simulates a specific count of iterations the task will do, e.g. x number of courses to loop through and do something. + $iterations = 100; + + // Updates the stored progress record with a start time. + $this->start_stored_progress(); + + for ($i = 1; $i <= $iterations; $i++) { + + // Here we just update and tell it which one we are on, and it will work out the percentage from those. + $this->progress->update($i, $iterations, get_string('processingitem', 'mod_yourplugin', [ + 'current' => $i, + 'total' => $iterations, + ])); + } + } +} +``` + +Before the task has started running (for example, immediately after an adhoc task has been queued), you can call `initialise_stored_progress()` on the task instance to create the stored progress record in a "pending" state, so that it can be displayed on screen straight away. Note that an adhoc task has no database ID until it has been queued, so the task must be queued, and the returned ID set back on the task, before `initialise_stored_progress()` is called - otherwise its progress name won't match the one used when the task actually runs: + +```php +$task = new my_adhoc_task(); +$task->set_custom_data(['courseid' => $courseid]); + +$taskid = \core\task\manager::queue_adhoc_task($task); +if ($taskid) { + // The task's ID must be set before initialising the stored progress record, so + // that both use the same idnumber when the task later calls start_stored_progress(). + $task->set_id($taskid); + + // Creates a stored progress record, so the progress can be displayed in a "pending" state, before the task has actually run. + $task->initialise_stored_progress(); +} +``` + +#### Displaying the progress on a page {/* #displaying-the-progress-on-a-page */} + +Once a task has created a stored progress record (either via `start_stored_progress()` or `initialise_stored_progress()`), any page can load it by its unique idnumber and render it. The idnumber is generated by `stored_progress_bar::convert_to_idnumber()`, using the task's class name and, for adhoc tasks, its record ID. This is exactly the approach used by the "Tasks running now" report in [`admin/tool/task`](https://github.com/moodle/moodle/blob/MOODLE_502_STABLE/public/admin/tool/task/classes/running_tasks_table.php), which shows the live progress of every currently-running scheduled and adhoc task. + +```php +if ($task instanceof \core\task\adhoc_task) { + // For an adhoc task, the idnumber includes the task's record ID, so that concurrent + // executions of the same adhoc task each have their own progress bar. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_adhoc_task::class, $task->get_id()); +} else { + // For a scheduled task, there is only ever one instance running at a time, so the + // idnumber is based on the class name alone. + $idnumber = \core\output\stored_progress_bar::convert_to_idnumber(my_task::class); +} + +$bar = \core\output\stored_progress_bar::get_by_idnumber($idnumber); +if ($bar) { + // Renders the progress bar HTML, and queues up the `core/stored_progress` AMD + // module which polls the `core_output_poll_stored_progress` web service and + // updates the bar on screen until the task completes. + echo $bar->get_content(); +} else { + // There is no stored progress record, e.g. because the task has not started, or + // has already finished and been cleaned up. + echo get_string('nothingtodisplay'); +} +``` + +`get_content()` can be called from any page, at any time after the record has been created, including in a completely different request to the one that queued or ran the task - for example, an admin page which is refreshed and simply checks for the presence of a stored progress record matching a known idnumber. + +See the [Stored Progress Bars](../output/index.md#stored-progress-bars) section of the Output API documentation for more information, including how to poll and render the progress bar, and how to configure the polling interval. + ## For Administrators {/* #for-administrators */} Several tools exist for administrators: