Laravel Queue Worker 无法解析动态单例绑定

Laravel dynamic singleton binding can't resolve by Queue Worker

在我的 Laravel 应用程序中,我必须进行第三方 API 调用,因此我将所有与第三方相关的详细信息存储在数据库中( URL 和密码, ETC。 )。为了让这个客户端在应用程序的任何地方都可用,我创建了服务提供者

ServiceProvider.php

 $thirdParties = ThirdParty::all();

 collect($thirdParties)->each(function ($thirdParty) {
            $this->app->singleton(Str::snake($thirdParty->name), function ($app) use($thirdParty) {
                $config = new Config();
                $config->setLoginUrl($thirdParty->auth_url)
                    ->setUsername($thirdParty->username)
                    ->setPassword($thirdParty->password);
                $client = new Client($config);
                $client->Login();
                return $client;
            });
        });

作为提供者的所有工作文件获取所有 Thrid Patry 并注册单例 class。应用程序用户还可以从 UI 添加新的第三方,所以现在为了制作单例,我将相同的代码与单个 $thirdParty.

问题

因此,当添加新的第三方时,应用程序将分派一个作业,我在其中使用相同 class 的相同 Singleton 实例。但是由于 Laravel 容器中的动态绑定,我的工作人员不知道如何解决这个问题并开始失败。

PS:重启 Queue worker 后一切正常。

感谢任何帮助或替代方法。 谢谢。

如果你 运行 你的队列工作器,它 运行 总是在后台(如果你有像 Supervisor 这样的监控进程),所以它会在第一次注册单例,如果你添加more Third-parties 之后,它将不再加载任何内容。因此,当您重新启动队列工作程序时,它就会开始工作。

您可以在 Laravel 文档中看到此建议,https://laravel.com/docs/5.8/queues#running-the-queue-worker

Remember, queue workers are long-lived processes and store the booted application state in memory. As a result, they will not notice changes in your code base after they have been started. So, during your deployment process, be sure to restart your queue workers.

希望对你有所帮助

此致。

如@Clemen 所述,队列工作者是一个 long-lived 进程,它是一个 PHP 实例,并且在您部署应用程序时已经启动了该应用程序。

每次第三方创建、更新和删除时,我都建议您 运行 Artisan::call('queue:restart')。您可以通过使用 Model Events 或在 APIs(Controller).

中手动执行此操作来实现此目的

当您更新它们时也存在问题,这是因为 API 的凭据将保持陈旧,因此您必须在创建、更新和删除时执行此操作。

示例:

class ThirdParty extends Model
{

    protected static function boot()
    {
        parent::boot();
        static::creating(function (ThirdParty $thirdParty) {
            Artisan::call('queue:restart');
        });
        static::updating(function (ThirdParty $thirdParty) {
            Artisan::call('queue:restart');
        });
        static::deleted(function (ThirdParty $thirdParty) {
            Artisan::call('queue:restart');
        });
    }
}