在 Laravel 6 中,在队列任务中,当任务可以尝试的最大次数不支持大于 1 时,拆分队列任务

1、在 Laravel 6 中,在队列任务中,当任务可以尝试的最大次数大于 1 时,在第 2 次运行时失败:must be an instance of App\Models\Theme, null given。原因在于队列任务不支持再次尝试。如图1

图1

    /**
     * 任务可以尝试的最大次数。
     *
     * @var int
     */    public $tries = 2;
Symfony\Component\Debug\Exception\FatalThrowableError: Argument 1 passed to Modules\ThemeStoreDb\ThemeSetting\ThemeSettingMigration::migrateBladeSettingsData() must be an instance of App\Models\Theme, null given, called in E:\wwwroot\object\Modules\ThemeStoreDb\Handlers\ThemeHandler.php on line 129 in E:\wwwroot\object\Modules\ThemeStoreDb\ThemeSetting\ThemeSettingMigration.php:42
Stack trace:
#0 E:\wwwroot\object\Modules\ThemeStoreDb\Handlers\ThemeHandler.php(129): Modules\ThemeStoreDb\ThemeSetting\ThemeSettingMigration->migrateBladeSettingsData(NULL, Object(Modules\ThemeStoreDb\Entities\ThemeInstallationTask))
#1 E:\wwwroot\object\Modules\ThemeStoreDb\Handlers\ThemeHandler.php(64): Modules\ThemeStoreDb\Handlers\ThemeHandler->migrateSettingsData(Object(Modules\ThemeStoreDb\Entities\ThemeInstallation), Object(Modules\ThemeStoreDb\Entities\ThemeInstallationTask), Array)
#2 E:\wwwroot\object\Modules\ThemeStoreDb\Jobs\ThemeInstallationJob.php(203): Modules\ThemeStoreDb\Handlers\ThemeHandler->migrateThemeSettings(Object(Modules\ThemeStoreDb\Entities\ThemeInstallation), Object(Modules\ThemeStoreDb\Entities\ThemeInstallationTask))
#3 E:\wwwroot\object\Modules\ThemeStoreDb\Jobs\ThemeInstallationJob.php(90): Modules\ThemeStoreDb\Jobs\ThemeInstallationJob->migrateThemeSettings()
#4 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(36): Modules\ThemeStoreDb\Jobs\ThemeInstallationJob->handle()
#5 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Util.php(37): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#6 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#7 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#8 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Container.php(590): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#9 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php(94): Illuminate\Container\Container->call(Array)
#10 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(130): Illuminate\Bus\Dispatcher->Illuminate\Bus\{closure}(Object(Modules\ThemeStoreDb\Jobs\ThemeInstallationJob))
#11 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(105): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Modules\ThemeStoreDb\Jobs\ThemeInstallationJob))
#12 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php(98): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#13 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(83): Illuminate\Bus\Dispatcher->dispatchNow(Object(Modules\ThemeStoreDb\Jobs\ThemeInstallationJob), false)
#14 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(130): Illuminate\Queue\CallQueuedHandler->Illuminate\Queue\{closure}(Object(Modules\ThemeStoreDb\Jobs\ThemeInstallationJob))
#15 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(105): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Modules\ThemeStoreDb\Jobs\ThemeInstallationJob))
#16 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(85): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#17 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(59): Illuminate\Queue\CallQueuedHandler->dispatchThroughMiddleware(Object(Illuminate\Queue\Jobs\RedisJob), Object(Modules\ThemeStoreDb\Jobs\ThemeInstallationJob))
#18 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Jobs\Job.php(88): Illuminate\Queue\CallQueuedHandler->call(Object(Illuminate\Queue\Jobs\RedisJob), Array)
#19 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(368): Illuminate\Queue\Jobs\Job->fire()
#20 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(314): Illuminate\Queue\Worker->process('redis', Object(Illuminate\Queue\Jobs\RedisJob), Object(Illuminate\Queue\WorkerOptions))
#21 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(134): Illuminate\Queue\Worker->runJob(Object(Illuminate\Queue\Jobs\RedisJob), 'redis', Object(Illuminate\Queue\WorkerOptions))
#22 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Console\WorkCommand.php(112): Illuminate\Queue\Worker->daemon('redis', 'default', Object(Illuminate\Queue\WorkerOptions))
#23 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Console\WorkCommand.php(96): Illuminate\Queue\Console\WorkCommand->runWorker('redis', 'default')
#24 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(36): Illuminate\Queue\Console\WorkCommand->handle()
#25 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Util.php(37): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#26 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#27 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#28 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Container.php(590): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#29 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Command.php(134): Illuminate\Container\Container->call(Array)
#30 E:\wwwroot\object\vendor\symfony\console\Command\Command.php(255): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#31 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Command.php(121): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#32 E:\wwwroot\object\vendor\symfony\console\Application.php(1009): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#33 E:\wwwroot\object\vendor\symfony\console\Application.php(273): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#34 E:\wwwroot\object\vendor\symfony\console\Application.php(149): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#35 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Application.php(93): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#36 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php(131): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#37 E:\wwwroot\object\artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#38 {main}

2、队列任务在第 1 次运行时,删除了一些数据表中的记录。当第 2 次运行时,已经被删除掉的记录需要再次使用,进而导致在 第 2 次运行时失败。此处的兼容不好处理,最终决定拆分队列任务。

3、将需要再次尝试的任务环节拆分为一个单独的队列任务,设置任务可以尝试的最大次数大于 1。原有的队列任务,可以尝试的最大次数等于 1,以避免再次运行时的报错。

    /**
     * 任务可以尝试的最大次数。
     *
     * @var int
     */    public $tries = 1;

 // 推送任务到队列
 UploadThemeAssetToCdnJob::dispatch($this->themeInstallationTask, $this->absolutePath, $this->destination);
    /**
     * 任务可以尝试的最大次数。
     *
     * @var int
     */    public $tries = 3;

4、当拆分出的新的队列任务失败时,原有的队列任务尝试了 1 次,新的队列任务尝试了 3 次。符合预期。如图2

图2

PS E:\wwwroot\object> php artisan queue:work
[2023-04-06 17:01:50][FSn8E0VIfENgDzP2CydEHcP4ZKdub5vT] Processing: Modules\ThemeStoreDb\Jobs\ThemeInstallationJob
[2023-04-06 17:02:39][FSn8E0VIfENgDzP2CydEHcP4ZKdub5vT] Processed:  Modules\ThemeStoreDb\Jobs\ThemeInstallationJob
[2023-04-06 17:02:39][Tf9DYc8hDoW6f3GVH2889yb9ZA1jSyWX] Processing: Modules\ThemeStoreDb\Jobs\UploadThemeAssetToCdnJob
[2023-04-06 17:02:50][Tf9DYc8hDoW6f3GVH2889yb9ZA1jSyWX] Processing: Modules\ThemeStoreDb\Jobs\UploadThemeAssetToCdnJob
[2023-04-06 17:02:50][Tf9DYc8hDoW6f3GVH2889yb9ZA1jSyWX] Processing: Modules\ThemeStoreDb\Jobs\UploadThemeAssetToCdnJob
[2023-04-06 17:02:50][Tf9DYc8hDoW6f3GVH2889yb9ZA1jSyWX] Failed:     Modules\ThemeStoreDb\Jobs\UploadThemeAssetToCdnJob

5、当连续的 3 个队列任务皆成功后,每一个队列任务皆尝试了 1 次。符合预期。如图3

图3

PS E:\wwwroot\object> php artisan queue:work
[2023-04-06 17:21:13][mJUCYgune7X37F4pBxbBTfqvKzOTi1I4] Processing: Modules\ThemeStoreDb\Jobs\ThemeInstallationJob
[2023-04-06 17:21:56][mJUCYgune7X37F4pBxbBTfqvKzOTi1I4] Processed:  Modules\ThemeStoreDb\Jobs\ThemeInstallationJob
[2023-04-06 17:21:56][245oFV2O4NuYfD81b9gwKE4rnG6iuSCa] Processing: Modules\ThemeStoreDb\Jobs\UploadThemeAssetToCdnJob
[2023-04-06 17:22:02][245oFV2O4NuYfD81b9gwKE4rnG6iuSCa] Processed:  Modules\ThemeStoreDb\Jobs\UploadThemeAssetToCdnJob
[2023-04-06 17:22:02][htBRuBPcfiKFXebjeCLuk8Vf6Lx55I5I] Processing: Modules\ThemeStoreDb\Jobs\ThemeInstallationedJob
[2023-04-06 17:22:04][htBRuBPcfiKFXebjeCLuk8Vf6Lx55I5I] Processed:  Modules\ThemeStoreDb\Jobs\ThemeInstallationedJob
永夜