Queue Laravel with Multitenancy

Asked

Viewed 175 times

0

Boas Galera!

I have a multi database application where every schema is a client, everything works perfectly, except the queues. I am directing all Jobs to the main database, Jobs records are successfully logged, but returns failure to execute the:

php artisan queue:work
[2020-02-27 13:06:25][14] Processing: app\Jobs\SendEmail
[2020-02-27 13:06:25][14] Failed:     app\Jobs\SendEmail

observing the log that inhabits the /Storage/logs, I have the following return:

[previous exception] [object] (PDOException(code: 3D000): SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected at /var/www/html/projetos/my.project/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:61)

I am forcing the application to save the Jobs in the main database in this way:

Queue.php

'default' => env('QUEUE_CONNECTION', 'database'),

'connections' => [
           'database' => [
            'driver' => 'database',
            'connection'=>'mysql',
            'table' => 'jobs',
            'queue' => 'default',
            'retry_after' => 90,
        ],
],

database php.

'connections' => [


        'sqlite' => [
            'driver' => 'sqlite',
            'url' => env('DATABASE_URL'),
            'database' => env('DB_DATABASE', database_path('database.sqlite')),
            'prefix' => '',
            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
        ],

        'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'db_principal'),
            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
],

Meucontroller.php

(...)

SendEmail::dispatch($cliente->email,
                    $insertPedido,
                    $remetente->from_name,
                    $pagamento
                    );
(...)

app/Jobs/Sendemail.php

class SendEmail implements ShouldQueue

{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $destino;
    protected $pedido;
    protected $remetente;
    protected $pagamento;

    public function __construct(
        $destino, 
        $pedido, 
        $remetente,
        $pagamento)
    {
        $this->destino = $destino;
        $this->pedido = $pedido;
        $this->remetente = $remetente;
        $this->pagamento = $pagamento;

    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
            //executa a conexão tenant
            TenantManager::setConnection(Auth::user()->banco_dados);
            //carrega as cpnfigurações de SMTP do cliente 
            EmailConfig::emailConfig()
            $mailAgenda = Mail::to($this->destino)->send(new Email($this->pedido, 
                                                            $this->remetente, 
                                                            $this->pagamento)
                                                        );

    }
}

app/Mails/Email.php

class Email extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;

    protected $pedido;
    protected $remetente;
    protected $pagamento;

    public function __construct(
        $pedido, 
        $agenda,
        $remetente,
        $pagamento)
    {
        $this->pedido = $pedido;
        $this->remetente = $remetente;
        $this->pagamento = $pagamento;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.mail-markdown',
                                [
                                    'pedido' => $this->pedido,
                                    'remetente' => $this->remetente,
                                    'pagamento' => $this->pagamento
                                ]
                            );
    }
}

What am I doing wrong? Can anyone help me? Detail: each client has its own SMTP.

From now on I thank you!

  • Good guys! I was able to "solve" as follows:

1 answer

0


Good guys!

I was able to "solve" as follows:

a) I gave up dynamic smtp as it would not work due to spoof error that several smtps would generate in the same domain.

b) I gave up JOB, instead, I informed the situation with a table that stores all the content of the email.

c) I created an Observer that monitors the table that stores the contents of emails, every time a record is created it invokes a notification.

d) Static SMTP no . env

It worked! I know, it’s not elegant but for now solved this question.

And how I did it?

config/Queue.php

 'default' => env('QUEUE_CONNECTION', 'database'),
'connections' => [

           'database' => [
            'driver' => 'database',
            'connection' => 'mysql',
            'table' => 'jobs',
            'queue' => 'default',
            'retry_after' => 90,
        ],

    'failed' => [
        'database' => env('DB_CONNECTION', 'mysql'),
        'table' => 'failed_jobs',
    ],

.env

MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
[email protected]
MAIL_PASSWORD=@XXXXXXXX
MAIL_ENCRYPTION=tls
[email protected]
MAIL_FROM_NAME="${APP_NAME}"

Meucontroller.php

(...)
   GerenciaEmailController::mailNewOrder($pedido->id);  
 (...)    

app/Models/Gerenciaemail.php

use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;

    class GerenciaEmail extends Model
    {
        use Notifiable;

        protected $connection = 'mysql';
        protected $table = 'gerencia_emails';
        protected $primaryKey ='id';
        protected $fillable =[
            'payload',
            'action',
        ];
    }

It is very important to set this model to the main database with protected $Connection

Gerenciaemailcontroller.php

public static function mailNewOrder($pedido_id):void
{

        $pedido = Pedido::find($pedido_id);
        $payload = Array('pedido' => $pedido,
            'cliente' =>  $pedido->cliente,
            'produto'=> $pedido->produto,
        );

        $insertEmail = new GerenciaEmail;           
        $insertEmail->payload= json_encode($payload);
        $insertEmail->action='novo';
        $insertEmail->save();

}

Observermail.php

use App\Models\GerenciaEmail;
use App\Notifications\NotificarCliente;

class ObserverMail
{
     /**
         * Listen to the User created event.
         *
         * @param  GerenciaEmail  $gerenciaEmail
         * @return void
         */
        public function created(GerenciaEmail $gerenciaEmail)
        {
            $gerenciaEmail->notify(new NotificarCliente());
        }

}

Notifier.php

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class NotificarCliente extends Notification implements ShouldQueue
{
    use Queueable;


    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {   
            return (new MailMessage)
                        ->subject('SEU PEDIDO!')
                        ->markdown('emails.pedido-markdown', ['payload' => $notifiable->payload]);
    }
}

Register Observer in App Providers Appserviceprovider

public function boot()
    {
       Schema::defaultStringLength(191);
       GerenciaEmail::observe(ObserverMail::class);

    }

It seems like a trick, but it works like a beauty.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.