|
11 | 11 | use Illuminate\Notifications\Events\NotificationSent; |
12 | 12 | use Illuminate\Queue\Events\JobAttempted; |
13 | 13 | use Illuminate\Queue\Events\JobProcessing; |
| 14 | +use Illuminate\Queue\Events\JobRetryRequested; |
14 | 15 | use Illuminate\Support\Arr; |
15 | 16 | use Illuminate\Support\Env; |
16 | 17 | use Illuminate\Support\Facades; |
@@ -236,52 +237,75 @@ public function register(): void |
236 | 237 | } |
237 | 238 |
|
238 | 239 | /** |
239 | | - * Register app-level events. |
| 240 | + * In multitenancy, we need to bootstrap a new app with the tenant id set. |
| 241 | + * This is because queue workers are long-running processes that are not |
| 242 | + * tenant aware. |
240 | 243 | */ |
241 | | - protected static function registerEvents(): void |
| 244 | + private static function bootstrapTenantApp(JobProcessing|JobRetryRequested $event): void |
242 | 245 | { |
243 | | - Facades\Event::listen(JobProcessing::class, function ($event) { |
244 | | - Context::hydrate($event->job->payload()['illuminate:log:context'] ?? null); |
245 | | - $tenantId = Context::get(config('multitenancy.current_tenant_context_key')); |
246 | | - if ($tenantId) { |
247 | | - if (!method_exists($event->job, 'getRedisQueue')) { |
248 | | - // Not a redis job |
249 | | - return; |
250 | | - } |
| 246 | + Context::hydrate($event->job->payload()['illuminate:log:context'] ?? null); |
| 247 | + $tenantId = Context::get(config('multitenancy.current_tenant_context_key')); |
| 248 | + if ($tenantId) { |
| 249 | + if (!method_exists($event->job, 'getRedisQueue')) { |
| 250 | + // Not a redis job |
| 251 | + return; |
| 252 | + } |
251 | 253 |
|
252 | | - // Save the landlord's config values so we can reset them later |
253 | | - if (self::$landlordValues === null) { |
254 | | - foreach (TenantBootstrapper::$landlordKeysToSave as $key) { |
255 | | - self::$landlordValues[$key] = $_SERVER[$key] ?? ''; |
256 | | - } |
| 254 | + // Save the landlord's config values so we can reset them later |
| 255 | + if (self::$landlordValues === null) { |
| 256 | + foreach (TenantBootstrapper::$landlordKeysToSave as $key) { |
| 257 | + self::$landlordValues[$key] = $_SERVER[$key] ?? ''; |
257 | 258 | } |
| 259 | + } |
258 | 260 |
|
259 | | - // Create a new tenant app instance |
260 | | - $_SERVER['TENANT'] = $tenantId; |
261 | | - $_ENV['TENANT'] = $tenantId; |
262 | | - $tenantApp = require app()->bootstrapPath('app.php'); |
263 | | - $tenantApp->instance('landlordValues', self::$landlordValues); |
264 | | - $tenantApp->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap(); |
| 261 | + // Create a new tenant app instance |
| 262 | + $_SERVER['TENANT'] = $tenantId; |
| 263 | + $_ENV['TENANT'] = $tenantId; |
| 264 | + $tenantApp = require app()->bootstrapPath('app.php'); |
| 265 | + $tenantApp->instance('landlordValues', self::$landlordValues); |
| 266 | + $tenantApp->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap(); |
265 | 267 |
|
266 | | - // Change the job's app service container to the tenant app |
267 | | - $event->job->getRedisQueue()->setContainer($tenantApp); |
268 | | - } |
269 | | - }); |
| 268 | + // Change the job's app service container to the tenant app |
| 269 | + $event->job->getRedisQueue()->setContainer($tenantApp); |
| 270 | + } |
| 271 | + } |
270 | 272 |
|
271 | | - Facades\Event::listen(JobAttempted::class, function ($event) { |
272 | | - if (!method_exists($event->job, 'getRedisQueue')) { |
273 | | - // Not a redis job |
274 | | - return; |
275 | | - } |
| 273 | + private static function resetTenantApp($event): void |
| 274 | + { |
| 275 | + if (!method_exists($event->job, 'getRedisQueue')) { |
| 276 | + // Not a redis job |
| 277 | + return; |
| 278 | + } |
276 | 279 |
|
277 | | - unset($_SERVER['TENANT']); |
278 | | - unset($_ENV['TENANT']); |
| 280 | + unset($_SERVER['TENANT']); |
| 281 | + unset($_ENV['TENANT']); |
279 | 282 |
|
280 | | - // Restore the original values since the tenant boostrapper modified them |
281 | | - foreach (self::$landlordValues as $key => $value) { |
282 | | - $_SERVER[$key] = $value; |
283 | | - $_ENV[$key] = $value; |
284 | | - } |
| 283 | + if (!self::$landlordValues) { |
| 284 | + return; |
| 285 | + } |
| 286 | + |
| 287 | + // Restore the original values since the tenant boostrapper modified them |
| 288 | + foreach (self::$landlordValues as $key => $value) { |
| 289 | + $_SERVER[$key] = $value; |
| 290 | + $_ENV[$key] = $value; |
| 291 | + } |
| 292 | + } |
| 293 | + |
| 294 | + /** |
| 295 | + * Register app-level events. |
| 296 | + */ |
| 297 | + protected static function registerEvents(): void |
| 298 | + { |
| 299 | + Facades\Event::listen(JobProcessing::class, function (JobProcessing $event) { |
| 300 | + self::bootstrapTenantApp($event); |
| 301 | + }); |
| 302 | + |
| 303 | + Facades\Event::listen(JobRetryRequested::class, function (JobRetryRequested $event) { |
| 304 | + self::bootstrapTenantApp($event); |
| 305 | + }); |
| 306 | + |
| 307 | + Facades\Event::listen(JobAttempted::class, function (JobAttempted $event) { |
| 308 | + self::resetTenantApp($event); |
285 | 309 | }); |
286 | 310 |
|
287 | 311 | // Listen to the events for our core screen |
|
0 commit comments