I am trying to implement a queue to send email in laravel. My .env file
MAIL_DRIVER = smtp
MAIL_HOST = smtp.gmail.com
MAIL_PORT = 587
MAIL_FROM_ADDRESS = from#gmail.com
MAIL_USERNAME = from
MAIL_PASSWORD = ********
MAIL_ENCRYPTION = tls
QUEUE_CONNECTION=database
My config/queue.php
'connections' => [
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
'after_commit' => false,
],
]
config/mail.php
'mailers' => [
'smtp' => [
'transport' => 'smtp',
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => env('MAIL_PORT', 587),
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN'),
],
]
My Job file
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendSampleMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Mail::send(['text' => 'mail'], ['name' => 'TestUser'], function ($message) {
$message->to('to#mailinator.com', 'testUserName')->subject('Test Laravel email');
$message->from('from#gmail.com', 'Test Mail');
});
}
}
In the controller, I am calling it like
$job = new SendSampleMail();
$this->dispatch($job);
The mail.blade.php
<p>Sending Mail from Laravel.</p>
When I run
php artisan queue:work
The jobs are queued but email fails to be sent.
I need to fix that issue. Any help would be appreciated. Thanks in advance.
As per the laravel document, create the jobs table in the database.
Run the below two command for the creating the table
php artisan queue:table
php artisan migrate
Related
Question: How to customize long-running job without attempting multiple time after each retry_after seconds?
I have one job which will take 1 to 3 hours to run,
I already created job-based on laravel documentation, here is my job file.
<?php
namespace App\Modules\Csv\Jobs;
use App\Jobs\Job;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use League\Csv\Reader;
use Phone;
/**
* A single excel import job, which can be pushed on to a queue
*/
class UploadCsvDataInTable extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels, Dispatchable,Queueable;
public $timeout = 172800;
/**
* The excel to import
*
* #var App\BulkUpload
*/
protected $csvUpload;
/**
* Create a new job instance.
*
* #param App\FeedImport
*
* #return void
*/
public function __construct(CsvUpload $csvUpload)
{
$this->csvUpload = $csvUpload;
}
public function handle()
{
app(CsvUploadService::class)->uploadCsv($this->csvUpload);
}
}
here is Laravel document to specify a timeout for jobs.
here is code for how I am calling that job.
UploadCsvDataInTable::dispatch($csvUpload)->onConnection('redis')->onQueue('low');
my command for queue:work In supervisor.
php artisan queue:work --queue=high,low,default --sleep=3 --tries=3
here is my configuration for queue & horizon
// horizon.php
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['high', 'default', 'low'],
'balance' => 'simple',
'processes' => 6,
'tries' => 3,
],
],
//queue.php
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
I can see because of retry_after my job is attempting multiple time and after reaching 3 try as per horizon configuration its throwing MaxAttemptsExceededException.
if I increase $timeout to 24 hours I am getting duplicate records in my db as retry_after is attempting that job multiple time.
is there any way I can set custom retry_after for this job?
I have created another connection for long-running jobs and its working properly for me.
created new supervisor connection in horizon.php for long running process
'supervisor-long-running' => [
'connection' => 'redis-long-processes',
'queue' => 'long-running',
'balance' => 'simple',
'processes' => 3,
'tries' => 1,
'timeout' => 86000 // should be shorter than retry_after out
]
and new redis connection in queue.php
'redis-long-processes' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'long-running',
'retry_after' => 86400,
'block_for' => null,
],
in database.php added new queue for long running jobs.
'queue' => [
[
'connection' => 'redis',
'queue' => ['high', 'default', 'low','long-running'],
'balance' => 'simple',
'processes' => 6,
'tries' => 3,
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
],
also don't forgot to call jobs using onConnection and onQueue to specify from which queue jobs should execute.
UploadDataInTable::dispatch($upload)->onConnection('redis-long-processes')->onQueue('long-running');
you don't need to set retry_after, you need to set tries to 1
public $tries = 1;
https://laravel.com/docs/8.x/queues#max-attempts
I need to run a very time consuming task asynchronous in Laravel 5.8. This is the .env file
...
QUEUE_CONNECTION=sync
QUEUE_DRIVER=redis
...
The queue driver must be Redis because the website uses Laravel-Echo with redis and socket.io to broadcast messages and I can't change queue driver to database.
This is the job I created
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class BroadcastRepeatJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
sleep(30);
}
}
and this is the HomeController:
public function index()
{
BroadcastRepeatJob::dispatch()->onQueue("default");
dd(1);
...
}
and I also run the following artisan commands
php artisan queue:work
php artisan queue:listen
when I visit /index of HomeController I expect to see dd(1) immediately not after 30 seconds because the sleep(30) must be ran in a queue but this does not happen and I have to wait 30 seconds to see dd(1). How can I run the job in background asynchronous ?
Thanks in advance.
Try switching your QUEUE_CONNECTION to redis rather than sync
/*
|--------------------------------------------------------------------------
| Queue Connections
|--------------------------------------------------------------------------
|
| Here you may configure the connection information for each server that
| is used by your application. A default configuration has been added
| for each back-end shipped with Laravel. You are free to add more.
|
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
*/
'connections' => [
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
],
I have this managing institution project. Each institution has its own DB like 'institution_1', 'institution_2' etc. I'm creating that institution DB and trying to migrate into them after I created them. Because it takes to long to migrate (I think bc it has a lot of tables) I'm using queue and jobs. Job is running but not the migration!!
*Controller: *
$newDb = DB::connection('rc')->statement("CREATE DATABASE intitution_$institutionId CHARACTER SET utf8 COLLATE utf8_general_ci;");
DB::connection('rc')->statement("GRANT ALL PRIVILEGES ON `institution\\_$institutionId`.* TO 'institutions'#'%' WITH GRANT OPTION");
if ($newDb) {
Config::set('database.connections.th', [
'driver' => 'mysql',
'host' => 'localhost',
'port' => '3306',
'database' => 'institution_'.$institutionId,
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'timezone' => '+00:00',
'strict' => false,
]);
$job = (new CreateInstitutionDb())->delay(Carbon::now()->addSecond(120));
dispatch($job);
return true;
}
*CreateInstitutionDb Job: *
public function handle()
{
\Illuminate\Support\Facades\Artisan::call('migrate',['--database' => 'th', '--force' => true]);
}
You're delaying the job execution by a 2 minutes, I assume you want to set 2 minutes timeout
$job = new CreateInstitutionDb();
And in your job
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class CreateInstitutionDb implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* The number of seconds the job can run before timing out.
*
* #var int
*/
public $timeout = 120;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
\Illuminate\Support\Facades\Artisan::call('migrate', ['--database' => 'th', '--force' => true]);
}
}
i'm connect multiple Database and i use Laravel Excel I can'n export. This is error "Database [mysql] not configured."
i'm use laravel 6.0 and phpmyadmin version 4.4.15.10
controller
public function exportExcel()
{
return Excel::download(new merakiExport, 'MerakiBluetooth.xlsx');
}
app/Exports
namespace App\Exports;
use App\MerakiBluetoothTemp;
use Maatwebsite\Excel\Concerns\FromCollection;
class merakiExport implements FromCollection
{
/**
* #return \Illuminate\Support\Collection
*/
public function collection()
{
return MerakiBluetoothTemp::all();
}
}
config/database
'meraki' => [
'driver' => 'mysql',
'host' => env('DB_HOST5', ''),
'port' => env('DB_PORT5', ''),
'database' => env('DB_DATABASE5', 'forge'),
'username' => env('DB_USERNAME5', 'forge'),
'password' => env('DB_PASSWORD5', ''),
'unix_socket' => env('DB_SOCKET5', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
env
DB_HOST5=sql.laravel.com
DB_PORT5=3306
DB_DATABASE5=time_sheet
DB_USERNAME5=*****
DB_PASSWORD5=*****
I succeeded too.
app/Exports
namespace App\Exports;
use App\MerakiBluetoothTemp;
use Maatwebsite\Excel\Concerns\FromCollection;
use App\Http\Controllers\Controller;
class merakiExport extends Controller implements FromCollection
{
/**
* #return \Illuminate\Support\Collection
*/
public function collection()
{
return MerakiBluetoothTemp::all();
}
}
I have laravel project used for apis(Passport). It uses multiple databases one database stores user information and the database name for that user. I created a BaseController, all the other controllers extends from this controller. But I am not able to fetch Auth::id(); from the BaseController. How can I get the Auth::id in the constructor?
class BaseController extends Controller
{
protected $companySchema;
public function __construct() {
$user = \App\User::where('user_id', Auth::id())->first();
$company = $user->company;
$this->companySchema = $company->cmp_Schema;
}
}
After laravel 5.3.4 you can't use Auth::user() in the constructor because the middleware isn't run yet.
class BaseController extends Controller {
public function __construct() {
$this->middleware(function ($request, $next) {
$this->companySchema = Auth::user()->company->cmp_Schema;
return $next($request);
});
}
}
try this code and tell me if it works
You cannot use Auth in constructor, because middleware is not run yet. its from 5.3
check this link : https://laravel.com/docs/5.3/upgrade#5.3-session-in-constructors
First you should setup a connection in config/database.php:
'my_new_connection' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => $your_db_name,
'username' => $your_db_username,
'password' => $your_db_password,
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
Then you can change default database connection dynamically by this:
Config::set('database.default', 'my_new_connection');
You should first call
$user = Auth::user();
which is returning you the current user model associated, which is normally User. Then following should work:
$user->id