diff --git a/app/Jobs/Job.php b/app/Jobs/Job.php index 51e56554..51d827fd 100644 --- a/app/Jobs/Job.php +++ b/app/Jobs/Job.php @@ -9,6 +9,14 @@ abstract class Job implements ShouldQueue { use Queueable; + // Set the execution timeout in seconds for jobs extending this class. + // This value takes precedence over the default timeout provided by the queue worker. + // Individual jobs may override this value. + // https://laravel.com/framework/docs/11.x/queues#timeout + // The timeout should be several seconds shorter than the queue connection's `retry_after` + // value. Otherwise, the job may be released back onto the queue, where another queue worker + // can attempt it, before the original has finished executing or timed out. + // https://laravel.com/framework/docs/11.x/queues#job-expirations-and-timeouts public $timeout = 60; public function backoff(): array { diff --git a/config/horizon.php b/config/horizon.php index c08e12a0..54435f12 100644 --- a/config/horizon.php +++ b/config/horizon.php @@ -190,7 +190,17 @@ 'maxShift' => intval(env('HORIZON_MAX_SHIFT', 1)), 'coolDown' => intval(env('HORIZON_COOL_DOWN', 3)), 'memory' => intval(env('HORIZON_MEMORY', 128)), + // Horizon passes "tries" to its queue workers as the default maximum number of attempts for + // a job. A job's `$tries` property or `tries()` method takes precedence over this default. + // https://laravel.com/framework/docs/11.x/queues#max-attempts 'tries' => intval(env('HORIZON_TRIES', 1)), + // Horizon passes "timeout" to its queue workers as the default job timeout in seconds. + // A job's `$timeout` property takes precedence over this default. + // https://laravel.com/framework/docs/11.x/queues#timeout + // A job's "timeout" value should be several seconds shorter than the queue connection's + // `retry_after` value. Otherwise, the job may be released back onto the queue, where another + // queue worker can attempt it, before the original has finished executing or timed out. + // https://laravel.com/framework/docs/11.x/queues#job-expirations-and-timeouts 'timeout' => intval(env('HORIZON_TIMEOUT', 3600)), ], ], diff --git a/config/queue.php b/config/queue.php index 359b97a4..24be72ca 100644 --- a/config/queue.php +++ b/config/queue.php @@ -63,6 +63,11 @@ 'driver' => 'redis', 'connection' => 'default', 'queue' => env('REDIS_QUEUE', 'default'), + // `retry_after` specifies how many seconds the queue connection should wait before a + // job that is being processed is released back onto the queue. This should be several + // seconds longer than every effective job or worker timeout to prevent jobs from being + // re-attempted by another queue worker before it has finished executing or timed out. + // https://laravel.com/framework/docs/11.x/queues#job-expirations-and-timeouts 'retry_after' => 100, 'block_for' => null, ], diff --git a/start.sh b/start.sh index d1a4e3b8..6025de86 100755 --- a/start.sh +++ b/start.sh @@ -21,6 +21,14 @@ elif [ "$role" = "queue" ] && [ "$HORIZON_ENABLED" = "1" ]; then elif [ "$role" = "queue" ]; then echo "Running the $queue_name queue..." + # The `--timeout` and `--tries` options are queue worker defaults. + # A job's `$tries` property or `tries()` method takes precedence over this `--tries` option. + # https://laravel.com/framework/docs/11.x/queues#max-attempts + # A job's `$timeout` property takes precedence over this `--timeout` option. + # https://laravel.com/framework/docs/11.x/queues#timeout + # A job's "timeout" value should always be less than the queue's `retry_after` value. + # Otherwise, the job may be re-attempted before it has actually finished executing or timed out. + # https://laravel.com/framework/docs/11.x/queues#job-expirations-and-timeouts php /var/www/html/artisan queue:work --verbose --tries=5 --timeout=90 --queue="$queue_name" elif [ "$role" = "scheduler" ]; then