Creating Events that are queueable and handle them with Supervisor

Vipul Basapati
codeburst
Published in
5 min readApr 2, 2018

--

So, I have always been told that PHP is a single threaded language that means, bad news, we can’t do anything as a background process in PHP.

But that doesn’t stop us, they invented Queues to handle background processes, through which we can simulate like a multithreaded system.

Laravel makes it easy.

I have a use case where we will need a background process to make a good user experience.

Use Case: When a user registers on the site, by filling up the registration form, you want to send them the confirmation email, but you don’t want the user to wait till we send email.

Instead what we can do, is to send email as a background process and tell user to check their email by giving them a green alert saying “Registration is complete”.

How can we do that in Laravel?

I have a fresh installation of Laravel 5.6 and auth scaffolding already done.

To do auth scaffolding in your laravel installation, you can run:

php artisan make:auth; php artisan migrate;

It will create register and login functionality in your application.

Now what we want to achieve is to send an email to the user when he registers. For that, (after make:auth command) we have RegisterController.php at app\Http\Controllers\Auth .

In which we have a create() function which handles the creation of user, as you can see it has User::create() .

We are going to tweak this function a little bit to fire our event, but first let’s make our event.

For creating an event, laravel has a command:

php artisan make:Event UserCreated

With this command, we will have an Event class atapp\Events\UserCreated.php .

Now let’s make our Listener of this event.

For that, again we have a command:

php artisan make:listener SendRegisterationEmail --event=UserCreated

From above command, we will have our listener for our UserCreated event at app\Listeners\SendRegisterationEmail.php .

Now we need to register our event and listener.

We can do that in EventServiceProvider.php by adding our event and listener in $listen[] array like below.

/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'App\Events\Event' => [
'App\Listeners\EventListener',
],
'App\Events\UserCreated' => [
'App\Listeners\SendRegisterationEmail'
]
];

Now, we have successfully registered our Event with our listener. What this will do is, it will call the SendRegisterationEmail Listener whenever our event UserCreated is fired.

We can call this event like below in our RegisterController :

/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
*/
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
//Fire the event
event(new UserCreated($user));

return $user;
}

Don’t forget to use App\Events\UserCreated;

See, here we have fired our event with $user , so we need to catch that user and pass it our listener.

We can do that by going to UserCreated.php and write below in our __construct() .

/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}

Now, in our SendRegisterationEmail.php in handle() method, we can retrieve the $user variable like below:

/**
* Handle the event.
*
* @param UserCreated $event
* @return void
*/
public function handle(UserCreated $event)
{
$user = $event->user;

//Send Email Code Here
}

Here, you can write your email sending code.

Now, we need to Queue it up.

For that, first tweak your listener to implement ShouldQueue .

class SendRegisterationEmail implements ShouldQueue

For using database queues, change your .env

QUEUE_DRIVER=database

then run,

php artisan queue:table; php artisan migrate;

It will create the queue table and then migrate the table to your database.

For testing, what I always do is to, dd() somewhere in my code, to check if my code is running and going where I want it to go.

So, in our listener in handle() method, we can dd('something').

Now, go to register link in your application, fill the form and register.

Does it work? Your dd() didn’t get called there, you know why? Because it is in the queue now.

You can type:

php artisan queue:work

to run the queue.

As soon as you run your queue, you can see your dd() printed out in the terminal.

So, it’s working.

Now, you know that handle() method in your listener is running on totally different thread from your application.

But you don’t want to manually run, php artisan queue:work every time a user registers.

Let’s Supervise

You can use an app Supervisor to run your queues indefinitely.

You can install it by:

sudo apt-get install supervisor

Now you need to create config file for your queues. The supervisor config files are typically stored at /etc/supervisor/conf.d . In this directory, you can create your config files to let supervisor know how to process your queues.

For our app, we will create an app-worker.conf .

[program:app-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/app/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=bvipul
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/html/app/worker.log

You need to make sure, you give correct location to your application.

After this has been done, you can:

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start app-worker:*

This will register your worker and start it.

Now, if you have set up the worker correctly, you can see worker.log in your root directory and now if a user registers, it will show up in this worker.log file that it is processing.

Kudos, you don’t need to manually do anything and your user experience and your testers are also happy.

Do tell me, if you any problem with the above steps.

You can find this project here.

Laravel And JS Resources

Below are some resources for Laravel and Javascript and my favorite JS framework: React.

Laravel

  1. Official Docs are the best maintained for Laravel. And Laracasts is the best.

Javascript

  1. For learning Javascript, Wes Bos is the best one to teach, because I have taken at least 6 courses from him. And have everything positive. You can learn the basics of JS and get your hands-on Vanilla Javascript using JavaScript30 course.
  2. You can learn the new syntax or the modern Javascript syntax called ES6 from es6.io. (Paid)
  3. You can learn React from scratch by learning from this tutorial on ReactForBeginners.com. (Paid)

✉️ Subscribe to CodeBurst’s once-weekly Email Blast, 🐦 Follow CodeBurst on Twitter, view 🗺️ The 2018 Web Developer Roadmap, and 🕸️ Learn Full Stack Web Development.

--

--