Understanding dispatch delays0:00
Now, if we look at this simple code we wrote in the last episode, let's break it down. We're using this helper function called dispatch to send a closure through the queue using, we see right here, our Redis connection. Now we also learned that we can delay it. So for example, if I want to do it in five minutes, that's very easy to do so. If you'll give me just a moment, let's dig down to that helper function, dispatch, and you'll see here it returns a new pending dispatch instance. Now you'll see, when you give it the job here, you can specify the connection, the queue, all of that. You'll learn about some of this later.
all of that. You'll learn about some of this later. But notice there's our delay function. So when you think about it, we're calling dispatch, then we're delaying it, and it all still works because it doesn't actually send the dispatch until the __destruct magic method is triggered by PHP. It's kind of wonky, but cool nonetheless. Okay, anyways, so just as we can send a closure through the queue, it's very, very cool. But I think in more scenarios, you'll want to reference a specific class, a job class. So I'm going to run, let's list everything under the make namespace.
Generating a job class1:08
But I think in more scenarios, you'll want to reference a specific class, a job class. So I'm going to run, let's list everything under the make namespace. So you'll see we can call php artisan make:job. And don't forget, you can always use the help command if you want to figure out which arguments and options you can pass there. In this case, we need the name of the class and whether or not the job should be synchronous because by default, it's going through the queue. So if you don't want that to be the case, you must explicitly pass the --sync option. So let's make a job. And again, this is anything for your system that would take a good amount of time.
So let's make a job. And again, this is anything for your system that would take a good amount of time. Maybe reconcile accounts or you're going back to the beginning of their account creation and then fixing things. I don't know. It doesn't matter. So if I switch back to Sublime, you'll now see within your app directory, you have this new jobs folder that was created. And here's the class. So again, notice by default, it implements this ShouldQueue contract.
And here's the class. So again, notice by default, it implements this ShouldQueue contract. Now behind the scenes, Laravel will notice that, oh, it implements that contract. So it's not a synchronous job. It should go through the queue. Now if I were to do that again, though, and pass the sync option, take a look at this next one. It's far more simple because again, it doesn't need to go through the queue. It can if you want, but it's not doing that by default. Okay.
Dispatching and running jobs2:27
It can if you want, but it's not doing that by default. Okay. So anyways, once again, within the handle method, this is where you'd accept the user, you'd make some database calls, you send the need, whatever is necessary for your application. Once again, we will simulate it with a log. All right. So now let's dispatch this job. I'll switch back to my route. So let's get rid of this closure entirely. And instead, we will instantiate that ReconcileAccount class, and I'll import that at the
So let's get rid of this closure entirely. And instead, we will instantiate that ReconcileAccount class, and I'll import that at the top. Okay. Let's give it a run in the browser. So we run it. But again, don't forget, if we go to our storage/log file, we're not going to see it there, and that's because we've thrown a job onto the queue, but we don't yet have a worker knocking those jobs out. So let's say queue, set up a worker, and there we go.
Serializing Eloquent models3:13
knocking those jobs out. So let's say queue, set up a worker, and there we go. It found it, which means our job has now executed. Now here's another thing I'd like you to see. So if we go back to our Job class, you'll see this trait here, SerializesModels. So if you think about it, when we have an Eloquent model that's being passed through to the constructor, when you're sending it through a queue, that information needs to be saved and serialized and deserialized properly, which can be a little tricky. But this is what Laravel will do for you automatically. And you can see how that's being done behind the scenes if you're curious.
But this is what Laravel will do for you automatically. And you can see how that's being done behind the scenes if you're curious. But what this does mean though is let's imagine we're going to accept the User. Maybe this is the authenticated User. I'm just going to find somebody. It doesn't matter who. And by the way, I have run my migrations behind the scenes, and I have one or two users ready to go. Okay, so now our job class is going to accept the User, like so. Let's clean this up and assign it.
Okay, so now our Job class is going to accept the User, like so. Let's clean this up and assign it. So now I can say here when it finally gets handled, and let's just tack on the user's name. This user name. Okay, so let's run it again. I'll give it a refresh. Now our queue worker is still listening and working. So that's finished, which means if I return to our log file, there we go. We have our user.
So that's finished, which means if I return to our log file, there we go. We have our User. So again, don't underestimate how neat this is. When we're throwing a job onto the queue, and that job's constructor accepts an Eloquent model, this trait will take care of everything for you. So what it's going to do is it will detect, ah, you have an Eloquent model. So I'm just going to serialize the Eloquent model's ID, and that gets thrown on the queue. But then once the worker receives the job and begins the job, well, we deserialize the model back into the correct User instance, in this case, from the database. It's all seamless, which is really neat.
Injecting dependencies in handle5:10
model back into the correct User instance, in this case, from the database. It's all seamless, which is really neat. You don't even have to think about the complexities associated with that. Finally, one last thing. Like so many of the components in Laravel, for the handle method, we can type hint any dependencies we need, and Laravel will do its best to send them through to us. So for example, maybe I want, I don't know, the fileSystem class. If we type hint it, Laravel will use php reflection to detect that and automatically instantiate or resolve the fileSystem class and send it through to you. So now you can interact with it however you normally would.
or resolve the FileSystem class and send it through to you. So now you can interact with it however you normally would. Let's do a test. Write to the public path. Just a proof of concept there. So let's give it a refresh. Our queue is running, and, oh, actually, this will give us something to talk about. So if I switch over to the log, we can now see the second item there because the queue is running. However, if I go to the public directory, it does not pick that up.
Restarting queue workers6:18
is running. However, if I go to the public directory, it does not pick that up. So here's an important thing to understand. When you run php artisan queue:work, well, in fact, let's take a look. You'll see it begins processing jobs on the queue as a daemon or a daemon. That last part is the key there. This daemon is running in the background, and all of that code is stored in memory. So any changes you make are not going to be picked up until you restart the queue. This is why, ultimately, when you deploy your code, you want to make sure that you run php artisan queue:restart so that it will pick up all of the code changes you've made.
This is why, ultimately, when you deploy your code, you want to make sure that you run queue:restart so that it will pick up all of the code changes you've made. Or you can just close it out and rerun it. So now take a look. If we run this one more time, now we'll see, let's see, there it is, our log. And now, because we restarted, it does create that file. OK, let's wrap up for this episode. So now you learned, in addition to passing a closure to the dispatch function, you can alternatively, and probably more typically, reference a job class, which you create using php artisan make:job.
alternatively, and probably more typically, reference a job class, which you create using php artisan make:job. Now that job class can accept anything you want through the constructor. But if you also pass an EloquentModel, because the job class uses this trait, it will be serialized properly, and only the identifier of the EloquentModel will be thrown on the queue. Later, once it's pulled out and handled, it will be deserialized, and then, in this case, the User will be fetched, a fresh instance will come from the database. Finally, you learned the difference between php artisan queue:work and queue:listen. The main difference being, with queue:work, it's a long-running process in the background,
Finally, you learned the difference between php artisan queue:work and queue:listen. The main difference being, with queue:work, it's a long-running process in the background, and it's not going to pick up any changes to your code until you restart the worker.
