This episode is for members only

Sign up to access "Job Batching Progress with Laravel" right now.

Get started
Already a member? Sign in to continue
Playing
17. Manually stopping the batch

Transcript

00:00
While a server is being provisioned, we want the ability to destroy this server,
00:04
which is going to cancel the batch and stop any subsequent jobs from running. Let's go ahead and create a button for when our server is being provisioned. And then we'll go and look at how we handle this cancellation. So back over to where, if it's not provisioned, we'll add a button just up here.
00:22
So let's go ahead and use the X primary button to create out a button to destroy this. And of course you can add any kind of button in here you want. So let's call this destroy server. And we'll hook this directly up to a destroy server
00:38
method over on our component. And this could be even after the server has been provisioned as well. It's entirely up to you. Okay. So if we head over to the show server component, let's create out this
00:51
destroy server method. And the first thing we want to do is grab the batch because we want to cancel off the batch using the batch from the database before we go ahead and delete the server. So for this,
01:04
because we are potentially accessing this batch multiple times, let's go ahead and create a batch computed property up here. Let's spell that properly. And we'll go ahead and make this computed. So we don't need to keep pulling it every single time. Okay.
01:19
So how do we grab a batch? Well, we know that we have a batch ID stored on each of our servers. This one's provisioned and complete. So it doesn't have one at the moment, but we can access that from the server batch.
01:33
So we can either do this directly in here using the bus facade and we can find a batch by its ID. So in our case, let's go ahead and say this server batch ID, or we can create a helper on our server to return this to us in case we
01:51
need to grab it anywhere else in our application. Let's go ahead and do that now. So I'm just going to say this server and batch, and let's go over to our server model and let's create out a method to grab
02:04
this. And that means that we can just access it anywhere that we need. So let's go ahead and return exactly what we did here, but of course, just reference this batch ID, and that will go ahead and find that batch for us. If we don't have a batch ID, this needs to return null.
02:17
So let's make sure we do that now. So we can just save this batch ID is not there. Let's just return null. And then when we get it here, we always know that we could potentially get a null value.
02:29
So we can add some if statements around that. Now that we've got a reference to the batch, which we saw earlier with all of these methods like progress in, we can just use this to output anything we want on the UI,
02:40
or we can call any actions on this, just so we're completely clear. Let's go over to our show server section and let's just grab the batch and output the progress directly in the UI as this gets provisioned. So let's go over to servers and create and hit create server.
02:59
And we should see zero of course, because it's not complete at the moment and there's been no progress, but then when it goes to the next job, we see the progress output. Now this is going to eventually error.
03:09
So if we just wait for this to get to the last task, the batch will no longer be available. And we either see an error if we're trying to access this outside of an if statement, in our case, we're using an if statement,
03:20
so it doesn't really matter, but just be careful of this. You'll want to wrap this in if statements like we've done here. So we know that when it's provisioned, the batch doesn't exist. So we're not doing anything. Okay.
03:30
So what we really want to do with this over in show server, when we destroy the server, we want to access the batch and then we want to cancel it. So we can just say this batch and cancel. Now, again,
03:43
because we are potentially trying to access something that doesn't already exist, we need to check this first of all. So we'll just, let's just pull this up here and assign this at the same time. So we'll say batch this batch. Now, if there is no batch,
03:58
we can't cancel it because it's already complete or failed, whatever. And here we can just say batch cancel. So we're just protecting ourselves if we don't have a batch available. So let's look at what happens now when we click on this while something is
04:12
provisioning. So just for the purpose of this, why don't we just change over the jobs here to have a slightly lower time, set these to three seconds, and that's going to be a little bit better. So let's change that to three and change that to three. Remember,
04:28
we're not using all these jobs at the moment, but if we wanted to add one, we could do very easily. Okay. So I'm going to go ahead and just cancel off and rerun our queue since we've made some changes there. And let's go back over and create out a server.
04:42
So I'm going to hit create. I'm just going to wait for the first one to run. We'll figure out the stars for this in a second. And once we've done that, I'm going to click destroy server. And there we go. So now let's wait a few more seconds.
04:53
And as you can see it still looks like it is running. Now the reason for this is that even if we cancel a batch, it's still going to go ahead and process each of the tasks in that batch. For that, we're going to need to use middleware.
05:08
Now there's actually a couple of ways that we can do this. So let me show you the first way we could say in here, create an if statement. Remember this is some sort of job to create the server, whatever we need to do.
05:19
We could say this batch. So we can actually grab the batch from the job that we're working with inside of the batch. And we can check if it's being canceled. If it's being canceled, we can return.
05:31
So essentially what we would have to do is add this if statement to every one of our jobs to then not do what we're trying to do down here. If we have canceled the batch, let's do that first and see what happens.
05:44
And then I'll go ahead and show you an easier way. So let's go over to each of these and add this if statement in to every single one of these. And let's try this functionality again. So once again, we need to cancel and rerun our queue.
05:58
Let's head back over to our interface and go ahead and run create again. Okay. So let's wait for this to get down to here and then I'll hit destroy server to cancel this and let's see what happens. So as you can see, although we are redirected to the provision state,
06:14
that then did not progress to the last job in the batch. That's a step in the right direction, but I'm going to show you a better way to do this. If you don't need to perform any kind of tasks in here,
06:27
when this has been canceled, you might need to do some sort of clear up in here, in which case you can use an if statement, but otherwise we could just implement some middleware. So inside of a job,
06:36
we can go ahead and add in a middleware method. And this returns to us an array of middleware that we want to use for each of these batches. So we can return new skip if batch canceled. So this will go ahead and skip this entire job. If this has been canceled,
06:53
let's go ahead and do that for each of these rather than use that if statement. So we'll pull that in there as well. Do the same for this one, get rid of this if statement and we'll do the same thing for the last one as well. Okay. So now that we've done that,
07:06
we're going to have exactly the same thing. This is going to skip each of these jobs. What we then need to do is figure out what we finally want to do. If the batch has been canceled,
07:15
we don't want the server to look like it's been created because it wouldn't have. Okay. So let's go over to servers and create once again, just restart our queue because we've already done some work in there and let's click create server. I'm going to wait for this to get to the second one.
07:31
And once it does hit destroy. And there we go. It works in exactly the same way, but we're redirected over here. That's not what we want to happen. So what we want to do is when we dispatch this batch,
07:44
we have a finally callback as well. So let's go back over to where we are observing our server. And let's go ahead and add in a finally callback. This will give us the opportunity to once something happens,
08:00
but not necessarily after this is completely finished, do something with this in here. So let's go ahead and pull in our batch and put in our server. Now, what do we want to do? Well,
08:12
we want to check here if the batch has been canceled and if there are no failed jobs, if that's the case, it means someone has destroyed the server. So we can use the batch now in here. Let's pull in batch and check if it's been canceled.
08:26
So if it's been canceled, but doesn't have any failures, that means that someone has destroyed the server while this batch was running. So we can just say batch failed jobs and we can check if that is zero. So if there are no failures,
08:42
because if there are failures, we want to show them on the UI. And if it's been canceled, then we want to delete the server. Now, what we also want to do, we need to be really careful because we've still got tasks hanging around.
08:54
We want to get rid of them as well. So why don't we just add another deleting event to this and we'll grab the server in just before a server is deleted. Let's go ahead and delete all of the tasks as well.
09:09
That will just help to clear things up when we do this. We don't want all of them tasks hanging around in the database. Okay. So once again, let's go ahead and close off our queue, rerun it and let's go and see the difference now.
09:22
So let's go over to create, hit create server. I'm going to destroy this after it gets down to the second task and let's just wait. And there we go. So we're making progress. We get a 404 not found yet, which is absolutely fine.
09:37
We can still handle this, but at least now that has been removed from the database, we've still got a few hanging around here, but the last one would have been deleted.
09:45
And now we can handle what happens after this has been deleted. So let's get rid of all of our servers. Let's get rid of all of our job batches and let's go over and figure this out. So effectively what we want to do is if we get to this point where we are,
10:00
we just head back over to our show server. If we're canceling the batch, we want to just redirect somewhere else. Everything else will happen in the background, like the server getting deleted.
10:11
We just want to redirect the user somewhere else. So they're not continuing to be on this page. There's no need for them to be on there. So we can just redirect them back over to a route.
10:21
So let's return a redirect here and we'll redirect them back over to servers and create. Okay. So now that we've done that, we cancel the batch. Everything gets handled in the background. The server gets deleted,
10:34
all the tasks get deleted and we either redirect them over to another page to confirm or just back to the servers create page. Let's go over and try this out now. Okay. So we'll go over to servers create and I'm just going to fiddle around with these
10:47
styles because this is getting annoying. So let's go over here and let's add a margin on the bottom here of six. Okay, great. So let's click create server. And let's wait for this to get the second task down.
11:02
And when we hit destroy, we redirect straight back over to servers create. If we open up the database, there are no servers. There are no tasks. Everything has been nicely cleared up.
18 episodes1 hr 37 mins

Overview

Let’s tackle how to batch tasks in Laravel, change their state as they complete, and display step-by-step progress in the UI.

Using job batching we’ll create, dispatch and monitor a list of sequential jobs — changing their state using model states. We’ll also take this a step further to allow batch variations based on different tasks, and the ability to easy swap around the order of tasks.

At the end of the course, we’ll set up a UI with Livewire to poll the state of our batch, displaying progress to the user (and if anything goes wrong).

Simply put, if you’re building something that requires step-by-step jobs to be run and you need to display progress to the user — this course covers absolutely everything you’ll need to know.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!