Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properly handle queued mailables and notification. #78

Merged

Conversation

ivalkenburg
Copy link

@ivalkenburg ivalkenburg commented Jul 11, 2020

Mailables and notifications implementing ShouldQueue were not properly being handled. This fix should inject the tenant id into the wrapper jobs handling mailables and notifications.

To replicate make sure you have queues_are_tenant_aware_by_default set to false and your ShouldQueue mailable/notification implements TenantAware.

@masterix21
Copy link
Collaborator

@ivalkenburg i have created a mailable that implements ShouldQueue with:

@component('mail::message')
Welcome to {{ \Spatie\Multitenancy\Models\Tenant::current()->domain }}

Next, from tinker I have executed:

Tenant::first()->makeCurrent();
Mail::to('me@me.com')->queue(new \App\Mail\TenantHello());

Using Redis, the mail is delivered "tenant" aware. What I'm doing wrong that doesn't help me to understand the PR?

@ivalkenburg
Copy link
Author

That is probably because you have queues_are_tenant_aware_by_default set to true. Sorry i should've probably added to my initial post.

Setting queues_are_tenant_aware_by_default to false and adding TenantAware to ShouldQueue mailable like is intended will give you error that you're trying to get name from null object because no tenant is set. This happens because the wrapping job that wraps the mailable does not implement TenantAware. This should fix that.

@masterix21
Copy link
Collaborator

Sorry @ivalkenburg, but I don't understand why you need a tenant in a job if you say to the package that your jobs are not tenant-aware. Shouldn't be more simple to use queues_are_tenant_aware_by_default to true?

@ivalkenburg
Copy link
Author

ivalkenburg commented Jul 11, 2020

Sorry i don't understand what you mean. Setting queues_are_tenant_aware_by_default to false and queuing mailable which implements TenantAware will not change the context when the mail is being send.

Also if you wanted to queue a mailable or notification while having no tenant set (being a landlord for example) and queues_are_tenant_aware_by_default enabled it would throw CurrentTenantCouldNotBeDeterminedInTenantAwareJob exception because tenantId was injected with null value. Implementing NotTenantAware would have no effect if put on mailable or notification because they get wrapped in a handler job internally by laravel.

@masterix21
Copy link
Collaborator

masterix21 commented Jul 15, 2020

@ivalkenburg, what do you think about a configurable parser instead of a switch?

For example, you could add in the config it:

'queue_jobs_parser' => [
    SendQueuedMailable::class => fn ($job) => $job->mailable,
    SendQueuedNotifications::class => fn ($job) => $job->notification,
    // ...
],

And next you could change the switch with something like this:

if ($parser = config('multitenancy.queue_jobs_parser.'. get_class($job)) {
    $job = $parser($job);
}

It's an idea, and I'd like to listen to your opinion and what @freekmurze thinks.

@ivalkenburg
Copy link
Author

ivalkenburg commented Jul 15, 2020

Unfortunately you can not pass functions in configs, it would break config caching. serialize does not serialize functions. I guess if you wanted to do that you would have to define a class/method to do the parsing. But at this point you might as well do it in a method in MakeQueueTenantAwareAction and extend it if you wanted to add functionality.

@masterix21
Copy link
Collaborator

Yes, you're right. Sorry for it, but I hate the switch syntax (it's only a bug of mine 🤣)

@freekmurze
Copy link
Member

Can you rebase this PR with the current master and let me know if the PR is ready for review?

@ivalkenburg ivalkenburg force-pushed the tenantaware-mailables-notifications branch from 5250157 to 814b45a Compare July 22, 2020 21:39
@ivalkenburg
Copy link
Author

@freekmurze squashed and rebased, ready for review.

@freekmurze
Copy link
Member

@ivalkenburg thanks for this. Could you also add tests to make sure that this works?

@ivalkenburg
Copy link
Author

ivalkenburg commented Jul 25, 2020

I'm not seeing a way to test whether or not the mailable/notification and listener are in the correct context as I don't have access to the underlying job from said objects. And testing Tenant::current() is not reliable at all. Regular jobs are in tenant context for the existing tests as well. :( Hence the assert was left out in the tests and opted to inspect the actual payload instead.

@@ -79,4 +84,18 @@ protected function findTenant(JobProcessing $event): Tenant

return $tenant;
}

protected function getJobFromQueueable($queueable)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add an object typehint and string return type.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added type hint for object. Sorry i'm not used to using type hints a lot for primitives. Either way, there is no union type for the return type as it can return both a string (FQCN) as well as an object. Hence the reason I used class reflection to check whether or not they implement the necessary interfaces as it can accept a string or object.

@freekmurze
Copy link
Member

@masterix21 does this also look good to you?

@masterix21
Copy link
Collaborator

@freekmurze, as I previously said, I would have preferred a configurable solution (without callable, but in the style of your tasks logic) instead of extending the class to check with a switch if any new queuable is compatible. Anyway, now this is a bug, and it's better to resolve it: we will take all the time to find a better solution next.

I hope only that @ivalkenburg finds a way to test the code if it exists.

@masterix21
Copy link
Collaborator

@freekmurze, do you have any suggestions to test the PR? Or can we merge?

@freekmurze
Copy link
Member

Let's merge now and refactor later 👍

@masterix21 masterix21 merged commit 3770369 into spatie:master Jul 30, 2020
@masterix21
Copy link
Collaborator

@ivalkenburg, thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants