You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel Job尝试因超时被终止时执行代码(Horizon)

捕获Laravel Job每次尝试的超时事件

要捕获Job每次尝试的超时并执行日志记录、用户通知,你可以通过以下方式实现:

核心思路

Laravel Job超时会抛出Illuminate\Queue\TimeoutException,你可以在handle方法中包裹业务逻辑并捕获该异常,结合attempts()方法判断当前尝试次数(小于总重试次数时),执行自定义逻辑后重新抛出异常,让队列系统正常触发重试流程。

代码实现

use Illuminate\Queue\TimeoutException;
use Throwable;

class MyJob implements ShouldQueue
{
    public $tries = 3;
    public $timeout = 600;
    
    // [...]

    public function handle()
    {
        try {
            // 这里编写你的Job核心业务逻辑
            $this->executeBusinessLogic();
        } catch (TimeoutException $e) {
            // 获取当前尝试次数,从1开始计数
            $currentAttempt = $this->attempts();
            
            // 仅在非最后一次尝试时执行通知与日志记录
            if ($currentAttempt < $this->tries) {
                // 记录超时日志
                logger()->warning("Job [{$this->job->getJobId()}] 第{$currentAttempt}次执行超时,即将进行重试");
                
                // 执行用户通知(示例:替换为你的实际通知逻辑)
                // UserAlert::send($targetUser, "任务执行超时,系统正在自动重试");
            }
            
            // 重新抛出异常,确保队列系统触发重试流程
            throw $e;
        } catch (Throwable $e) {
            // 如需处理其他异常导致的重试,可在此添加逻辑
            // 同样判断尝试次数后执行操作,再抛出异常触发重试
            throw $e;
        }
    }

    public function failed(Throwable $exception)
    {
        // 3次尝试全部失败后的最终处理逻辑
        logger()->error("Job [{$this->job->getJobId()}] 3次尝试均失败");
        // 通知用户任务最终失败
    }

    private function executeBusinessLogic()
    {
        // 你的具体业务代码
    }
}

额外说明

  • attempts()方法返回当前是第几次尝试(第一次执行返回1,第二次重试返回2,以此类推)。
  • 必须重新抛出异常,否则队列系统会判定Job执行成功,不会触发后续重试。
  • 如果需要区分“超时重试”和“其他异常重试”,可以分别捕获对应异常类做针对性处理。

内容的提问来源于stack exchange,提问作者Ifnot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:41:03