Job Service Override

The job service override allows jobs to function as if they are being run within a tenants' tenancy, despite being run externally

Introduction

The job service override is an implementation of Sprouts service override functionality, that allows jobs to be processed within a tenants' tenancy.

If your job relies on tenant child models, specifically within the constructor, those models will be serialised and loaded fresh from the database when the job is run. Ordinarily this would cause several possible exceptions to be thrown, as the tenant child model functionality would kick in and complain that there's no current tenancy, let alone a current tenant.

Similar issues would occur if your job creates new child models without a current tenant, unless, of course, you're passing the tenant to the job too and manually setting that relation, which would be less than ideal.

This service override addresses both of these issues by setting not only the multitenanted context, but any tenancies and their tenants that were active when the job was dispatched.

How it works

This service override relies on the presence of the Sprout\Listeners\SetCurrentTenantContext tenancy bootstrapper, which adds the current tenant to Laravel's context functionality. When a job is dispatched to the queue, Laravel "dehydrates" the context and appends it to the job, allowing the job to inherit the context that was present when it was dispatched.

Before the queue processes a job, Laravel dispatches a Illuminate\Queue\Events\JobProcessing event, which this service override listens for. By the time this event is dispatched, the context has been "rehydrated", allowing this service override to load any tenancies and their tenants.

The context stores the tenants' key, so when the current tenant is set, it is loaded using its key. This process will bootstrap the tenancy, meaning that the job will have access to not only the current tenant, but any service overrides or other functionality that is enabled during that process.

Using

The only thing you need to do to use this service override, is to enable it in the services section of the sprout config, and dispatch a job while there's a current tenant.

1'services' => [
2 \Sprout\Overrides\JobOverride::class,
3],

Considerations

This service override is intentionally named the job service override, and not the queue service override, as that would be a very different set of functionality. This override deals only with individual jobs, not the queue as a whole.