make(Dispatcher::class)); } public function __construct(Repository $config, QueueManager $queue) { $this->config = $config; $this->queue = $queue; $this->setUpPayloadGenerator(); } protected static function setUpJobListener($dispatcher) { $previousTenant = null; $dispatcher->listen(JobProcessing::class, function ($event) use (&$previousTenant) { $previousTenant = tenant(); static::initializeTenancyForQueue($event->job->payload()['tenant_id'] ?? null); }); $dispatcher->listen(JobRetryRequested::class, function ($event) use (&$previousTenant) { $previousTenant = tenant(); static::initializeTenancyForQueue($event->payload()['tenant_id'] ?? null); }); $revertToPreviousState = function ($event) use (&$previousTenant) { static::revertToPreviousState($event, $previousTenant); }; $dispatcher->listen(JobProcessed::class, $revertToPreviousState); // artisan('queue:work') which succeeds $dispatcher->listen(JobFailed::class, $revertToPreviousState); // artisan('queue:work') which fails } protected static function initializeTenancyForQueue($tenantId) { if (! $tenantId) { // The job is not tenant-aware, so we make sure tenancy isn't initialized. if (tenancy()->initialized) { tenancy()->end(); } return; } tenancy()->initialize(tenancy()->find($tenantId)); } protected static function revertToPreviousState($event, &$previousTenant) { $tenantId = $event->job->payload()['tenant_id'] ?? null; if (! $tenantId) { // The job was not tenant-aware, so there's nothing to revert return; } if (tenant() && $previousTenant && $previousTenant->is(tenant())) { // dispatchNow() was used and the tenant in the job is the same as the previous tenant return; } if (tenant() && $previousTenant && $previousTenant->isNot(tenant())) { // Revert back to the previous tenant (since Tenancy v3.8.5 this should should *likely* not happen) tenancy()->initialize($previousTenant); return; } if (tenant() && (! $previousTenant)) { // No previous tenant = previous context was central // NOTE: Since Tenancy v3.8.5 this should *likely* not happen tenancy()->end(); } } protected function setUpPayloadGenerator() { $bootstrapper = &$this; if (! $this->queue instanceof QueueFake) { $this->queue->createPayloadUsing(function ($connection) use (&$bootstrapper) { return $bootstrapper->getPayload($connection); }); } } public function bootstrap(Tenant $tenant) { // } public function revert() { // } public function getPayload(string $connection) { if (! tenancy()->initialized) { return []; } if ($this->config["queue.connections.$connection.central"]) { return []; } $id = tenant()->getTenantKey(); return [ 'tenant_id' => $id, ]; } }