diff --git a/application/extra/queue.php b/application/extra/queue.php index 1969703..4135cce 100644 --- a/application/extra/queue.php +++ b/application/extra/queue.php @@ -1,7 +1,7 @@ 'Redis', // Redis 驱动 - 'expire' => 0, // 任务的过期时间,默认为60秒; 若要禁用,则设置为 null + 'expire' => 180, // 任务的租期超时时间(秒),必须大于任务最大执行时间(如120s),防止执行中的任务被提前误判超时重投 // 任务的过期时间,默认为60秒; 若要禁用,则设置为 null 'default' => 'default', // 默认的队列名称 'host' => '127.0.0.1', // redis 主机ip 'port' => 6379, // redis 端口 diff --git a/tests/StabilityFixTest.php b/tests/StabilityFixTest.php index 69f0a96..c16469a 100644 --- a/tests/StabilityFixTest.php +++ b/tests/StabilityFixTest.php @@ -16,6 +16,7 @@ class StabilityFixTest self::testNotifyTimeParsing(); self::testAreaTreeAssembly(); self::testUserAddressDefenseLogic(); + self::testQueueConfigSafety(); echo "====================================================\n"; echo "【测试结论】所有稳定性测试均已通过!\n"; @@ -127,6 +128,26 @@ class StabilityFixTest echo "[PASS] 测试 3 通过: 用户收货地址防 IDOR 越权及空指针防御逻辑有效\n"; } + + /** + * 测试 4: 队列配置安全基线测试(杜绝 expire=0 导致的幽灵重复消费) + */ + public static function testQueueConfigSafety() + { + $queueConfigFile = dirname(__DIR__) . '/application/extra/queue.php'; + assert(file_exists($queueConfigFile), "queue.php 配置文件不存在"); + + $queueConfig = include $queueConfigFile; + assert(is_array($queueConfig), "queue.php 返回格式错误"); + + // 当 expire 为 0 时,think-queue 会在每个 tick 把正在执行的任务立即判定为已过期并重新投递,造成并发重复消费 + assert( + $queueConfig['expire'] === null || $queueConfig['expire'] >= 120, + "queue.php 的 expire 配置必须大于等于 120 秒或为 null,当前配置为 {$queueConfig['expire']},存在并发重复消费隐患" + ); + + echo "[PASS] 测试 4 通过: 队列超时与任务租期配置安全合规\n"; + } } if (php_sapi_name() === 'cli' && basename(__FILE__) === basename($_SERVER['SCRIPT_FILENAME'] ?? '')) {