Imagine a sequence of actions to be performed "in the background", in addition to creating the main logic.
For example, after user registration, you want to prepare demo data for their dashboard. You may want to put it into the background queue so the user won't wait for the operation to finish.
This is where Job classes come to help you.
Jobs are similar to Actions we discussed earlier, but Jobs may be put in a Queue. And they have Artisan command to create them:
php artisan make:job NewUserDataJob
And our job would look like this:
app/Jobs/NewUserDataJob.php:
class NewUserDataJob implements ShouldQueue{ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function __construct(public User $user) {} public function handle() { Project::create([ 'user_id' => $this->user->id, 'name' => 'Demo project 1', ]); Category::create([ 'user_id' => $this->user->id, 'name' => 'Demo category 1', ]); Category::create([ 'user_id' => $this->user->id, 'name' => 'Demo category 2', ]); }}
All that's left is to...
The question may be out of the scope of this lesson but how to make sure to keep data integrity when the job fails in this code :
let's suppose the user is created but the job fail creating related post. How to handle that ? Should we put the user creation and job dispatching of the project creation in database transaction ?
So in this case, I would actually move everything to the inside of a job with a transaction. That way it will be handled mostly automatically, instead of manually reverting :)
Of course, you could use batch jobs and chain them with catch condition, but... that is quite more work to do!
This is also outside of this course's scope but the last comment/answer got me wondering : So I guess testing becomes difficult when the DB::transaction() is involved as the transaction will include multiple responsibilities, right? How would you approach such situation? Thanks!
Hi, I'm not sure why this would make testing hard.
For example, your test assumes that when an action is called - there is
Nthings that happen. Right? Well, it doesn't matter if there was a DB::transaction() or not, as you still check for end result. And if there is no desired end result - your tests will fail.In other words, you don't care what happens under the hood most of the time. You care about:
If anything fails inside of there - you will still fail to see #3 pass. This does include all 500 errors or db failures/malformed data