Define database connection for supervisor - laravel

In my laravel 8 app, I have three database connections, viz Database-0, Database-1, Database-2.
Database-0 used for authenticating users so it has users table and Laravel Auth method retrieve user using this connection as I have set it in passport configuration file.
Database-1 and Database-2 connection used for all other purposes except authentication.
In my users table I have just two users with email first_user#example.com and second_user#example.com
When user is logged in with first_user#example.com then Database-1 should be used and if user is logged in with second_user#example.com then Database-2 should be used.
To acheive this I have created a middleware and register it in $middleware group so it run for all the request. In this middleware, I am checking the logged in user email and based on that I am setting database connection.
Up until now everything works perfectly
Now I have a job of that is being queued and I am using database as my QUEUE_CONNECTION. so my job stored in database jobs table. I have configured supervisor for processing this job.
Now the problem is when supervisor make query to retrieve job, my middleware doesn't get called and it throws following error
invalid catalog name: 1046 No database selected (SQL: select * from jobs where ....)
So my question is how can I set database connection for supervisor to choose from database when retrieving jobs?
middleware
public function handle(Request $request, Closure $next)
{
$auth_email = Auth::guard('api')->user()?->email;
if ($auth_email === 'first_user#example.com') {
config(['database.connections.fe_mysql.database' => 'Database-1']);
} elseif ($auth_email === 'second_user#example.com') {
config(['database.connections.fe_mysql.database' => 'Database-2']);
}
return $next($request);
}
supervisor config
[program:queue-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/laravel-project/artisan queue:work --queue=admin
autostart=true
autorestart=true
user=root
numprocs=8
redirect_stderr=true
stopwaitsecs=7200
stdout_logfile=/var/www/html/laravel-project/worker.log

Use the config() function to set extra or overwrite existing connection settings.
config(['database.connections.mynewconnection' => {settings here}]);
Keep in mind that these settings are cached. So when you need to use the new settings, purge the DB cache for the connection you're gonna use.
DB::purge('mynewconnection');
You can also manipulate the default connection that is used. This can come in handy if you wish to use migrations over different connections and keep track of them with a migration table within the used connection. Or other cool stuff ofcourse...
DB::setDefaultConnection('mynewconnection');

Related

Laravel job executing real time without queue being started

Running on Laravel 5.8
I am creating a large number of Jobs which I believe should be executed once the queue has been initiated.
My issue is that the jobs get executed then and there when I haven't even started the queue.
They are not even being inserted in to the jobs table created by the migration.
Below are the settings and the piece of code I believe is relevant. Please let me know if more info is needed.
On a fresh installation:
php artisan queue:table
php artisan migrate
.env file
QUEUE_CONNECTION=database
Created the queuedtask
class FulfillmentTask implements ShouldQueue{
//code here
}
Controller
use App\Jobs\FulfillmentTask;
//rest of the class here
public function somefunction(Request $request){
//some code here
//read csv file
foreach ($fileContents as $row){
FulfillmentTask::dispatch($orderId, $client, $request->sendEmail)->onQueue('database');
}
}
Issue is the FulfillmentTask is executed without the queue:work command being given in the terminal.
Any idea on why this is happening?
"database" is a queue connection. Pls dispatch your job to that connection.
FulfillmentTask::dispatch($orderId, $client, $request->sendEmail)->onConnection('database');
And that seems to be the default connection so you just dispatch the job.
FulfillmentTask::dispatch($orderId, $client, $request->sendEmail);

What is the right way to send bulk mail with Laravel via AWS SES?

I've SES approved sending rate of 500 emails / second. When I try to send bulk email via Laravel using SES API, the actual mail sending rate is very slow (about ~100 per minute).
Here's an overview of how I do it -
...
Users::latest()->chunk(100, function($users) use($newsletter) {
Notification::send($users, new SendNewsLetter($newsletter)); // queued
})
My guess was that I'd send about 100 mails in one shot, however, Horizon shows that the queue which I'm using will have long wait time (of several seconds).
Can someone inform me what is the right way to send bulk emails using SES and Laravel?
First, i recommand you change the .env file setting for QUEUE_DRIVER=sync to QUEUE_DRIVER=database.
sending Email action
$users = Users::latest()->take(100)->get();
Mail::queue('send', ['users' => $users], function($m) use ($users) {
foreach ($users as $user) {
$m->to($user->email)->subject('YOUR SUBJECT GOES HERE');
}
});
As next step you need to create a Queue table in the database using
the following command before clicking on the route:
PHP artisan queue: table
PHP artisan migrate
Before starting the project you need to run a listener to listen to
the Queue Request. But you're gonna introduce with the new method as
listen is high CPU usage. It's better to use a daemon. So Run the
following command:
PHP artisan queue:work --daemon --tries=3
Source

How to access Session data from database

I want to access session data from database. Currently, I have changed default setting in session.php to database so that I can capture all the session columns in DB. But now I want to access these in my code. Do I need to create some session model or it's present out of the box just like user.php. Please help me.
You should create sessions table with these commands:
php artisan session:table
composer dump-autoload
php artisan migrate
Or you could manually create migration and run it, an example from documentation:
Schema::create('sessions', function ($table) {
$table->string('id')->unique();
$table->text('payload');
$table->integer('last_activity');
});
After doing that, you can just use sessions as usual with Session:: facade or sessions() helper:
session()->flash('message', 'Success!');
Update
If you need to access table data directly, you could do this:
DB::table('sessions')->get();
Or you could create SessionData() model and do this:
SessionData::all();

How to globally prevent saving to database in Laravel 5

I made a PHP script in Laravel and now I want to show demo to my buyers. Since I don't want them to make any changes to the database, I was wondering if there is a way to globally disable any saving to the database?
If you have a BaseModel that extends Laravel's default Eloquent model class. And all of your applications models extend that BaseModel you can add the following to it:
public static function boot()
{
parent::boot();
static::saving(function($model)
{
return false;
});
}
This will intercept any creating or updating events from Eloquent.
This may be the technical answer for your question, but ideally just backup your db and restore it after showing to your buyers.
The easiest thing will be to create a mysql user that hasn't permissions to insert. Use the following mysql statement to create the user and use this user as the user in your database setting. I don't think there's a global method for this in laravel.
GRANT SELECT ON [database name].[table name] TO ‘[username]’#'%’;
This way, your user can view everything, but isn't able to save a bit.

Where does Laravel's Artisan get session config info from?

My session config file says to use memcached, but all artisan commands are loading the "array" driver instead. I'm writing a web sockets application with Ratchet and need to connect to Memcached to get the user's session information, but seems to ignore my config.
Where and how does Laravel determine which session drivers to use for Artisan commands?
According to Illuminate\Support\ServiceProvider\SessionServiceProvider::setupDefaultDriver() Laravel will set the session driver to array if running in console.
You can easily override this by registering your custom service provider. Create a custom service provider, extend the default session service provider and override the method setupDefaultDriver). Here is my custom service provider for example:
<?php namespace App\Console;
use Illuminate\Session\SessionServiceProvider as DefaultSessionProvider;
class SessionServiceProvider extends DefaultSessionProvider
{
protected function setupDefaultDriver() {}
}
Then open up config/app.php and replace 'Illuminate\Session\SessionServiceProvider' with 'App\Console\SessionServiceProvider'.
Now artisan will also use the same session storage as Laravel app.
Since you are trying to attach the session to Ratchet, You can directly inject this session instance into Ratchet app:
$session = new \Ratchet\Session\SessionProvider(
new MyCustomRatchetApp(),
$this->getLaravel()['session.store']
);
$server = new \Ratchet\App('localhost');
$server->route('/sessDemo', $session);
$server->run();
Gufran posted a good answer, but another solution which doesn't involve swapping out a service provider, it just to set the default driver manually in your artisan command (or tests).
Like so: Session::setDefaultDriver('memcached');. You can do the same for cache: Cache::setDefaultDriver('memcached');. You do this before doing any other commands, of course, so that it doesn't start using the array.
If you need to, you can manually put in connection information: Config::set('cache.memcached', array(array('host' => '127.0.0.1', 'port' => 12345, 'weight' => 100)));

Resources