Laravel 11, очереди Spatie для многопользовательской архитектуры не срабатывают

Вопрос или проблема

Laravel 11, очереди Spatie для многопользовательской архитектуры не срабатывают

Я использую Laravel 11 с пакетом Spatie/Multi-tenancy для создания многоарендного SaaS-приложения.

Вот мой database.php

   'tenant' => [
        'driver' => 'mysql',
        'url' => env('DB_URL'),
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => null,
        'username' => env('DB_USERNAME', 'root'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => env('DB_CHARSET', 'utf8mb4'),
        'collation' => env('DB_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'),
        ]) : [],
    ],

    'landlord' => [
        'driver' => 'mysql',
        'url' => env('DB_URL'),
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => 'landlord_db',
        'username' => env('DB_USERNAME', 'root'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => env('DB_CHARSET', 'utf8mb4'),
        'collation' => env('DB_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'),
        ]) : [],
    ],

multitenancy.php

 'tenant_finder' =>  Spatie\Multitenancy\TenantFinder\DomainTenantFinder::class,
 'switch_tenant_tasks' => [
    // \Spatie\Multitenancy\Tasks\PrefixCacheTask::class,
     Spatie\Multitenancy\Tasks\SwitchTenantDatabaseTask::class,
    // \Spatie\Multitenancy\Tasks\SwitchRouteCacheTask::class,
],
'tenant_model' => Tenant::class,

'queues_are_tenant_aware_by_default' => true,

'tenant_database_connection_name' => 'tenant',

/*
 * Имя подключения для доступа к базе данных арендодателя.
 */
'landlord_database_connection_name' => 'landlord',

файл env

   DB_CONNECTION=tenant
   DB_HOST=mysql_db
   DB_PORT=3306
   DB_DATABASE=landlord_db
   DB_USERNAME=root
   DB_PASSWORD=root

app.php, сообщите, пожалуйста, если промежуточное ПО правильное

return Application::configure(basePath: dirname(__DIR__))
->withRouting(
    web: __DIR__ . '/../routes/web.php',
    api: __DIR__ . '/../routes/api.php',
    commands: __DIR__ . '/../routes/console.php',
    health: '/up',
)
  ->withMiddleware(function (Middleware $middleware) {
    $middleware->api(append: [
          \Spatie\Multitenancy\Http\Middleware\NeedsTenant::class,
           \Spatie\Multitenancy\Http\Middleware\EnsureValidTenantSession::class,
          \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Session\Middleware\StartSession::class,
    ]);
})
->withExceptions(function (Exceptions $exceptions) {

 })

моя проблема в том, что очереди не срабатывают:

    php artisan queue:work

Пожалуйста, дайте знать, если я что-то забыл или что-то упустил.

ошибка StackTrace:

[2024-09-20 20:05:25] local.ERROR: SQLSTATE[3D000]: Неверное имя каталога: 1046 База данных не выбрана (Соединение: tenant, SQL: select * from `jobs` where `queue` = high and ((`reserved_at` is null and `available_at` <= 1726862725) or (`reserved_at` <= 1726862635)) order by `id` asc limit 1 FOR UPDATE SKIP LOCKED) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 3D000): SQLSTATE[3D000]: Неверное имя каталога: 1046 База данных не выбрана (Соединение: tenant, SQL: select * from `jobs` where `queue` = high and ((`reserved_at` is null and `available_at` <= 1726862725) or (`reserved_at` <= 1726862635)) order by `id` asc limit 1 FOR UPDATE SKIP LOCKED) at /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:825)

[stacktrace]

Ответ или решение

Проблема, с которой вы столкнулись, заключается в том, что система очередей в вашем приложении Laravel 11 с использованием пакета Spatie Multi-Tenancy не может корректно переключаться на соединение с арендатором для выполнения запросов к базе данных. Судя по предоставленному вами стеку ошибок, сообщение указывает на то, что база данных не выбрана для соединения tenant.

Вот несколько шагов, которые помогут вам диагностировать и решить проблему:

1. Проверьте настройки соединения с базой данных

Убедитесь, что у вашего арендатор-соединения в config/database.php, значение для database корректно устанавливается на имя базы данных арендатора. В данный момент в конфигурации, вы указали database => null в секции tenant. Это, вероятно, является причиной ошибки "No database selected".

Примечание: Чтобы установить базу данных арендатора, нужно обновить код следующим образом:

'tenant' => [
    'driver' => 'mysql',
    'url' => env('DB_URL'),
    'host' => env('DB_HOST', '127.0.0.1'),
    'port' => env('DB_PORT', '3306'),
    'database' => 'имя_вашей_базы_данных_арендатора', // замените на соответствующее значение
    'username' => env('DB_USERNAME', 'root'),
    'password' => env('DB_PASSWORD', ''),
    'unix_socket' => env('DB_SOCKET', ''),
    'charset' => env('DB_CHARSET', 'utf8mb4'),
    'collation' => env('DB_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'),
    ]) : [],
],

Также, необходимо убедиться, что имя базы данных арендатора устанавливается динамически при его создании или переключении.

2. Настройте очереди для арендаторов

Важно, чтобы ваш код правильно переключал арендаторское соединение перед выполнением задач в очереди. Убедитесь, что в вашем Job используется правильная база данных арендатор при выполнении через очереди. Например:

class ExampleJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function handle()
    {
        // Проверка текущего соединения
        $tenant = app('currentTenant'); // Получите текущего арендатора

        // Здесь должен быть код, который выполняется в контексте арендатора
    }
}

3. Проверьте настройки multi-tenancy

Убедитесь, что вы правильно настроили пакет Spatie Multi-Tenancy для работы с очередями. В вашем файле config/multitenancy.php, параметр queues_are_tenant_aware_by_default установлен в true, что правильно. Однако важно также удостовериться, что все задачи работают с текущей базой данных арендатора.

4. Обнаружение арендатора в очередях

При запуске php artisan queue:work убедитесь, что правильный арендатор установлен в контексте, прежде чем вы обрабатываете задачи в очереди. Возможно, вам нужно будет использовать Tenant::find() или другой способ, чтобы определить текущего арендатора до начала обработки заданий напрямую.

5. Настройка middleware

Ваши правила для middleware, кажется, в порядке. Однако, если вы добавите \Spatie\Multitenancy\Http\Middleware\SwitchTenantDatabase::class в ваше API middleware, это обеспечит переключение базы данных арендатора.

Пример:

$middleware->api(append: [
    \Spatie\Multitenancy\Http\Middleware\NeedsTenant::class,
    \Spatie\Multitenancy\Http\Middleware\EnsureValidTenantSession::class,
    \Spatie\Multitenancy\Http\Middleware\SwitchTenantDatabase::class, // Добавьте этот middleware
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    \Illuminate\Session\Middleware\StartSession::class,
]);

Заключение

Проверьте указанные шаги, чтобы убедиться, что у вас корректно настроено соединение с базой данных арендатора и процессы обработки очередей. Основная проблема связана с тем, что очередь пытается выполнить запрос к базе данных, которая не определена. Убедитесь в правильном переключении баз данных для каждой задачи в очереди. После внесения всех изменений, не забудьте протестировать их и перезапустить рабочие процессы очереди.

Оцените материал
Добавить комментарий

Капча загружается...