简体   繁体   English

Laravel多租户职位

[英]Laravel multi-tenant jobs

Running into a problem where jobs cannot connect to the database. 遇到作业无法连接到数据库的问题。

Invalid catalog name: 1046 No database selected

I need to set the account in the job so I have an extended class to make sure the account is sent with the job so that I can ensure the database can connect to the correct database. 我需要在作业中设置帐户,所以我有一个扩展类来确保该帐户随作业一起发送,这样我就可以确保数据库可以连接到正确的数据库。

<?php

namespace App\Jobs;

use Illuminate\Support\Facades\DB;

abstract class Job
{
    protected $account;

    public function start()
    {
        // runs when creating the job, so the config holds the correct value
        $this->account = config('database.connections.tenant.database');
    }

    public function handle()
    {
        // since the handle function runs outside of setting the job 
        // the database is no longer set in the config
        config()->set('database.connections.tenant.database', $this->account);
        // try to force it to reconnect incase it already did for some reason.
        DB::reconnect();
    }
}

This is my current version I am playing around with, variations seem to not affect it. 这是我正在使用的当前版本,变化似乎不会对其产生影响。 I basically run start in the constructor and then make sure it runs the parent handle in the job so that it bootstraps the proper db configuration. 我基本上是在构造函数中运行start ,然后确保它在作业中运行父handle ,以便它引导正确的数据库配置。

The end result I am looking for is it to set the tenant database as account and when its running the job it uses that database for all queries. 我寻找的最终结果是将租户数据库设置为account并且在运行作业时将所有查询都使用该数据库。

Found out a way around this. 找到了解决此问题的方法。 Its not pretty but based on what I can see laravels queues just don't really handle this sort of thing well. 它不是很漂亮,但是基于我可以看到的laravel队列,实际上并不能很好地处理这种事情。

First I removed the override for the handle function, all I really needed was to make sure the account the queue needed to run on was available on the Job class. 首先,我删除了handle函数的替代,我真正需要的只是确保Job类上有运行队列所需的帐户。

abstract class Job
{
    protected $account;

    public function start()
    {
        // runs when creating the job, so the config holds the correct value
        $this->account = config('database.connections.tenant.database');
    }
}

Next I moved the switch to the correct tenant database to the AppServiceProvider in the boot method. 接下来,在boot方法中,将切换到正确的租户数据库移动到AppServiceProvider

Event::listen(JobProcessing::class, function ($event) {
   if ($payload = $event->job->payload()) {
      preg_match('/"account";s:[0-9]+:"(.*?)"/', $payload['data']['command'], $matches);
      if (count($matches)) {
         if (isset($matches[1])) {
            config()->set('database.connections.tenant.database', $matches[1]);
            config()->set('database.default', 'tenant');
         }
      }
   }
});

What i did here is look into the serialize object for the account with some regex. 我在这里所做的是使用一些正则表达式查看该帐户的序列化对象。 Might be improvements to be made here but so far works in testing. 可能需要在此处进行改进,但到目前为止在测试中仍然有效。 It then sets the correct database once it confirms the account. 确认帐户后,它将设置正确的数据库。

The reason I had to go this far is that the Job does queries when the job itself is serialized, so in order to pass the account it needed to be done before its serialized. 我必须走的原因是作业在序列化时会查询,因此为了传递帐户,需要在序列化之前完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM