예제 #1
0
 /**
  * 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);
     }
 }
예제 #2
0
    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);
    }
}
    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);
    }
예제 #4
0
/**
 * 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");
}