В системе ygin существует отдельная консольная команда, которое отвечает за выполнение периодических задач - scheduler.

Т.о. настроив один раз системный планировщик, например, cron, на запуск планировщика ygin, можно создавать неограниченное число задач. Рекомендуемое время для запуска приложения - один раз в минуту. Для тестирования работы планировщика во время разработки можно запустить его набрав в адресной строке: /yiic/scheduler/ (должен быть включен дебаг-режим).

По умолчанию в системе уже создана одна задача по отправке почтовых сообщений из очереди сообщений. Отдельно стоит отметить, что почтовые уведомления не отправляются сразу, но попадают сначала в стэк, и далее планировщиком доставляются до адресатов. Такая схема работы позволяет быть уверенным, что почтовые сообщения будут точно доставлены, даже если почтовый сервер какое-то время был не доступен.

Рассмотрим пример по созданию задачи планировщика, которая будет с определенной частотой получать данные с rss-ленты.

Для этого перейдем в раздел Разработка -> Планировщик и создадим новую задачу.

job-create.jpg

В примере заполнены минимально необходимые поля. Некоторые поля требуют дополнительных комментариев:

  • Интервал запуска задачи (в секундах) - задача будет запущена только в случае, если пройдет указанный здесь период времени с момента последнего запуска этой задачи
  • Интервал запуска задачи в случае ошибки (в секундах) - в случае если задача отработает с ошибкой (например хост с rss-лентой будет не доступен), то можно указать свой интервал запуска
  • Дата последнего запуска, Дата следущего запуска, Дата первого запуска - заполняются автоматически
  • Количество ошибок - поле также заполняется автоматически. При достижении 16 ошибок по отработке задачи, задача автоматически перестанет выполняться. При этом будут в логи записываться сообщения об ошибках, и отправляться уведомления на e-mail (если настроен такой тип логирования)
  • Имя класса задачи - yii-алиас класса, расширяющий класс SchedulerJob. Класс должен реализовывать метод run()
  • Приоритет запуска - можно указать приоритет запуска по отношению к другим задачам. Если планировщик видит, что стоит 2 задачи в очереди, требующие исполнения, то будет запущена та, у которой приоритет выше
  • Дата запуска текущего потока - заполняется автоматически
  • Максимальное число секунд выполнения задачи - если через указанное время задача будет всё ещё выполняться, то она будет отмечена как зависшая, и будут делать соответствующие записи в лог. Такие задачи необходимо вручную разблокировать

Задача считается выполненной успешно, если метод run() вернул константу self::RESULT_OK

Алгоритм работы планировщика следующий:

  • выбираются задачи, требующие по времени исполнения
  • все найденные задачи последовательно выполняются, при этом на каждую запись накладывается блокировка. Т.е. вы можете быть уверены, что в один момент времени задача будет запущена только один раз
  • после исполнения всех задач планировщик ещё раз делает выборку задач, которые нуждаются выполнения и делает так по циклу

И напоследок приведем заговку класса задачи:

class RssImportJob extends SchedulerJob {
  public function run() {
    // необходимая логика работы задачи
    return self::RESULT_OK;
  }
}
19 ноября 2013

Автор: Михаил Абрамов

Комментарии (9)

Добавить комментарий
  • Денис
    16.03.2016, 12:24:12

    Как писать логику работы в задаче?

    Как писать логику работы в задаче? Если, там нельзя вызвать ни модель, ни компонент и вообще практически ничего не работает, кроме какой то локальной логики типа baseUrl
    • Иван
      16.03.2016, 12:38:35

      Денис, а что вам мешает подключить модель, компонент и использовать их для работы?
      • Денис
        16.03.2016, 13:45:54

        Каким способом?
        Вот так?
        'import'=>array(
        'application.components.*',
        'application.models.*',
        'application.helpers.*',
        ),
        так не работает. пишет ошибку что файла с таким именем нет include(User.php)
        или воттак?
        Yii::import('application.components.HistorySender');
        подключая так, он начинает выдавать ошибку выше по всем унаследаванным классам
        • Иван
          16.03.2016, 14:11:48

          Денис, к сожалению я не могу вам ничем помочь, т.к. проблема не в Ygin, а конкретно в вашем коде. На мой взгляд со стороны, вы правильно используете команды импорта, но правильные ли вы указываете пути - я не знаю.

          Обратите внимание на то, что в консольных приложениях не подключается файл конфигурации project.php, поэтому все нужные модули необходимо подключать в console.php, возможно, ваша проблема связана с этим.
          • Денис
            16.03.2016, 14:20:22

            Иван, спасибо за то что вы отвечаете.
            Но помощь мне действительно нужна, и я уверен, что это в ваших силах.
            Давайте поступим проще.
            Можете ли вы показать пример как выглядят все необходимые файлы для вызова в команде скажем вот такого кода
            $model = Test::model()->findAll();
            • Иван
              16.03.2016, 14:56:57

              Yii::import('application.models.Test');
              class TestJob extends SchedulerJob {
              public function run() {
              $model = Test::model()->findAll();
              return self::RESULT_OK;
              }
              }
              • Денис
                16.03.2016, 15:05:42

                Вернулась ошибка

                Fatal error: Call to undefined method Partner::model() in C:\OpenServer\domains\lknew.loc\protected\components\DispatchHistorySender.php on line 5
                PHP Error[1]: Fatal error: Call to undefined method Partner::model()
                in file C:\OpenServer\domains\lknew.loc\protected\components\DispatchHistorySender.php at line 5
                #0 unknown(0): DaConsoleApplication->onShutdownHandler()

                Модель Partner есть, лежит в папке с остальными моделями
  • Денис
    17.03.2016, 12:02:38

    К сожалению пока вынужден использовать обычные контроллеры для работы моделей и запускать кроном с сервера эмулятором браузера.

    К слову в стандартных консольных командах yii так же ну удалось использовать модели и компоненты, весь гуглеш заканчивается примерно такой же информацией, как статье выше (// необходимая логика работы задачи), а как в этой логике вызвать модель не понятно.

    Не спорю что возможно секрет прост и кроется в одной строчке. но пока нет времени разгадывать его.

    Если кто-то знает, как сделать, то, о чем говорить в комментариях, буду очень благодарен, за пример или ссылку
    • Я
      07.10.2016, 10:53:21

      Scheduler

      В ответ на дискуссию выше: Просто импортируйте недостающие модели в задачу планировщика через Yii::import("application.models.ModelName");
      Или даже так: Yii::import("application.models.*");