首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >排队作业被卡住,表可能已锁定在Laravel中

排队作业被卡住,表可能已锁定在Laravel中
EN

Stack Overflow用户
提问于 2019-02-21 22:31:28
回答 1查看 1.1K关注 0票数 1

我在Laravel应用程序中使用队列发送电子邮件通知。我使用数据库作为队列驱动程序,因此有一个jobs DB表,如下所示:

id | queue | payload | attempts | reserved_at

在我重新启动MySQL后,它允许我删除行,并正确发送所有其他消息。

从表面上看,该行的内容(我仔细查看了payload字段)与所有其他行相同。

这是正在执行的作业:

public function handle()
{
    try {

        $this->order->sendOrderConfirmation();

    } catch( Exception $e ){

        Log::info('Unable to dispatch order confirmation email.', [
            'order'   => $this->order->id,
            'message' => $e->getMessage(),
            'code'    => $e->getCode(),
            'line'    => $e->getLine(),
            'file'    => $e->getFile()
        ]);

        $this->release();
    }
}

上面的日志消息在日志中找不到,但我在日志中找到的是:

SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts' at row 1 (SQL: update `jobs` set `reserved_at` = 1550737859, `attempts` = 256 where `id` = 1638) in /home/truvisi3/public_html/secure/vendor/laravel/framework/src/Illuminate/Database/Connection.php:647

看起来它正在尝试递增尝试计数器,但该字段被限制为255。好吧,但是为什么这会破坏整个队列,而不仅仅是这个过程呢?我能做些什么来阻止这种情况在未来发生(除了手动更改尝试列的格式以接受大量数字之外)?

编辑:这是作业类

class DispatchOrderConfirmationEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * @var Order
     */
    protected $order;
    public $tries = 10;

    /**
     * Create a new job instance.
     *
     * @param Order $order
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        try {

            $this->order->sendOrderConfirmation();

        } catch( Exception $e ){

            $this->release();
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2019-02-22 06:12:26

您需要定义排队作业的最大尝试次数,否则将无限期尝试。使用database驱动程序时,这意味着尝试次数可能超过MySQL TINYINT UNSIGNED字段的最大值,从而导致在第256次尝试时抛出数据库异常。

有两种方法可以做到这一点。

在启动工作进程时使用--tries

$ php artisan queue:work --tries=10

或在作业类上定义$tries属性:

public $tries = 10;

当两者都存在时,$tries属性优先。

最好总是使用--tries指定工作进程的最大尝试次数,这样排队的侦听器、邮件和任何其他使用您的队列的东西在多次尝试后最终都会失败,并在对特定作业有意义时使用$tries属性覆盖该限制。

您的自定义错误消息没有出现在日志中的原因是,当database队列驱动程序从队列中弹出作业时,它会更新attemptsreserved_at字段,然后将作业发送到worker类。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54809482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档