How to dispatch an async job in Laravel 5.8 with Redis? - laravel

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,
],
],

Related

Email is being pushed to laravel Queue but doesn't get sent

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

Laravel is not sending Pusher Events to my Vue.js frontend

I have a Vue.js separated project from a Laravel backend in many tutorials I see a Laravel + Vue.js but I have a Vue.js SPA separated and I don`t know what I doing wrong.
I already make the configuration on front end, this is it:
const pusher = new Pusher(configMain.PUSHER_APP_KEY, {
cluster: configMain.PUSHER_APP_CLUSTER
});
const pusherChannel = pusher.subscribe('teste');
pusherChannel.bind('my-event', function(data) {
console.log(data);
});
When I use the debug console in PUSHER and send an event, it works fine I receive it. But when I try to send an event from my backend Laravel project it doesn`t work.
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=********
PUSHER_APP_KEY=********
PUSHER_APP_SECRET=********
PUSHER_APP_CLUSTER=********
I already set the keys and change the driver, in config broadcasting i have this:
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
],
],
I created an event in Laravel that is this:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MyEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
private $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($message)
{
//
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('teste');
}
public function broadcastAs()
{
return 'my-event';
}
}
And when i execute this in my backend:
event(new MyEvent('hello world'));
dd("ENTROU");
My front doesn't receive it, I must do something that I don't see it?

How to call migration on job, properly?

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]);
}
}

Laravel Broadcasting does't write to redis but direct call to redis works

I have tried sereval tuto to try to setup Laravel Redis NodeJs Socket.
And it'is not working.
So far :
- my broadcast fires as I can see it in Laravel log
- my redis server works (I have added a call to Redis in my homecontroller and I can see the value in the log and in redis-cli monitor - I have also installed Horizon and I can see its call in Redis-cli monitor)
But when my broadcast fires I don't see anything in redis-cli monitor
I have already tried the obvious things (cache/ config clear / reboot / ...)
Help will be very apreciated !
Redis call in my homecontroller : working
Redis::set("foo","bar");
$value = Redis::get("foo");
Log::debug('Redis value :'.$value);
.Env
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=siview
DB_USERNAME=root
DB_PASSWORD=
QUEUE_DRIVER=sync
QUEUE_CONNECTION=sync
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
BROADCAST_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
Database.php
'redis' => [
'client' => 'predis',
'default' => [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
'read_write_timeout' => 60,
],
'cache' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
'pubsub' => [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 2,
],
],
Boadcasting.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Broadcaster
|--------------------------------------------------------------------------
|
| This option controls the default broadcaster that will be used by the
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
| Supported: "pusher", "redis", "log", "null"
|
*/
'default' => env('BROADCAST_DRIVER', 'redis'),
/*
|--------------------------------------------------------------------------
| Broadcast Connections
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over websockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'pubsub',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];
Event
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\User;
class SendMessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
private $user;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('App.User.' . $this->user->id);
}
public function broadcastWith()
{
return ['message' => 'Salut ' . $this->user->name];
}
}
Route Channel
<?php
/*
|--------------------------------------------------------------------------
| Broadcast Channels
|--------------------------------------------------------------------------
|
| Here you may register all of the event broadcasting channels that your
| application supports. The given channel authorization callbacks are
| used to check if an authenticated user can listen to the channel.
|
*/
Broadcast::channel('App.User.{id}', function ($user, $id) {
return true;//(int) $user->id === (int) $id;
});
Route web
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Auth::routes();
Route::get('/send/{user}', function(\App\User $user){
event(new \App\Events\SendMessageEvent($user));
});
Route::get('/home', 'HomeController#index')->name('home');
Laravel.log showing my broascast
[2018-11-04 09:39:42] local.INFO: Broadcasting [App\Events\SendMessageEvent] on channels [private-App.User.1] with payload:
{
"message": "Salut nathalie",
"socket": null
}
redis-cli monitor showing my homecontroller test
1541324518.159040 [0 127.0.0.1:59334] "SELECT" "0"
1541324518.159776 [0 127.0.0.1:59334] "SET" "foo" "bar"
1541324518.160360 [0 127.0.0.1:59334] "GET" "foo"
I have found and it's a bit strange :
I am working on windows with wamp.
The wamp server was started by not the Laravel server.
Strangly everything seemed to work well (no errors, pages rendered, auth was working...)
I just started laravel with : php artisan serve
and now I can see in Redis-cli monitor :
1541328214.873429 [0 127.0.0.1:52962] "SELECT" "2"
1541328214.874260 [2 127.0.0.1:52962] "PUBLISH" "private-App.User.1" "{\"event\":\"App\\\\Events\\\\SendMessageEvent\",\"data\":{\"message\":\"Salut nathalie\",\"socket\":null},\"socket\":null}"
1541328661.366923 [0 127.0.0.1:53078] "SELECT" "2"
1541328661.367643 [2 127.0.0.1:53078] "PUBLISH" "private-App.User.1" "{\"event\":\"App\\\\Events\\\\SendMessageEvent\",\"data\":{\"message\":\"Salut nathalie\",\"socket\":null},\"socket\":null}"
1541328679.554077 [0 127.0.0.1:53083] "SELECT" "2"
1541328679.555197 [2 127.0.0.1:53083] "PUBLISH" "private-App.User.1" "{\"event\":\"App\\\\Events\\\\SendMessageEvent\",\"data\":{\"message\":\"Salut nathalie\",\"socket\":null},\"socket\":null}"
Make sure you have latest version of redis serve.
Laravel uses commands like eval that supported in latest version on redis server.
I used Redis 3.2.100 and issue was solved.
I found that same problem and after a lot of useless research it was as simple to update de redis server.
Download here:
https://redis.io/download
Or here for windows:
https://redislabs.com/ebook/appendix-a/a-3-installing-on-windows/a-3-2-installing-redis-on-window/

Laravel Spark not sending message to Pusher from event

Trying to get Pusher working on my app but cannot get it to send any messages to Pusher itself.
I have an event that is fired when creating a 'booking':
event(new BookingCreated($booking));
This event:
<?php
namespace App\Events\Booking;
use App\Booking;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class BookingCreated implements ShouldBroadcast
{
use SerializesModels, InteractsWithSockets;
public $booking;
/**
* Create a new event instance.
*
* #param Booking $booking
* #return void
*/
public function __construct(Booking $booking)
{
$this->booking = $booking;
}
public function broadcastOn()
{
return ['teams.'.$this->booking->team_id.'.bookings'];
}
}
My env file has the following (with details):
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
My broadcasting config file has the pusher details set up as:
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => 'eu'
],
],
When looking in the Pusher dashboard I can see open connections, but no messages. I am running queue:listen which is showing that the events are being processed.
Anything I am missing?
This was a mistake on my behalf, I had changed the env file BROADCAST_DRIVER but hadn't restarted the queue listener so my events were broadcasting to the log.

Resources