WithoutOverlapping для Queue в Larvel 5?

Здравствуй, %username%.

В L5 (как и в предыдущих версиях) есть замечательный schedule-ер, который позволяет запускать задачи (оформленные как команды для artisan) по расписанию, и на шаге инициализации задачи мы можем юзать замечательный "флаг" ->withoutOverlapping(), который предотвращает запуск команды, если она ещё не завершена, например:
$schedule
  ->command('queue:listen')
  ->everyMinute()
  ->withoutOverlapping();


А так же есть ещё более замечательная штука, как Queue (и реализация самих задач под названием Job). Так вот, возник вопрос - как обеспечить гарантию того, что один и тот же Job не будет запущен дважды в одну единицу времени? Так как операция запускается длительная в нем, существует вероятность что она будет выполнена дважды. Контекст её вызова пока не важен. Я сделал следующим образом:

// /app/Jobs/Job.php
<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class Job implements ShouldQueue {

  use InteractsWithQueue,
      Queueable,
      SerializesModels;

  /**
   * Get path to the 'lock' file.
   *
   * @return string
   */
  protected function getLockFilePath() {
    return storage_path('framework/schedule-' . md5(__NAMESPACE__ . get_class($this)) . '.lock');
  }

  /**
   * Lock current job (PREVENTING OVERLAPPING).
   *
   * @return boolean
   */
  protected function lock() {
    return touch($this->getLockFilePath());
  }

  /**
   * Disable locking.
   *
   * @return boolean
   */
  protected function unlock() {
    return unlink($this->getLockFilePath());
  }

  /**
   * Check - job is locked?
   *
   * @return boolean
   */
  protected function locked() {
    return file_exists($this->getLockFilePath());
  }

}


После чего наследую данный класс, и юзаю примерно так:

// /app/Jobs/SomeJob.php
<?php

namespace App\Jobs;

use App\Jobs\Job;

class SomeJob extends Job {

  /**
   * Execute the job.
   *
   * @return void
   */
  public function handle() {
    // PREVENTING OVERLAPPING
    if (!$this->locked()) {
      $this->lock();
      // LONG-LONG operation is here
      $this->unlock();
    }
  }

}


И вот вопрос - на сколько этот метод колхозный? Может я упустил что-то в документации к Ларке?
  • Вопрос задан
  • 924 просмотра
Пригласить эксперта
Ответы на вопрос 1
v_decadence
@v_decadence
Насколько я понимаю, во время работы
php artisan queue:work
Laravel смотрит в таблицу работ и запускает необработанные поочерёдно.
Поэтому, если Job добавлен один раз, более одного раза он выполнен не будет, если во время обработки не будет ошибок. Так что какие-то доработки здесь излишни.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы