laravel-multitenancy: Error dispatching queued jobs from artisan commands
Thanks for the great work, I have been using it for a short time and it has worked quite well except for putting a job in the queue when it is dispatched from an artisan command
Preconditions:
"php": "^7.4.0"
"laravel/framework": "^7.0",
- Database for each tenant
jobs
andjobs_failed
tables are in each tenant database- Queue connection environment var
QUEUE_CONNECTION=database
- multitenancy config file has this value for queues
'queues_are_tenant_aware_by_default' => true
\Spatie\Multitenancy\Tasks\SwitchTenantDatabaseTask::class
is registered in multitenancy file config
The command handler looks like:
class ImportUsers extends Command
{
... //removed to keep it short...
public function handle(PeopleImporter $import)
{
... //removed to keep it short
try {
DB::beginTransaction();
user = User::updateOrCreate($data);
if ($access->wasRecentlyCreated) {
// Push a queue job for publish a notification
dispatch(new PublishNewUser($access))->delay($this->delay);
} else {
// Push a queue job for publish a notification
dispatch(new PublishUserChanges($access))->delay($this->delay);
}
DB::commit();
} catch (\Throwable $exception) {
DB::rollBack();
Log::error($exception->getTraceAsString());
}
... //removed to keep it short
}
}
Using the tenants:artisan
command wrapper, my command signature looks like:
php artisan tenants:artisan "app:import-users --file=files/imports/users.csv" --tenant=1
I have verified that the users are correctly registered in the correct database schema for the specified tenant, but I always get an error when trying to push the job to the queue.
The exception trace is:
Running command for tenant `Sandbox` (id: 1)...
---------------------------------------------------------
Starting import
===============
0/10 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0%
Error: Call to a member function prepare() on null in /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:458
Stack trace:
#0 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(664): Illuminate\Database\Connection->Illuminate\Database\{closure}('insert into `jo...', Array)
#1 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(631): Illuminate\Database\Connection->runQueryCallback('insert into `jo...', Array, Object(Closure))
#2 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(465): Illuminate\Database\Connection->run('insert into `jo...', Array, Object(Closure))
#3 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php(417): Illuminate\Database\Connection->statement('insert into `jo...', Array)
#4 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php(32): Illuminate\Database\Connection->insert('insert into `jo...', Array)
#5 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php(2771): Illuminate\Database\Query\Processors\Processor->processInsertGetId(Object(Illuminate\Database\Query\Builder), 'insert into `jo...', Array, NULL)
#6 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/DatabaseQueue.php(162): Illuminate\Database\Query\Builder->insertGetId(Array)
#7 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/DatabaseQueue.php(111): Illuminate\Queue\DatabaseQueue->pushToDatabase('publish-access-...', '{"uuid":"a7cd02...', Object(Carbon\Carbon))
#8 /var/www/html/vendor/laravel/framework/src/Illuminate/Queue/Queue.php(60): Illuminate\Queue\DatabaseQueue->later(Object(Carbon\Carbon), Object(App\Jobs\PublishAccessChanges), '', 'publish-access-...')
#9 /var/www/html/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(171): Illuminate\Queue\Queue->laterOn('publish-access-...', Object(Carbon\Carbon), Object(App\Jobs\PublishAccessChanges))
#10 /var/www/html/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(158): Illuminate\Bus\Dispatcher->pushCommandToQueue(Object(Illuminate\Queue\DatabaseQueue), Object(App\Jobs\PublishAccessChanges))
#11 /var/www/html/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(73): Illuminate\Bus\Dispatcher->dispatchToQueue(Object(App\Jobs\PublishAccessChanges))
#12 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Bus/PendingDispatch.php(134): Illuminate\Bus\Dispatcher->dispatch(Object(App\Jobs\PublishAccessChanges))
#13 /var/www/html/app/Imports/PeopleImport.php(104): Illuminate\Foundation\Bus\PendingDispatch->__destruct()
#14 /var/www/html/vendor/maatwebsite/excel/src/Sheet.php(275): App\Imports\PeopleImport->onRow(Object(Maatwebsite\Excel\Row))
#15 /var/www/html/vendor/maatwebsite/excel/src/Reader.php(111): Maatwebsite\Excel\Sheet->import(Object(App\Imports\PeopleImport), 2)
#16 /var/www/html/vendor/maatwebsite/excel/src/Transactions/NullTransactionHandler.php(14): Maatwebsite\Excel\Reader->Maatwebsite\Excel\{closure}()
#17 /var/www/html/vendor/maatwebsite/excel/src/Reader.php(115): Maatwebsite\Excel\Transactions\NullTransactionHandler->__invoke(Object(Closure))
#18 /var/www/html/vendor/maatwebsite/excel/src/Excel.php(146): Maatwebsite\Excel\Reader->read(Object(App\Imports\PeopleImport), 'files/imports/p...', 'Csv', 's3')
#19 /var/www/html/vendor/maatwebsite/excel/src/Concerns/Importable.php(37): Maatwebsite\Excel\Excel->import(Object(App\Imports\PeopleImport), 'files/imports/p...', 's3', 'Csv')
#20 /var/www/html/app/Console/Commands/ImportPeople.php(66): App\Imports\PeopleImport->import('files/imports/p...', 's3', 'Csv')
#21 [internal function]: App\Console\Commands\ImportPeople->handle(Object(App\Imports\PeopleImport))
#22 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(33): call_user_func_array(Array, Array)
#23 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Util.php(36): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#24 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(91): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#25 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#26 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(592): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#27 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(134): Illuminate\Container\Container->call(Array)
#28 /var/www/html/vendor/symfony/console/Command/Command.php(258): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\StringInput), Object(Illuminate\Console\OutputStyle))
#29 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(121): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\StringInput), Object(Illuminate\Console\OutputStyle))
#30 /var/www/html/vendor/symfony/console/Application.php(911): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\StringInput), Object(Illuminate\Console\OutputStyle))
#31 /var/www/html/vendor/symfony/console/Application.php(264): Symfony\Component\Console\Application->doRunCommand(Object(App\Console\Commands\ImportPeople), Object(Symfony\Component\Console\Input\StringInput), Object(Illuminate\Console\OutputStyle))
#32 /var/www/html/vendor/symfony/console/Application.php(140): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\StringInput), Object(Illuminate\Console\OutputStyle))
#33 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Application.php(93): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\StringInput), Object(Illuminate\Console\OutputStyle))
#34 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Application.php(185): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\StringInput), Object(Illuminate\Console\OutputStyle))
#35 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(263): Illuminate\Console\Application->call('zintech:import:...', Array, Object(Illuminate\Console\OutputStyle))
#36 /var/www/html/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(261): Illuminate\Foundation\Console\Kernel->call('zintech:import:...', Array, Object(Illuminate\Console\OutputStyle))
#37 /var/www/html/vendor/spatie/laravel-multitenancy/src/Commands/TenantsArtisanCommand.php(56): Illuminate\Support\Facades\Facade::__callStatic('call', Array)
#38 /var/www/html/vendor/spatie/laravel-multitenancy/src/Commands/TenantsArtisanCommand.php(42): Spatie\Multitenancy\Commands\TenantsArtisanCommand->runArtisanCommandForTenant(Object(App\Models\Tenancy\Tenant), 'zintech:import:...')
#39 /var/www/html/vendor/laravel/framework/src/Illuminate/Support/Traits/EnumeratesValues.php(202): Spatie\Multitenancy\Commands\TenantsArtisanCommand->Spatie\Multitenancy\Commands\{closure}(Object(App\Models\Tenancy\Tenant), 0)
#40 /var/www/html/vendor/spatie/laravel-multitenancy/src/Commands/TenantsArtisanCommand.php(43): Illuminate\Support\LazyCollection->each(Object(Closure))
#41 [internal function]: Spatie\Multitenancy\Commands\TenantsArtisanCommand->handle()
#42 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(33): call_user_func_array(Array, Array)
#43 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Util.php(36): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#44 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(91): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#45 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#46 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(592): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#47 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(134): Illuminate\Container\Container->call(Array)
#48 /var/www/html/vendor/symfony/console/Command/Command.php(258): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#49 /var/www/html/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))
#50 /var/www/html/vendor/symfony/console/Application.php(911): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#51 /var/www/html/vendor/symfony/console/Application.php(264): Symfony\Component\Console\Application->doRunCommand(Object(Spatie\Multitenancy\Commands\TenantsArtisanCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#52 /var/www/html/vendor/symfony/console/Application.php(140): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#53 /var/www/html/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))
#54 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#55 /var/www/html/artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#56 {main}# php artisan tenants:artisan "app:import-users --file=files/imports/users.csv" --tenant=1
The result is the same if exec the command without database transactions
Do you have any idea how I can solve it?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (1 by maintainers)
No, im not using Redis for now, only database for this little project, but you are right the next step for a large app should be change to Redis or another service for now i don’t have many tenants that is why for now the solution that you helped me works well in my project, hopefully soon I will have to change to Redis, it would mean that everything is going very well with the project.
Thank you very much for your help.
Isn’t better to create only one jobs table in the landlord database? I think that’s more powerful: so, you can use Telescope to track all your jobs with no pain, for example.
Using that approach, you need to start a “queue:listen” for each tenant. I don’t know how many tenants you have, but for me, it’s a bit a wrong way.
Ok. Your jobs table is in landlord database? If so, change your database queue config following:
It seems that somewhere the app loses the connection with the database. Can you supply a more accurate example?
You wrote
php class ImportUsers...
but the error starts fromphp App\Console\Commands\ImportPeople...
.Finally, does your job implements the
Spatie\Multitenancy\Jobs\TenantAware
interface?