thinkphp-queue在使用过程中 遇到的一个教训

在项目中我们使用了适合于 thinphp5 的队列 thinphp-queue version v1.1.5。 正常执行没有问题,但是每隔一段时间就会有很多任务重试。经过排查发现是一个配置的问题。具体可以进入本文来查看一些事项。

关于 thinkphp-queue 的使用可以见这个网址 thinkphp-queue 笔记

我遇到的问题 就是因为一个配置 当我们在 thinkphpapplication 应用目录下创建一个 extra/queue.php时 我们一般这样创建

1
2
3
4
5
6
7
return [
'connector' => 'Database', // 数据库驱动
'expire' =>60, // 任务的过期时间,默认为60秒; 若要禁用,则设置为 null
'default' => 'pic', // 默认的队列名称
'table' => 'jobs', // 存储消息的表名,不带前缀
// 'dsn' => [],
];

我天真的以为这个任务过期时间时自动删掉任务的结果不是。
结果通过\think\queue\connector\Database::pop这个方法的一个判断得到这样的结果

1
2
3
if (!is_null($this->options['expire'])) {
$this->releaseJobsThatHaveBeenReservedTooLong($queue);
}

\think\queue\connector\Database::releaseJobsThatHaveBeenReservedTooLong 方法是这样写的(请注意:这个方法是 protected 所以无法在类外部直接调用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected function releaseJobsThatHaveBeenReservedTooLong($queue)
{
$expired = time() - $this->options['expire'];

$this->db->name($this->options['table'])
->where('queue', $this->getQueue($queue))
->where('reserved', 1)
->where('reserved_at', '<=', $expired)
->update([
'reserved' => 0,
'reserved_at' => null,
'attempts' => ['inc', 1]
]);
}

如果过期时间不是 null, 那么就重新将任务更新为未执行任务。
于是我悲哀的任务重复执行来了。。。
所以如果你的任务只执行一次,且你想保留任务的话可以将这个设置项 expire 设置为 null

  • Post author: hainuo
  • Post link: thinkphp-queue-used-in-thinkphp5
  • Copyright Notice: All articles in this blog are licensed under BY-NC-SA unless stating additionally.