public function test_get_next_adhoc_task() { $this->resetAfterTest(true); // Create an adhoc task. $task = new \core\task\adhoc_test_task(); // Queue it. $task = \core\task\manager::queue_adhoc_task($task); $now = time(); // Get it from the scheduler. $task = \core\task\manager::get_next_adhoc_task($now); $this->assertNotNull($task); $task->execute(); \core\task\manager::adhoc_task_failed($task); // Should not get any task. $task = \core\task\manager::get_next_adhoc_task($now); $this->assertNull($task); // Should get the adhoc task (retry after delay). $task = \core\task\manager::get_next_adhoc_task($now + 120); $this->assertNotNull($task); $task->execute(); \core\task\manager::adhoc_task_complete($task); // Should not get any task. $task = \core\task\manager::get_next_adhoc_task($now); $this->assertNull($task); }
public function definition() { $mform = $this->_form; /** @var \core\task\scheduled_task $task */ $task = $this->_customdata; $lastrun = $task->get_last_run_time() ? userdate($task->get_last_run_time()) : get_string('never'); $nextrun = $task->get_next_run_time(); if ($task->get_disabled()) { $nextrun = get_string('disabled', 'tool_task'); } else { if ($nextrun > time()) { $nextrun = userdate($nextrun); } else { $nextrun = get_string('asap', 'tool_task'); } } $mform->addElement('static', 'lastrun', get_string('lastruntime', 'tool_task'), $lastrun); $mform->addElement('static', 'nextrun', get_string('nextruntime', 'tool_task'), $nextrun); $mform->addElement('text', 'minute', get_string('taskscheduleminute', 'tool_task')); $mform->setType('minute', PARAM_RAW); $mform->addHelpButton('minute', 'taskscheduleminute', 'tool_task'); $mform->addElement('text', 'hour', get_string('taskschedulehour', 'tool_task')); $mform->setType('hour', PARAM_RAW); $mform->addHelpButton('hour', 'taskschedulehour', 'tool_task'); $mform->addElement('text', 'day', get_string('taskscheduleday', 'tool_task')); $mform->setType('day', PARAM_RAW); $mform->addHelpButton('day', 'taskscheduleday', 'tool_task'); $mform->addElement('text', 'month', get_string('taskschedulemonth', 'tool_task')); $mform->setType('month', PARAM_RAW); $mform->addHelpButton('month', 'taskschedulemonth', 'tool_task'); $mform->addElement('text', 'dayofweek', get_string('taskscheduledayofweek', 'tool_task')); $mform->setType('dayofweek', PARAM_RAW); $mform->addHelpButton('dayofweek', 'taskscheduledayofweek', 'tool_task'); $mform->addElement('advcheckbox', 'disabled', get_string('disabled', 'tool_task')); $mform->addHelpButton('disabled', 'disabled', 'tool_task'); $mform->addElement('advcheckbox', 'resettodefaults', get_string('resettasktodefaults', 'tool_task')); $mform->addHelpButton('resettodefaults', 'resettasktodefaults', 'tool_task'); $mform->disabledIf('minute', 'resettodefaults', 'checked'); $mform->disabledIf('hour', 'resettodefaults', 'checked'); $mform->disabledIf('day', 'resettodefaults', 'checked'); $mform->disabledIf('dayofweek', 'resettodefaults', 'checked'); $mform->disabledIf('month', 'resettodefaults', 'checked'); $mform->disabledIf('disabled', 'resettodefaults', 'checked'); $mform->addElement('hidden', 'task', get_class($task)); $mform->setType('task', PARAM_RAW); $mform->addElement('hidden', 'action', 'edit'); $mform->setType('action', PARAM_ALPHANUMEXT); $this->add_action_buttons(true, get_string('savechanges')); // Do not use defaults for existing values, the set_data() is the correct way. $this->set_data(\core\task\manager::record_from_scheduled_task($task)); }
/** * Store new setting * * @param mixed $data string or array, must not be NULL * @return string empty string if ok, string error message otherwise */ public function write_setting($data) { $oldvalue = get_config($this->plugin, $this->name); if ($oldvalue == $data && !empty($data)) { return ''; } if (!empty($data)) { $this->config_write($this->name, $data); $this->config_write('sharepoint_initialized', '0'); $sharepointinit = new \local_o365\task\sharepointinit(); \core\task\manager::queue_adhoc_task($sharepointinit); } else { // Support default value so it doesn't prompt for setting on install. $this->config_write($this->name, ''); } return ''; }
public function check_status(thresholds $thresholds, $params = array()) { if (!isset($params['task'])) { throw new invalid_service_exception("Task parameter required"); } if (!($task = \core\task\manager::get_scheduled_task($params['task']))) { throw new invalid_service_exception("Task not found"); } $result = new status_result(); $lastrun = $task->get_last_run_time(); if (!$lastrun) { $result->text = 'Task has never run'; $result->status = service::NAGIOS_STATUS_UNKNOWN; } else { $timeelapsed = time() - $lastrun; $result->status = $thresholds->check($timeelapsed); $result->text = "Last ran at " . date(DATE_RSS, $lastrun) . ", {$timeelapsed} seconds ago"; } return $result; }
/** * Called when an role has been removed. */ public static function roledeleted(\core\event\role_unassigned $event) { global $CFG; if (\panopto_data::get_panopto_course_id($event->courseid) === false || $CFG->version < $requiredVersion) { return; } $task = new \block_panopto\task\update_user(); $task->set_custom_data(array('courseid' => $event->courseid, 'relateduserid' => $event->relateduserid, 'contextid' => $event->contextid, 'eventtype' => "role")); if ($CFG->block_panopto_async_tasks) { \core\task\manager::queue_adhoc_task($task); } else { $task->execute(); } }
* - For debugging & better logging, you are encouraged to use in the command line: * -d log_errors=1 -d error_reporting=E_ALL -d display_errors=0 -d html_errors=0 * * Performance notes: * We have optimized it as best as we could for PostgreSQL and MySQL, with 27K students * we have seen this take 10 minutes. * * @package auth_cas * @copyright 2007 Jerome Gutierrez - based on code by Martin Langhoff * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @deprecated since Moodle 3.0 MDL-51824 - please do not use this CLI script any more, use scheduled task instead. * @todo MDL-50264 This will be deleted in Moodle 3.2. */ define('CLI_SCRIPT', true); require __DIR__ . '/../../../config.php'; require_once $CFG->dirroot . '/course/lib.php'; require_once $CFG->libdir . '/clilib.php'; // Ensure errors are well explained set_debugging(DEBUG_DEVELOPER, true); if (!is_enabled_auth('cas')) { error_log('[AUTH CAS] ' . get_string('pluginnotenabled', 'auth_ldap')); die; } cli_problem('[AUTH CAS] The sync users cron has been deprecated. Please use the scheduled task instead.'); // Abort execution of the CLI script if the auth_cas\task\sync_task is enabled. $task = \core\task\manager::get_scheduled_task('auth_cas\\task\\sync_task'); if (!$task->get_disabled()) { cli_error('[AUTH CAS] The scheduled task sync_task is enabled, the cron execution has been aborted.'); } $casauth = get_auth_plugin('cas'); $casauth->sync_users(true);
try { get_mailer('buffer'); $task->execute(); if (isset($predbqueries)) { mtrace("... used " . ($DB->perf_get_queries() - $predbqueries) . " dbqueries"); mtrace("... used " . (microtime(1) - $pretime) . " seconds"); } mtrace("Task completed."); \core\task\manager::scheduled_task_complete($task); get_mailer('close'); exit(0); } catch (Exception $e) { if ($DB->is_transaction_started()) { $DB->force_transaction_rollback(); } mtrace("... used " . ($DB->perf_get_queries() - $predbqueries) . " dbqueries"); mtrace("... used " . (microtime(true) - $pretime) . " seconds"); mtrace("Task failed: " . $e->getMessage()); if ($CFG->debugdeveloper) { if (!empty($e->debuginfo)) { mtrace("Debug info:"); mtrace($e->debuginfo); } mtrace("Backtrace:"); mtrace(format_backtrace($e->getTrace(), true)); } \core\task\manager::scheduled_task_failed($task); get_mailer('close'); exit(1); } }
/** * Run adhoc tasks. */ protected function run_adhock_tasks() { while ($task = \core\task\manager::get_next_adhoc_task(time())) { $task->execute(); \core\task\manager::adhoc_task_complete($task); } }
public function test_get_broken_scheduled_task() { global $DB; $this->resetAfterTest(true); // Delete all existing scheduled tasks. $DB->delete_records('task_scheduled'); // Add a scheduled task. // A broken task that runs all the time. $record = new stdClass(); $record->blocking = true; $record->minute = '*'; $record->hour = '*'; $record->dayofweek = '*'; $record->day = '*'; $record->month = '*'; $record->component = 'test_scheduled_task'; $record->classname = '\\core\\task\\scheduled_test_task_broken'; $DB->insert_record('task_scheduled', $record); $now = time(); // Should not get any task. $task = \core\task\manager::get_next_scheduled_task($now); $this->assertDebuggingCalled(); $this->assertNull($task); }
/** * Runs all ad-hoc tasks in the queue. * * This is faster and more reliable than running cron (running cron won't * work more than once in the same test, for instance). However it is * a little less 'realistic'. * * While the task is running, we suppress mtrace output because it makes * the Behat result look ugly. * * @Given /^I run all adhoc tasks$/ * @throws DriverException */ public function i_run_all_adhoc_tasks() { // Do setup for cron task. cron_setup_user(); // Run tasks. Locking is handled by get_next_adhoc_task. $now = time(); ob_start(); // Discard task output as not appropriate for Behat output! while (($task = \core\task\manager::get_next_adhoc_task($now)) !== null) { try { $task->execute(); // Mark task complete. \core\task\manager::adhoc_task_complete($task); } catch (Exception $e) { // Mark task failed and throw exception. \core\task\manager::adhoc_task_failed($task); ob_end_clean(); throw new DriverException('An adhoc task failed', 0, $e); } } ob_end_clean(); }
/** * Invalidates browser caches and cached data in temp. * * IMPORTANT - If you are adding anything here to do with the cache directory you should also have a look at * {@link phpunit_util::reset_dataroot()} * * @return void */ function purge_all_caches() { global $CFG, $DB; reset_text_filters_cache(); js_reset_all_caches(); theme_reset_all_caches(); get_string_manager()->reset_caches(); core_text::reset_caches(); if (class_exists('core_plugin_manager')) { core_plugin_manager::reset_caches(); } // Bump up cacherev field for all courses. try { increment_revision_number('course', 'cacherev', ''); } catch (moodle_exception $e) { // Ignore exception since this function is also called before upgrade script when field course.cacherev does not exist yet. } $DB->reset_caches(); cache_helper::purge_all(); // Purge all other caches: rss, simplepie, etc. clearstatcache(); remove_dir($CFG->cachedir . '', true); // Make sure cache dir is writable, throws exception if not. make_cache_directory(''); // This is the only place where we purge local caches, we are only adding files there. // The $CFG->localcachedirpurged flag forces local directories to be purged on cluster nodes. remove_dir($CFG->localcachedir, true); set_config('localcachedirpurged', time()); make_localcache_directory('', true); \core\task\manager::clear_static_caches(); }
/** * Test that the file_temp_cleanup_task removes directories and * files as expected. */ public function test_file_temp_cleanup_task() { global $CFG; // Create directories. $dir = $CFG->tempdir . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'backup01' . DIRECTORY_SEPARATOR . 'courses'; mkdir($dir, 0777, true); // Create files to be checked and then deleted. $file01 = $dir . DIRECTORY_SEPARATOR . 'sections.xml'; file_put_contents($file01, 'test data 001'); $file02 = $dir . DIRECTORY_SEPARATOR . 'modules.xml'; file_put_contents($file02, 'test data 002'); // Change the time modified for the first file, to a time that will be deleted by the task (greater than seven days). touch($file01, time() - (8 * 24 * 3600)); $task = \core\task\manager::get_scheduled_task('\\core\\task\\file_temp_cleanup_task'); $this->assertInstanceOf('\core\task\file_temp_cleanup_task', $task); $task->execute(); // Scan the directory. Only modules.xml should be left. $filesarray = scandir($dir); $this->assertEquals('modules.xml', $filesarray[2]); $this->assertEquals(3, count($filesarray)); // Change the time modified on modules.xml. touch($file02, time() - (8 * 24 * 3600)); // Change the time modified on the courses directory. touch($CFG->tempdir . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'backup01' . DIRECTORY_SEPARATOR . 'courses', time() - (8 * 24 * 3600)); // Run the scheduled task to remove the file and directory. $task->execute(); $filesarray = scandir($CFG->tempdir . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'backup01'); // There should only be two items in the array, '.' and '..'. $this->assertEquals(2, count($filesarray)); // Change the time modified on all of the files and directories. $dir = new \RecursiveDirectoryIterator($CFG->tempdir); // Show all child nodes prior to their parent. $iter = new \RecursiveIteratorIterator($dir, \RecursiveIteratorIterator::CHILD_FIRST); for ($iter->rewind(); $iter->valid(); $iter->next()) { $node = $iter->getRealPath(); touch($node, time() - (8 * 24 * 3600)); } // Run the scheduled task again to remove all of the files and directories. $task->execute(); $filesarray = scandir($CFG->tempdir); // All of the files and directories should be deleted. // There should only be two items in the array, '.' and '..'. $this->assertEquals(2, count($filesarray)); }
/** * Run adhoc tasks. */ protected function run_adhock_tasks() { while ($task = \core\task\manager::get_next_adhoc_task(time())) { $task->execute(); \core\task\manager::adhoc_task_complete($task); } $this->expectOutputRegex("/^Sending message to the user with id \\d+ for the subscription with id \\d+\\.\\.\\..Sent./ms"); }
/** * Execute task * * @global \moodle_database $DB * @global \stdClass $CFG * @return void * @throws \moodle_exception */ public function execute() { global $DB, $CFG; // Not going to work if we're missing settings. if (!isset($CFG->block_mailchimp_apicode) || !isset($CFG->block_mailchimp_listid) || !isset($CFG->block_mailchimp_linked_profile_field)) { return; } echo '== Beginning synchronization of MailChimp subscribers ==', "\n"; // Get all users in MailChimp and synchronize. echo 'Getting list of users in MailChimp.', "\n"; $listusers = \block_mailchimp\helper::getMembersSync(); if (!$listusers) { debugging("ERROR: Failed to get list of all members. Unable to synchronize users."); return; } // If there is an interest specified, filter out users who do not have this interest marked. if (isset($CFG->block_mailchimp_interest) && !$CFG->block_mailchimp_interest == "0") { foreach ($listusers['members'] as $key => $externaluser) { if ($externaluser['interests'][$CFG->block_mailchimp_interest] == false) { unset($listusers['members'][$key]); } } // Reindex the array $listusers['members'] = array_values($listusers['members']); } $listuserscount = count($listusers['members']); // Get list of users in Moodle echo 'Getting list of users in Moodle.', "\n"; $moodleusers = $DB->get_records('user'); $moodleuserscount = count($moodleusers); // Convert Moodle email addresses to lower case. Mailchimp stores emails in lower case and calculates the MD5 hash on the lower case email. foreach ($moodleusers as $moodleuser) { $moodleuser->email = strtolower($moodleuser->email); } // Sort MailChimp users list echo 'Sorting list of MailChimp users.', "\n"; foreach ($listusers['members'] as $key => $row) { $emails[$key] = $row['email_address']; } array_multisort($emails, SORT_ASC, $listusers['members']); unset($emails); // Sort Moodle users list echo 'Sorting list of Moodle users.', "\n"; foreach ($moodleusers as $key => $row) { $emails[$key] = $row->email; } array_multisort($emails, SORT_ASC, $moodleusers); unset($emails); // Syncronize the list of users in Moodle with those in Mailchimp echo '== Starting sync of Moodle users with users in MailChimp ==', "\n"; foreach ($moodleusers as $moodleusersynckey => $moodleuser) { $statuspercent = round($moodleusersynckey / $moodleuserscount * 100, 1, PHP_ROUND_HALF_UP); echo $statuspercent, "% \r"; if (isguestuser($moodleuser)) { continue; } $this->synchronize_user($moodleuser, $listusers); } echo 'Done.', "\n"; //Iterate through mailchimp list and compare to moodle users' emails. If the email is not found in moodle, delete from mailchimp list. echo '== Starting MailChimp list cleanup ==', "\n"; foreach ($listusers['members'] as $listuserskey => $externaluser) { $statuspercent = round($listuserskey / $listuserscount * 100, 1, PHP_ROUND_HALF_UP); echo $statuspercent, "% \r"; $this->synchronize_mcuser($externaluser, $moodleusers); } echo 'Done.', "\n"; echo '== Finished MailChimp syncronization ==', "\n"; // Clean up static caches, since this process runs for a long time and (potentially) changes many DB records. See https://docs.moodle.org/dev/Task_API#Caches \core\task\manager::clear_static_caches(); }
/** * Test future adhoc task execution. */ public function test_get_next_adhoc_task_future() { $this->resetAfterTest(true); $now = time(); // Create an adhoc task in future. $task = new \core\task\adhoc_test_task(); $task->set_next_run_time($now + 1000); \core\task\manager::queue_adhoc_task($task); // Fetching the next task should not return anything. $this->assertNull(\core\task\manager::get_next_adhoc_task($now)); // Fetching in the future should return the task. $task = \core\task\manager::get_next_adhoc_task($now + 1020); $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task); $task->execute(); \core\task\manager::adhoc_task_complete($task); }
/** * Execute cron tasks */ function cron_run() { global $DB, $CFG, $OUTPUT; if (CLI_MAINTENANCE) { echo "CLI maintenance mode active, cron execution suspended.\n"; exit(1); } if (moodle_needs_upgrading()) { echo "Moodle upgrade pending, cron execution suspended.\n"; exit(1); } require_once $CFG->libdir . '/adminlib.php'; if (!empty($CFG->showcronsql)) { $DB->set_debug(true); } if (!empty($CFG->showcrondebugging)) { set_debugging(DEBUG_DEVELOPER, true); } core_php_time_limit::raise(); $starttime = microtime(); // Increase memory limit raise_memory_limit(MEMORY_EXTRA); // Emulate normal session - we use admin accoutn by default cron_setup_user(); // Start output log $timenow = time(); mtrace("Server Time: " . date('r', $timenow) . "\n\n"); // Run all scheduled tasks. while (!\core\task\manager::static_caches_cleared_since($timenow) && ($task = \core\task\manager::get_next_scheduled_task($timenow))) { mtrace("Execute scheduled task: " . $task->get_name()); cron_trace_time_and_memory(); $predbqueries = null; $predbqueries = $DB->perf_get_queries(); $pretime = microtime(1); try { get_mailer('buffer'); $task->execute(); if ($DB->is_transaction_started()) { throw new coding_exception("Task left transaction open"); } if (isset($predbqueries)) { mtrace("... used " . ($DB->perf_get_queries() - $predbqueries) . " dbqueries"); mtrace("... used " . (microtime(1) - $pretime) . " seconds"); } mtrace("Scheduled task complete: " . $task->get_name()); \core\task\manager::scheduled_task_complete($task); } catch (Exception $e) { if ($DB && $DB->is_transaction_started()) { error_log('Database transaction aborted automatically in ' . get_class($task)); $DB->force_transaction_rollback(); } if (isset($predbqueries)) { mtrace("... used " . ($DB->perf_get_queries() - $predbqueries) . " dbqueries"); mtrace("... used " . (microtime(1) - $pretime) . " seconds"); } mtrace("Scheduled task failed: " . $task->get_name() . "," . $e->getMessage()); if ($CFG->debugdeveloper) { if (!empty($e->debuginfo)) { mtrace("Debug info:"); mtrace($e->debuginfo); } mtrace("Backtrace:"); mtrace(format_backtrace($e->getTrace(), true)); } \core\task\manager::scheduled_task_failed($task); } get_mailer('close'); unset($task); } // Run all adhoc tasks. while (!\core\task\manager::static_caches_cleared_since($timenow) && ($task = \core\task\manager::get_next_adhoc_task($timenow))) { mtrace("Execute adhoc task: " . get_class($task)); cron_trace_time_and_memory(); $predbqueries = null; $predbqueries = $DB->perf_get_queries(); $pretime = microtime(1); try { get_mailer('buffer'); $task->execute(); if ($DB->is_transaction_started()) { throw new coding_exception("Task left transaction open"); } if (isset($predbqueries)) { mtrace("... used " . ($DB->perf_get_queries() - $predbqueries) . " dbqueries"); mtrace("... used " . (microtime(1) - $pretime) . " seconds"); } mtrace("Adhoc task complete: " . get_class($task)); \core\task\manager::adhoc_task_complete($task); } catch (Exception $e) { if ($DB && $DB->is_transaction_started()) { error_log('Database transaction aborted automatically in ' . get_class($task)); $DB->force_transaction_rollback(); } if (isset($predbqueries)) { mtrace("... used " . ($DB->perf_get_queries() - $predbqueries) . " dbqueries"); mtrace("... used " . (microtime(1) - $pretime) . " seconds"); } mtrace("Adhoc task failed: " . get_class($task) . "," . $e->getMessage()); if ($CFG->debugdeveloper) { if (!empty($e->debuginfo)) { mtrace("Debug info:"); mtrace($e->debuginfo); } mtrace("Backtrace:"); mtrace(format_backtrace($e->getTrace(), true)); } \core\task\manager::adhoc_task_failed($task); } get_mailer('close'); unset($task); } mtrace("Cron script completed correctly"); gc_collect_cycles(); mtrace('Cron completed at ' . date('H:i:s') . '. Memory used ' . display_size(memory_get_usage()) . '.'); $difftime = microtime_diff($starttime, microtime()); mtrace("Execution took " . $difftime . " seconds"); }
/** * Course section deletion, using an adhoc task for deletion of the modules it contains. * 1. Schedule all modules within the section for adhoc removal. * 2. Move all modules to course section 0. * 3. Delete the resulting empty section. * * @param \stdClass $section the section to schedule for deletion. * @param bool $forcedeleteifnotempty whether to force section deletion if it contains modules. * @return bool true if the section was scheduled for deletion, false otherwise. */ function course_delete_section_async($section, $forcedeleteifnotempty = true) { global $DB, $USER; // Objects only, and only valid ones. if (!is_object($section) || empty($section->id)) { return false; } // Does the object currently exist in the DB for removal (check for stale objects). $section = $DB->get_record('course_sections', array('id' => $section->id)); if (!$section || !$section->section) { // No section exists, or the section is 0. Can't proceed. return false; } // Check whether the section can be removed. if (!$forcedeleteifnotempty && (!empty($section->sequence) || !empty($section->summary))) { return false; } $format = course_get_format($section->course); $sectionname = $format->get_section_name($section); // Flag those modules having no existing deletion flag. Some modules may have been scheduled for deletion manually, and we don't // want to create additional adhoc deletion tasks for these. Moving them to section 0 will suffice. $affectedmods = $DB->get_records_select('course_modules', 'course = ? AND section = ? AND deletioninprogress <> ?', [$section->course, $section->id, 1], '', 'id'); $DB->set_field('course_modules', 'deletioninprogress', '1', ['course' => $section->course, 'section' => $section->id]); // Move all modules to section 0. $modules = $DB->get_records('course_modules', ['section' => $section->id], ''); $sectionzero = $DB->get_record('course_sections', ['course' => $section->course, 'section' => '0']); foreach ($modules as $mod) { moveto_module($mod, $sectionzero); } // Create and queue an adhoc task for the deletion of the modules. $removaltask = new \core_course\task\course_delete_modules(); $data = array('cms' => $affectedmods, 'userid' => $USER->id, 'realuserid' => \core\session\manager::get_realuser()->id); $removaltask->set_custom_data($data); \core\task\manager::queue_adhoc_task($removaltask); // Delete the now empty section, passing in only the section number, which forces the function to fetch a new object. // The refresh is needed because the section->sequence is now stale. $result = $format->delete_section($section->section, $forcedeleteifnotempty); // Trigger an event for course section deletion. if ($result) { $context = \context_course::instance($section->course); $event = \core\event\course_section_deleted::create(array('objectid' => $section->id, 'courseid' => $section->course, 'context' => $context, 'other' => array('sectionnum' => $section->section, 'sectionname' => $sectionname))); $event->add_record_snapshot('course_sections', $section); $event->trigger(); } rebuild_course_cache($section->course, true); return $result; }
* -d log_errors=1 -d error_reporting=E_ALL -d display_errors=0 -d html_errors=0 * * Performance notes: * We have optimized it as best as we could for PostgreSQL and MySQL, with 27K students * we have seen this take 10 minutes. * * @package auth_ldap * @copyright 2004 Martin Langhoff * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @deprecated since Moodle 3.0 MDL-51824 - please do not use this CLI script any more, use scheduled task instead. * @todo MDL-50264 This will be deleted in Moodle 3.2. */ define('CLI_SCRIPT', true); require __DIR__ . '/../../../config.php'; // global moodle config file. require_once $CFG->dirroot . '/course/lib.php'; require_once $CFG->libdir . '/clilib.php'; // Ensure errors are well explained set_debugging(DEBUG_DEVELOPER, true); if (!is_enabled_auth('ldap')) { error_log('[AUTH LDAP] ' . get_string('pluginnotenabled', 'auth_ldap')); die; } cli_problem('[AUTH LDAP] The users sync cron has been deprecated. Please use the scheduled task instead.'); // Abort execution of the CLI script if the auth_ldap\task\sync_task is enabled. $taskdisabled = \core\task\manager::get_scheduled_task('auth_ldap\\task\\sync_task'); if (!$taskdisabled->get_disabled()) { cli_error('[AUTH LDAP] The scheduled task sync_task is enabled, the cron execution has been aborted.'); } $ldapauth = get_auth_plugin('ldap'); $ldapauth->sync_users(true);
/** * Executes all adhoc tasks in the queue. Useful for testing asynchronous behaviour. * * @return void */ public static function run_all_adhoc_tasks() { $now = time(); while (($task = \core\task\manager::get_next_adhoc_task($now)) !== null) { try { $task->execute(); \core\task\manager::adhoc_task_complete($task); } catch (Exception $e) { \core\task\manager::adhoc_task_failed($task); } } }
/** * Handle role_deleted event * * Does the following: * - Unfortunately the role has already been deleted when we hear about it here, and have no way to determine the affected * users. Therefore, we have to do a global sync. * * @param \core\event\role_deleted $event The triggered event. * @return bool Success/Failure. */ public static function handle_role_deleted(\core\event\role_deleted $event) { if (\local_o365\utils::is_configured() !== true) { return false; } $roleid = $event->objectid; // Role deletions can be heavy - run in cron. $spaccesssync = new \local_o365\task\sharepointaccesssync(); $spaccesssync->set_custom_data(['roleid' => '*', 'userid' => '*', 'contextid' => null]); \core\task\manager::queue_adhoc_task($spaccesssync); return true; }
public function test_complete_plans_task() { global $DB; $this->resetAfterTest(true); $this->setAdminUser(); $dg = $this->getDataGenerator(); $lpg = $dg->get_plugin_generator('core_competency'); $user = $dg->create_user(); $up1 = $lpg->create_plan(array('userid' => $user->id, 'status' => \core_competency\plan::STATUS_DRAFT)); $up2 = $lpg->create_plan(array('userid' => $user->id, 'status' => \core_competency\plan::STATUS_ACTIVE)); // Set duedate in the past. $date = new \DateTime('yesterday'); $record1 = $up1->to_record(); $record2 = $up2->to_record(); $record1->duedate = $date->getTimestamp(); $record2->duedate = $date->getTimestamp(); $DB->update_record(plan::TABLE, $record1); $DB->update_record(plan::TABLE, $record2); $task = \core\task\manager::get_scheduled_task('\\core\\task\\complete_plans_task'); $this->assertInstanceOf('\\core\\task\\complete_plans_task', $task); // Test that draft plan can not be completed on running task. $task->execute(); $plandraft = api::read_plan($up1->get_id()); $this->assertEquals(\core_competency\plan::STATUS_DRAFT, $plandraft->get_status()); // Test that active plan can be completed on running task. $task->execute(); $planactive = api::read_plan($up2->get_id()); $this->assertEquals(\core_competency\plan::STATUS_COMPLETE, $planactive->get_status()); }
/** * Run adhoc tasks. */ protected function run_adhock_tasks() { ob_start(); while ($task = \core\task\manager::get_next_adhoc_task(time())) { $task->execute(); \core\task\manager::adhoc_task_complete($task); } ob_clean(); // Suppress mtrace debugging info. }
/** * Runs a scheduled task immediately, given full class name. * * This is faster and more reliable than running cron (running cron won't * work more than once in the same test, for instance). However it is * a little less 'realistic'. * * While the task is running, we suppress mtrace output because it makes * the Behat result look ugly. * * Note: Most of the code relating to running a task is based on * admin/tool/task/cli/schedule_task.php. * * @Given /^I run the scheduled task "(?P<task_name>[^"]+)"$/ * @param string $taskname Name of task e.g. 'mod_whatever\task\do_something' */ public function i_run_the_scheduled_task($taskname) { $task = \core\task\manager::get_scheduled_task($taskname); if (!$task) { throw new DriverException('The "' . $taskname . '" scheduled task does not exist'); } // Do setup for cron task. raise_memory_limit(MEMORY_EXTRA); cron_setup_user(); // Get lock. $cronlockfactory = \core\lock\lock_config::get_lock_factory('cron'); if (!($cronlock = $cronlockfactory->get_lock('core_cron', 10))) { throw new DriverException('Unable to obtain core_cron lock for scheduled task'); } if (!($lock = $cronlockfactory->get_lock('\\' . get_class($task), 10))) { $cronlock->release(); throw new DriverException('Unable to obtain task lock for scheduled task'); } $task->set_lock($lock); if (!$task->is_blocking()) { $cronlock->release(); } else { $task->set_cron_lock($cronlock); } try { // Discard task output as not appropriate for Behat output! ob_start(); $task->execute(); ob_end_clean(); // Mark task complete. \core\task\manager::scheduled_task_complete($task); } catch (Exception $e) { // Mark task failed and throw exception. \core\task\manager::scheduled_task_failed($task); throw new DriverException('The "' . $taskname . '" scheduled task failed', 0, $e); } }
$task->set_month($defaulttask->get_month()); $task->set_day_of_week($defaulttask->get_day_of_week()); $task->set_day($defaulttask->get_day()); $task->set_disabled($defaulttask->get_disabled()); $task->set_customised(false); } else { $task->set_minute($data->minute); $task->set_hour($data->hour); $task->set_month($data->month); $task->set_day_of_week($data->dayofweek); $task->set_day($data->day); $task->set_disabled($data->disabled); $task->set_customised(true); } try { \core\task\manager::configure_scheduled_task($task); redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS); } catch (Exception $e) { redirect($PAGE->url, $e->getMessage(), null, \core\output\notification::NOTIFY_ERROR); } } else { echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('edittaskschedule', 'tool_task', $task->get_name())); $mform->display(); echo $OUTPUT->footer(); } } else { echo $OUTPUT->header(); $tasks = core\task\manager::get_all_scheduled_tasks(); echo $renderer->scheduled_tasks_table($tasks); echo $OUTPUT->footer();
function convert_with_ffmpeg_bg($filerecord, $tempdir, $tempfilename, $convfilenamebase, $convext) { global $CFG; //init our fs object $fs = get_file_storage(); $convfilename = $convfilenamebase . $convext; $placeholderfilename = "convertingmessage" . $convext; $filerecord->filename = $convfilename; $stored_file = $fs->create_file_from_pathname($filerecord, $CFG->dirroot . '/filter/poodll/' . $placeholderfilename); //we need this id later, to find the old draft file and remove it, in ad hoc task $filerecord->id = $stored_file->get_id(); // set up task and add custom data $conv_task = new \filter_poodll\task\adhoc_convert_media(); $qdata = array('filerecord' => $filerecord, 'filename' => $convfilename, 'tempdir' => $tempdir, 'tempfilename' => $tempfilename, 'convfilenamebase' => $convfilenamebase, 'convext' => $convext); $conv_task->set_custom_data($qdata); // queue it \core\task\manager::queue_adhoc_task($conv_task); //error_log('queeued:' . $convfilename); //error_log(print_r($qdata,true)); return $stored_file; }
public function test_get_next_scheduled_task() { global $DB; $this->resetAfterTest(true); // Delete all existing scheduled tasks. $DB->delete_records('task_scheduled'); // Add a scheduled task. // A task that runs once per hour. $record = new stdClass(); $record->blocking = true; $record->minute = '0'; $record->hour = '0'; $record->dayofweek = '*'; $record->day = '*'; $record->month = '*'; $record->component = 'test_scheduled_task'; $record->classname = '\core\task\scheduled_test_task'; $DB->insert_record('task_scheduled', $record); // And another one to test failures. $record->classname = '\core\task\scheduled_test2_task'; $DB->insert_record('task_scheduled', $record); // And disabled test. $record->classname = '\core\task\scheduled_test3_task'; $record->disabled = 1; $DB->insert_record('task_scheduled', $record); $now = time(); // Should get handed the first task. $task = \core\task\manager::get_next_scheduled_task($now); $this->assertInstanceOf('\core\task\scheduled_test_task', $task); $task->execute(); \core\task\manager::scheduled_task_complete($task); // Should get handed the second task. $task = \core\task\manager::get_next_scheduled_task($now); $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); $task->execute(); \core\task\manager::scheduled_task_failed($task); // Should not get any task. $task = \core\task\manager::get_next_scheduled_task($now); $this->assertNull($task); // Should get the second task (retry after delay). $task = \core\task\manager::get_next_scheduled_task($now + 120); $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); $task->execute(); \core\task\manager::scheduled_task_complete($task); // Should not get any task. $task = \core\task\manager::get_next_scheduled_task($now); $this->assertNull($task); }
/** * Upgrade moodle core * @param float $version target version * @param bool $verbose * @return void, may throw exception */ function upgrade_core($version, $verbose) { global $CFG, $SITE, $DB, $COURSE; raise_memory_limit(MEMORY_EXTRA); require_once($CFG->libdir.'/db/upgrade.php'); // Defines upgrades try { // Reset caches before any output. cache_helper::purge_all(true); purge_all_caches(); // Upgrade current language pack if we can upgrade_language_pack(); print_upgrade_part_start('moodle', false, $verbose); // Pre-upgrade scripts for local hack workarounds. $preupgradefile = "$CFG->dirroot/local/preupgrade.php"; if (file_exists($preupgradefile)) { core_php_time_limit::raise(); require($preupgradefile); // Reset upgrade timeout to default. upgrade_set_timeout(); } $result = xmldb_main_upgrade($CFG->version); if ($version > $CFG->version) { // store version if not already there upgrade_main_savepoint($result, $version, false); } // In case structure of 'course' table has been changed and we forgot to update $SITE, re-read it from db. $SITE = $DB->get_record('course', array('id' => $SITE->id)); $COURSE = clone($SITE); // perform all other component upgrade routines update_capabilities('moodle'); log_update_descriptions('moodle'); external_update_descriptions('moodle'); events_update_definition('moodle'); \core\task\manager::reset_scheduled_tasks_for_component('moodle'); message_update_providers('moodle'); \core\message\inbound\manager::update_handlers_for_component('moodle'); // Update core definitions. cache_helper::update_definitions(true); // Purge caches again, just to be sure we arn't holding onto old stuff now. cache_helper::purge_all(true); purge_all_caches(); // Clean up contexts - more and more stuff depends on existence of paths and contexts context_helper::cleanup_instances(); context_helper::create_instances(null, false); context_helper::build_all_paths(false); $syscontext = context_system::instance(); $syscontext->mark_dirty(); print_upgrade_part_end('moodle', false, $verbose); } catch (Exception $ex) { upgrade_handle_exception($ex); } }
/** * Handle calendar_unsubscribed event - queue calendar sync jobs for cron. * * @param \local_o365\event\calendar_unsubscribed $event The triggered event. * @return bool Success/Failure. */ public static function handle_calendar_unsubscribed(\local_o365\event\calendar_unsubscribed $event) { $eventdata = $event->get_data(); $calunsubscribe = new \local_o365\feature\calsync\task\syncoldevents(); $calunsubscribe->set_custom_data(['caltype' => $eventdata['other']['caltype'], 'caltypeid' => isset($eventdata['other']['caltypeid']) ? $eventdata['other']['caltypeid'] : 0, 'userid' => $eventdata['userid'], 'timecreated' => time()]); \core\task\manager::queue_adhoc_task($calunsubscribe); return true; }
/** * This method process all events stored in the buffer. * * This is a multi purpose api. It does the following:- * 1. Write event data to tool_monitor_events * 2. Find out users that need to be notified about rule completion and schedule a task to send them messages. */ public function process_buffer() { global $DB; $events = $this->flush(); // Flush data. $select = "SELECT COUNT(id) FROM {tool_monitor_events} "; $now = time(); $messagestosend = array(); $allsubids = array(); // Let us now process the events and check for subscriptions. foreach ($events as $eventobj) { $subscriptions = subscription_manager::get_subscriptions_by_event($eventobj); $idstosend = array(); foreach ($subscriptions as $subscription) { $starttime = $now - $subscription->timewindow; $starttime = $starttime > $subscription->lastnotificationsent ? $starttime : $subscription->lastnotificationsent; if ($subscription->courseid == 0) { // Site level subscription. Count all events. $where = "eventname = :eventname AND timecreated > :starttime"; $params = array('eventname' => $eventobj->eventname, 'starttime' => $starttime); } else { // Course level subscription. if ($subscription->cmid == 0) { // All modules. $where = "eventname = :eventname AND courseid = :courseid AND timecreated > :starttime"; $params = array('eventname' => $eventobj->eventname, 'courseid' => $eventobj->courseid, 'starttime' => $starttime); } else { // Specific module. $where = "eventname = :eventname AND courseid = :courseid AND contextinstanceid = :cmid\n AND timecreated > :starttime"; $params = array('eventname' => $eventobj->eventname, 'courseid' => $eventobj->courseid, 'cmid' => $eventobj->contextinstanceid, 'starttime' => $starttime); } } $sql = $select . "WHERE " . $where; $count = $DB->count_records_sql($sql, $params); if (!empty($count) && $count >= $subscription->frequency) { $idstosend[] = $subscription->id; // Trigger a subscription_criteria_met event. // It's possible that the course has been deleted since the criteria was met, so in that case use // the system context. Set it here and change later if needed. $context = \context_system::instance(); // We can't perform if (!empty($subscription->courseid)) below as it uses the magic method // __get to return the variable, which will always result in being empty. $courseid = $subscription->courseid; if (!empty($courseid)) { if ($coursecontext = \context_course::instance($courseid, IGNORE_MISSING)) { $context = $coursecontext; } } $params = array('userid' => $subscription->userid, 'courseid' => $subscription->courseid, 'context' => $context, 'other' => array('subscriptionid' => $subscription->id)); $event = \tool_monitor\event\subscription_criteria_met::create($params); $event->trigger(); } } if (!empty($idstosend)) { $messagestosend[] = array('subscriptionids' => $idstosend, 'event' => $eventobj); $allsubids = array_merge($allsubids, $idstosend); } } if (!empty($allsubids)) { // Update the last trigger flag. list($sql, $params) = $DB->get_in_or_equal($allsubids, SQL_PARAMS_NAMED); $params['now'] = $now; $sql = "UPDATE {tool_monitor_subscriptions} SET lastnotificationsent = :now WHERE id {$sql}"; $DB->execute($sql, $params); } // Schedule a task to send notification. if (!empty($messagestosend)) { $adhocktask = new notification_task(); $adhocktask->set_custom_data($messagestosend); $adhocktask->set_component('tool_monitor'); \core\task\manager::queue_adhoc_task($adhocktask); } }
private function process_publish_allocations() { $now = time(); if ($this->ratingallocate->accesstimestop < $now) { global $USER, $OUTPUT; $this->origdbrecord->{this_db\ratingallocate::PUBLISHED} = true; $this->origdbrecord->{this_db\ratingallocate::PUBLISHDATE} = time(); $this->origdbrecord->{this_db\ratingallocate::NOTIFICATIONSEND} = -1; $this->ratingallocate = new ratingallocate_db_wrapper($this->origdbrecord); $this->db->update_record(this_db\ratingallocate::TABLE, $this->origdbrecord); // create the instance $domination = new mod_ratingallocate\task\send_distribution_notification(); // set blocking if required (it probably isn't) // $domination->set_blocking(true); // add custom data $domination->set_component('mod_ratingallocate'); $domination->set_custom_data(array('userid' => $USER->id, 'ratingallocateid' => $this->ratingallocateid)); // queue it \core\task\manager::queue_adhoc_task($domination); //Logging $event = \mod_ratingallocate\event\allocation_published::create_simple(context_course::instance($this->course->id), $this->ratingallocateid); $event->trigger(); /* @var $renderer mod_ratingallocate_renderer */ $renderer = $this->get_renderer(); $renderer->add_notification(get_string('distribution_published', ratingallocate_MOD_NAME), self::NOTIFY_SUCCESS); return $this->process_default(); } }