perHours

@param int   $hours
@param mixed $task

@return  ScheduleEvent

@throws \ReflectionException
@throws \Windwalker\DI\Exception\DependencyResolutionException

@since  __DEPLOY_VERSION__
559944
public function perHours(int $hours, $task): ScheduleEvent
    {
        return $this->cron(sprintf('0 */%d * * *', $hours), $task);
    }
342237
public function perMonths(int $months, $task): ScheduleEvent
    {
        return $this->cron(sprintf('0 0 1 */%d *', $months), $task);
    }
1269376
public function schedule($time = null)
    {
        if (is_null($time)) {
            $time = time();
        }
        $this->setStatus(Aoe_Scheduler_Model_Schedule::STATUS_PENDING)
            ->setCreatedAt(strftime('%Y-%m-%d %H:%M:%S', time()))
            ->setScheduledAt(strftime('%Y-%m-%d %H:%M:00', $time))
            ->save();
        return $this;
    }
1071364
public String schedule(TriggerTask task) {
        if (getCurrentScheduler() == null) {
            throw new IllegalStateException("New scheduler should be crea");
        }
        ScheduledFuture<?> future = getCurrentScheduler().schedule(task.getRunnable(), task.getTrigger());
        String id = Schedulers.getUUID();
        runningSchedullers.put(id, future);
        Schedulers.increaseNoOfRunningSchedullers();
        setCurrentScheduler(null);
        return id;
    }
663053
public function hourlyAt(int $minute, $task): ScheduleEvent
    {
        return $this->cron(sprintf('%d * * * *', $minute), $task);
    }
252072
public function endTask(Task $task)
    {
        if ($task->isShallow()) {
            return;
        }

        $endTime = round(microtime(true) * 1000);
        $millis = $endTime - $this->startTime;
        $seconds = floor($millis / 1000);
        $millis = $millis - $seconds * 1000;
        $taskTime = ($seconds > 0 ? "{$seconds}s " : "") . "{$millis}ms";

        $shouldReplaceTaskMark =
            $this->output->isDecorated() &&
            $this->output->getVerbosity() == OutputInterface::VERBOSITY_NORMAL &&
            !$this->output->getWasWritten();

        if ($shouldReplaceTaskMark) {
            $this->output->writeln("\r\033[K\033[1A\r<info>✔</info>");
        } else {
            if ($this->output->getVerbosity() == OutputInterface::VERBOSITY_NORMAL) {
                $this->output->writeln("<info>✔</info> Ok");
            } else {
                $this->output->writeln("<info>✔</info> Ok [$taskTime]");
            }
        }
    }
259202
public function disableTask(TaskInterface $task)
    {
        $task->setInterval($task->getInterval(), $task->getFirstExecution(), new \DateTime());

        return $this->abortPending($task);
    }
789182
public function setHour($hour)
 	{
		if(! in_array($hour, range(0, 23))) {
			throw new InvalidArgumentException('Hour must be between 0 and 23');
		}
 		$this->hour = $hour;
        return $this;
 	}
237422
public static function runTask($task)
    {
        $run = $task->createTaskRun();
        $run->setTaskId($task->getTaskId());
        $run->setTs(date('Y-m-d H:i:s'));
        $run->setStatus(TaskRunInterface::RUN_STATUS_STARTED);
        $run->saveTaskRun();
        $run_final_status = TaskRunInterface::RUN_STATUS_COMPLETED;

        ob_start();
        $time_begin = microtime(true);

        $result = self::parseAndRunCommand($task->getCommand());
        if (!$result) {
            $run_final_status = TaskRunInterface::RUN_STATUS_ERROR;
        }

        $output = ob_get_clean();
        $run->setOutput($output);

        $time_end = microtime(true);
        $time = round(($time_end - $time_begin), 2);
        $run->setExecutionTime($time);

        $run->setStatus($run_final_status);
        $run->saveTaskRun();
        return $output;
    }
1078297
protected function runTaskOverSSH(Task $task)
    {
        // If the pretending option has been set, we'll simply dump the script out to the command
        // line so the developer can inspect it which is useful for just inspecting the script
        // before it is actually run against these servers. Allows checking for errors, etc.
        if ($this->pretending()) {
            echo $task->script.PHP_EOL;

            return 1;
        } else {
            return $this->passToRemoteProcessor($task);
        }
    }
352279
public function schedule(Task $task, callable $callback = null)
    {
        // 特殊场景回调，如清理资源
        if ($callback !== null) {
            $task->resetCallBack($callback);
        }

        /* @var $task Task */
        $task->run();

        try {
            do {
                // 迭代器检查
                if (!$task->getRoutine() instanceof \Generator) {
                    break;
                }

                // 协程异步IO
                if ($task->getRoutine()->valid() && ($task->getRoutine()->current() instanceof IBase)) {
                    break;
                }

                // 继续调度
                if (!$task->isFinished()) {
                    $this->schedule($task);
                    break;
                }

                // 请求调度结束（考虑是否回调）
                $task->resetRoutine();
                if (is_callable($task->getCallBack())) {
                    $func = $task->getCallBack();
                    $task->resetCallBack();
                    $func();
                    break;
                }
            } while (0);
        } catch (\Throwable $e) {
            $task->handleTaskException($e, null);
            $this->schedule($task);
        }

        return $this;
    }
929991
public function cron(string $expression, $task): ScheduleEvent
    {
        return $this->events[] = $this->createEvent($expression, $task);
    }
1014109
private function _getCreateTaskContext(Task $task)
    {
        $result = new HttpCallContext();
        $result->setMethod(Resources::HTTP_POST);
        $result->setHeaders($this->_batchHeaders);
        $result->setUri($this->getUri());
        $result->setPath('/$1/Tasks');
        $result->setBody($this->wrapAtomEntry($task));
        $result->addStatusCode(Resources::STATUS_CREATED);

        return $result;
    }
898701
private function commit($task)
    {
        $lineConfig = false;
        $timetable = false;
        foreach ($task->getAmqpAcks() as $ack) {
            try {
                if ($ack->getPayload()->generated == true) {
                    $lineConfig = $this->getLineConfig($ack, $lineConfig);
                    $timetable = $this->getTimetable($ack, $lineConfig, $timetable);
                    $stopPoint = $this->getStopPoint($ack, $timetable);
                    if (empty($stopPoint)) {
                        $stopPoint = new StopPoint();
                        $stopPoint->setTimetable($timetable);
                        $stopPoint->setExternalId($ack->getPayload()->timetableParams->externalStopPointId);
                    }
                    $stopPoint->setPdfHash($ack->getPayload()->generationResult->pdfHash);
                    $pdfGenerationDate = new \DateTime();
                    $pdfGenerationDate->setTimestamp($ack->getPayload()->generationResult->created);
                    $stopPoint->setPdfGenerationDate($pdfGenerationDate);
                    $this->om->persist($stopPoint);
                    $this->mediaManager->saveStopPointTimetable(
                        $timetable,
                        $stopPoint->getExternalId(),
                        $ack->getPayload()->generationResult->filepath
                    );
                    $this->removeTmpMedia($timetable, $stopPoint->getExternalId());
                } elseif (isset($ack->getPayload()->error)) {
                    throw new \Exception('Ack error msg: ' . $ack->getPayload()->error);
                }
            } catch (\Exception $e) {
                $task->fail();
                echo "ERROR during task Completion, task n°" . $task->getId() . "\n";
                echo $e->getMessage() . "\n";
            }
        }
        $task->complete();
    }
722922
private Task taskToBeRescheduled(Task task) {
        Task taskToBeRetried = task.copy();
        taskToBeRetried.setTaskId(IDGenerator.generate());
        taskToBeRetried.setRetriedTaskId(task.getTaskId());
        taskToBeRetried.setStatus(SCHEDULED);
        taskToBeRetried.setRetryCount(task.getRetryCount() + 1);
        taskToBeRetried.setRetried(false);
        taskToBeRetried.setPollCount(0);
        taskToBeRetried.setCallbackAfterSeconds(0);
        task.setRetried(true);
        return taskToBeRetried;
    }
1349868
protected function add($task) {
		if (is_string($task)) {
			$task = new $task();
		}

		$class = get_class($task);
		if (!$task instanceof TaskInterface) {
			throw new InvalidArgumentException(
				"Cannot use '$class' as task, it is not implementing " . TaskInterface::class . '.'
			);
		}

		$this->tasks[$class] = $task;

		return $this;
	}
88870
public function scheduled_tasks_table($tasks) {
        global $CFG;

        $showloglink = \core\task\logmanager::has_log_report();

        $table = new html_table();
        $table->head = [
            get_string('name'),
            get_string('component', 'tool_task'),
            get_string('edit'),
            get_string('logs'),
            get_string('lastruntime', 'tool_task'),
            get_string('nextruntime', 'tool_task'),
            get_string('taskscheduleminute', 'tool_task'),
            get_string('taskschedulehour', 'tool_task'),
            get_string('taskscheduleday', 'tool_task'),
            get_string('taskscheduledayofweek', 'tool_task'),
            get_string('taskschedulemonth', 'tool_task'),
            get_string('faildelay', 'tool_task'),
            get_string('default', 'tool_task'),
        ];

        $table->attributes['class'] = 'admintable generaltable';
        $table->colclasses = [];

        if (!$showloglink) {
            // Hide the log links.
            $table->colclasses['3'] = 'hidden';
        }

        $data = array();
        $yes = get_string('yes');
        $no = get_string('no');
        $never = get_string('never');
        $asap = get_string('asap', 'tool_task');
        $disabledstr = get_string('taskdisabled', 'tool_task');
        $plugindisabledstr = get_string('plugindisabled', 'tool_task');
        $runnabletasks = tool_task\run_from_cli::is_runnable();
        foreach ($tasks as $task) {
            $customised = $task->is_customised() ? $no : $yes;
            if (empty($CFG->preventscheduledtaskchanges)) {
                $configureurl = new moodle_url('/admin/tool/task/scheduledtasks.php', array('action'=>'edit', 'task' => get_class($task)));
                $editlink = $this->action_icon($configureurl, new pix_icon('t/edit', get_string('edittaskschedule', 'tool_task', $task->get_name())));
            } else {
                $editlink = $this->render(new pix_icon('t/locked', get_string('scheduledtaskchangesdisabled', 'tool_task')));
            }

            $loglink = '';
            if ($showloglink) {
                $loglink = $this->action_icon(
                    \core\task\logmanager::get_url_for_task_class(get_class($task)),
                    new pix_icon('e/file-text', get_string('viewlogs', 'tool_task', $task->get_name())
                ));
            }

            $namecell = new html_table_cell($task->get_name() . "\n" . html_writer::tag('span', '\\'.get_class($task),
                array('class' => 'task-class text-ltr')));
            $namecell->header = true;

            $component = $task->get_component();
            $plugininfo = null;
            list($type, $plugin) = core_component::normalize_component($component);
            if ($type === 'core') {
                $componentcell = new html_table_cell(get_string('corecomponent', 'tool_task'));
            } else {
                if ($plugininfo = core_plugin_manager::instance()->get_plugin_info($component)) {
                    $plugininfo->init_display_name();
                    $componentcell = new html_table_cell($plugininfo->displayname);
                } else {
                    $componentcell = new html_table_cell($component);
                }
            }

            $lastrun = $task->get_last_run_time() ? userdate($task->get_last_run_time()) : $never;
            $nextrun = $task->get_next_run_time();
            $disabled = false;
            if ($plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled()) {
                $disabled = true;
                $nextrun = $plugindisabledstr;
            } else if ($task->get_disabled()) {
                $disabled = true;
                $nextrun = $disabledstr;
            } else if ($nextrun > time()) {
                $nextrun = userdate($nextrun);
            } else {
                $nextrun = $asap;
            }

            $runnow = '';
            if ( ! $disabled && get_config('tool_task', 'enablerunnow') && $runnabletasks ) {
                $runnow = html_writer::div(html_writer::link(
                        new moodle_url('/admin/tool/task/schedule_task.php',
                            array('task' => get_class($task))),
                        get_string('runnow', 'tool_task')), 'task-runnow');
            }

            $clearfail = '';
            if ($task->get_fail_delay()) {
                $clearfail = html_writer::div(html_writer::link(
                        new moodle_url('/admin/tool/task/clear_fail_delay.php',
                                array('task' => get_class($task), 'sesskey' => sesskey())),
                        get_string('clear')), 'task-clearfaildelay');
            }

            $row = new html_table_row(array(
                        $namecell,
                        $componentcell,
                        new html_table_cell($editlink),
                        new html_table_cell($loglink),
                        new html_table_cell($lastrun . $runnow),
                        new html_table_cell($nextrun),
                        new html_table_cell($task->get_minute()),
                        new html_table_cell($task->get_hour()),
                        new html_table_cell($task->get_day()),
                        new html_table_cell($task->get_day_of_week()),
                        new html_table_cell($task->get_month()),
                        new html_table_cell($task->get_fail_delay() . $clearfail),
                        new html_table_cell($customised)));

            // Cron-style values must always be LTR.
            $row->cells[6]->attributes['class'] = 'text-ltr';
            $row->cells[7]->attributes['class'] = 'text-ltr';
            $row->cells[8]->attributes['class'] = 'text-ltr';
            $row->cells[9]->attributes['class'] = 'text-ltr';
            $row->cells[10]->attributes['class'] = 'text-ltr';

            if ($disabled) {
                $row->attributes['class'] = 'disabled';
            }
            $data[] = $row;
        }
        $table->data = $data;
        return html_writer::table($table);
    }