tenancy / multi-tenant

Run multiple websites using the same Laravel installation while keeping tenant specific data separated for fully independent multi-domain setups, previously github.com/hyn/multi-tenant
https://tenancy.dev
MIT License
2.54k stars 391 forks source link

Queue: Tenant Override Not Working #777

Open ArlonAntonius opened 5 years ago

ArlonAntonius commented 5 years ago

This issue is meant for gathering information and doing research on the possibility that Auto Job Tenancy Overriding is not working.

Description

We added Auto Job Tenancy #711 in Version 5.4. In that version, we had the idea that users were able to override the job by adjusting the payload. Later on, we figured out that you're not easily able to override Laravel's Job Payload unless you're doing it in the way we did it. We adjusted the QueueProvider in 5.4.2 with #774.

@satyago reported that this might not be working.

Explanations / Detailed Info

Queue Provider Explanation

Job Creation

- Check if a website_id is provided in the payload if so, don't change anything
- If there is no website_id in the payload, get the current identified tenant from the env, add website_id to the payload if there is a tenant identified

Job Processing

- Grab the Payload
- Get the Data for the job that's inside the payload [Refer to my image in the T/T issue to understand what I exactly mean]
- Set a "key" variable to one of these in this priority order:
    - website_id provided in the data
    - website_id provided in the payload
    - null
- If the key is set:
    - Find a Tenant with that specific ID through the repo
    - Change the tenant

Use Cases

Ways to dispatch:

Actual behavior TBA

Expected behavior

TBA


Information


Terminology Payload: The full data set used by workers to do their work. Data: The set of information that's inside the payload, used by the job.

open-collective-bot[bot] commented 5 years ago

Hey :wave:,

Thank you for using our package.

We firmly believe that open sourcing our code improves the developer experience. In a pursuit to continue our work, help us by donating to our collective! :heart:

Issues opened by backers of our Open Collective will automatically labelled with the "backer" tag for priority response and resolve times.

https://opencollective.com/tenancy

satyago commented 5 years ago

Note: All examples below assume the job is accepting a nullable $website_id in its constructor and is using the following traits: Dispatchable, InteractsWithQueue, Queueable and SerializesModels.

Working Example (in hyn/multi-tenant version 5.4.2)

$job = new \App\Jobs\TenantAwareJob($website_id = 1);
\dispatch($job);

Needs Testing

$job = new \App\Jobs\TenantAwareJob($website_id = 1);
\dispatch_now($job);
\App\Jobs\TenantAwareJob::dispatch($website_id = 1);
\App\Jobs\TenantAwareJob::dispatch($website_id = 1)->onConnection('sync');
Plytas commented 5 years ago

781 should've fixed the issues with queue provider. 5.4.4 has been tagged.

Plytas commented 5 years ago

One issue remains regarding tenant override for queueables (notifications, mail...). We're currently checking if $website_id property was set on the command that is being processed. Queueables work differently as it's actually processing a different job (eg: SendQueuedNotifications) and that job has that Queueable inside it:

Array
(
    [displayName] => App\Notifications\TestNotification
    [job] => Illuminate\Queue\CallQueuedHandler@call
    [maxTries] => 
    [timeout] => 
    [timeoutAt] => 
    [data] => Array
        (
            [commandName] => Illuminate\Notifications\SendQueuedNotifications Object
                (
                    [notifiables] => Illuminate\Notifications\AnonymousNotifiable Object
                        (
                            [routes] => Array
                                (
                                    [mail] => example@test.com
                                )

                        )

                    [notification] => App\Notifications\TestNotification Object
                        (
                            [website_id] => 1
                            [id] => 9fd33198-a993-4f3e-a1b9-d2917f362ded
                            [locale] => 
                            [connection] => 
                            [queue] => 
                            [chainConnection] => 
                            [chainQueue] => 
                            [delay] => 
                            [chained] => Array
                                (
                                )

                        )

                    [channels] => Array
                        (
                            [0] => mail
                        )

                    [tries] => 
                    [timeout] => 
                    [connection] => 
                    [queue] => 
                    [chainConnection] => 
                    [chainQueue] => 
                    [delay] => 
                    [chained] => Array
                        (
                        )

                )

            [command] => Illuminate\Notifications\SendQueuedNotifications Object
                (
                    [notifiables] => Illuminate\Notifications\AnonymousNotifiable Object
                        (
                            [routes] => Array
                                (
                                    [mail] => example@test.com
                                )

                        )

                    [notification] => App\Notifications\TestNotification Object
                        (
                            [website_id] => 1
                            [id] => 9fd33198-a993-4f3e-a1b9-d2917f362ded
                            [locale] => 
                            [connection] => 
                            [queue] => 
                            [chainConnection] => 
                            [chainQueue] => 
                            [delay] => 
                            [chained] => Array
                                (
                                )

                        )

                    [channels] => Array
                        (
                            [0] => mail
                        )

                    [tries] => 
                    [timeout] => 
                    [connection] => 
                    [queue] => 
                    [chainConnection] => 
                    [chainQueue] => 
                    [delay] => 
                    [chained] => Array
                        (
                        )

                )

        )

)

Maybe a possible solution would be to write specific logic for these cases and fetch the website_id from the Queueable object inside it?