我在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();
}
}
}
发布于 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
队列驱动程序从队列中弹出作业时,它会更新attempts
和reserved_at
字段,然后将作业发送到worker类。
https://stackoverflow.com/questions/54809482
复制相似问题