Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 concurrent request and scheduled job

I am using Laravel 5 with php 5.5.9-1ubuntu4.14 and mysql 5.5.47. I have a multi-tenant environment with each tenant having a separate DB. So for every HTTP request, I set the appropriate DB connection in the BeforeMiddleware like so

public function handle($request, Closure $next)
{
...
// Set the client DB name and fire it up as the new default DB connection
Config::set('database.connections.mysql_client.host', $db_host);
Config::set('database.connections.mysql_client.database', $db_database);
Config::set('database.connections.mysql_client.username', $db_username);
Config::set('database.connections.mysql_client.password', $db_password);
DB::setDefaultConnection('mysql_client');
...
}

This works correctly even for concurrent HTTP requests.

But now I want to add scheduled jobs to my application. These jobs will send notifications to users belonging to all tenants. So, I again need to connect to respective tenant Databases. But this connection won't be through an HTTP request. Let's say I have a CommunicationController and a function inside it for sending notifications.

public function sendNotification()
{
  ...
  DB::purge('mysql_client');//IMP
  // Set the client DB name and fire it up as the new default DB connection
  Config::set('database.connections.mysql_client.host', $db_host);
  Config::set('database.connections.mysql_client.database', $db_database);
  Config::set('database.connections.mysql_client.username', $db_username);
  Config::set('database.connections.mysql_client.password', $db_password);

  DB::setDefaultConnection('mysql_client');
  ...
}

This is where I set the Config values. This function will be executed every minute through Laravel Scheduler.

My questions are:

  • What will happen when an HTTP request comes in? Will there be any concurrency issues as Config parameters are being set in both, HTTP request as well as Scheduled job?
  • Will the HTTP request connect to some incorrect DB if it's running simultaneously with the scheduled job?
like image 546
linuxartisan Avatar asked Jul 20 '16 05:07

linuxartisan


People also ask

How to schedule Laravel command scheduler?

As you notice i schedule the command on daily basis but there are number of schedule frequencies which you can assign to the tasks. If you wan to start the scheduler itself then you will have to add one cron job on server using the crontab -e command. Using this, Laravel command scheduler will be called by cron every minute.

How do I run a queue worker in Laravel?

The queue:workCommand Laravel includes an Artisan command that will start a queue worker and process new jobs as they are pushed onto the queue. You may run the worker using the queue:workArtisan command. Note that once the queue:workcommand has started, it will continue to run until it is manually stopped or you close your terminal:

How to avoid concurrency attacks in Laravel jobs?

However, laravel provides two powerful features in Job classes that can be leveraged to avoid concurrency attacks. First is the ShouldBeUnique interface. Implementing this interface on a job class tells laravel to ensure that only one instance of this job should be running at any given time.

What is a Laravel cronjob?

Generally laravel cronjob is task scheding. it means it will work according scheduled time. If you want to schedule tasks that will be executed every day automatically that is very helpful for you. Laravel cronjob is reduce the manually working time.


2 Answers

According to the Laravel docs:

Configuration values that are set at run-time are only set for the current request, and will not be carried over to subsequent requests.

Configuration values are set at run-time when you specifically call the Config::set method so the value will be only valid for that current request and you'll never have any concurrency issues due to that.

Your second question is impossible as well. Even if your previous task was running a request on the database, the second/subsequent tasks will wait for locks if any to be release on the database. You should try to be sure you're not performing any queries that can lock for a long period on your DB by using multi-insert, sqldump (if you're performing large queries).. etc

like image 184
Chibueze Opata Avatar answered Sep 25 '22 02:09

Chibueze Opata


Looking at Illuminate\Config\Repository which is the implementation used for the Config facade and specifically the set method

public function set($key, $value = null)
{
    if (is_array($key)) {
        foreach ($key as $innerKey => $innerValue) {
            Arr::set($this->items, $innerKey, $innerValue);
        }
    } else {
        Arr::set($this->items, $key, $value);
    }
}

you can be assured that the set is not an IO set (ie. to the filesystem) but an in-memory set. So the CLI scheduler command that runs every minute will run in its own context like every other http request.

like image 43
Leon Vismer Avatar answered Sep 26 '22 02:09

Leon Vismer