Laravel queue job only works when I clear browser cache? - laravel

Goal: is to dispatch job: right after user is logged in into the system.
So I have placed dispatch code in: app/Http/Middleware/RedirectIfAuthenticated.php
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param Request $request
* #param \Closure $next
* #param string|null ...$guards
*
* #return mixed
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
MyJob::dispatch(Auth::user()); // HERE I DISPATCH MY JOB
return redirect(theme()->getPageUrl(RouteServiceProvider::HOME));
}
}
return $next($request);
}
}
This is my simple job example:-
<?php
namespace App\Jobs;
use App\Models\User;
use Exception;
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\Log;
class MyJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public User $user;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
try {
Log::info('JOB STARTED : ' .now());
sleep(5);
Log::info('JOB ENDED : ' .now());
} catch (Exception $exception) {
Log::info('---------------------------------------------------------------------------------------');
Log::info('****************************************');
Log::info('CLASS : ' . __CLASS__);
Log::info('METHOD : ' . __METHOD__);
Log::info('FUNCTION : ' . __FUNCTION__);
Log::info('DIRECTORY : ' . __DIR__);
Log::info('****************************************');
Log::info('EXCEPTION', [
'status' => 'error',
'message' => $exception->getMessage(),
'code' => $exception->getCode(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => $exception->getTrace(),
]);
}
}
}
It doesn't work until I clear the browser cache or run in incognito mode of the browser.Also it's running only once, even if I logout and login again this job won't exceute or dispatch.
I'm running my project on aws ec2 machine and this is my supervisor config:-
[program:laravel_worker]
command=php /var/www/development/artisan queue:work
process_name=%(program_name)s_%(process_num)02d
autostart=false
autorestart=true
stopsgroup=true
user=root
numprocs=3
stderr_logfile=/var/www/development/laraqueue.err.log
stdout_logfile=/var/www/development/laraqueue.out.log
stopwaitsecs=3600
Already tried all the following commands:-
php artisan queue:clear
php artisan config:cache
php artisan optimize:cache
I don't see the problem with my code, maybe something to do with user=root in supervisor config, because my project is under Ubuntu group and Ubuntu user? I don't I'm super confused where to go.

Related

Where can I see my jobs from Laravel that should be executed with Docker

I am using Docker and I have command that looks like this
protected $signature = 'woocommerce:checkstock';
$woocount=WoocommerceProduct::where('sync_status', 'IN_SYNC')->count();
$fromId=1;
$toId=50;
while($fromId<=$woocount){
$job = (new CheckStockJob($fromId, $toId));
dispatch($job)->delay(now());
$fromId=$toId+1;
$toId=$toId+50;
sleep(600);
}
And my job is
<?php
class CheckStockJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
protected $fromId, $toId;
public function __construct( $fromId, $toId)
{
$this->queue = 'woocommerce';
$this->fromId=$fromId;
$this->toId=$toId;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
\Artisan::call('woocommerce:update_stock',
[
'fromId'=>$this->fromId,
'toId'=>$this->toId
]
);
}
}
When I run php artisan woocommerce:checkstock it doesn't creates any job in database table jobs, but when I run php artisan queue:work --queue=woocommerce it executes all CheckStockJobs, I want to know where are store those jobs that shoulg be executed, because I don't see them in database?? Are they somewhere in Docker??

Laravel automated invoice reminder email on due date, after 3days, after a week from different users to different clients

I am implementing a invoice API system for that I have to implement an automated reminder email on due date, after 3days, after 7days (it is like a API so the email has to be send from login user email to the selected customer)
For this system so far I implemented a checkbox selection which will store the login user, selected customer, due date, day selection for reminder stored the data in database). I have issues in sending emails from different users, adding condition to send email from the due date
console->commands->SendReminderemail.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
Use App\Reminder;
use App\Donor;
use App\Mail\ReminderEmailDigest;
Use Mail;
class SendReminderEmails extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'reminder:emails';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Invoice Reminder Emails';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
$pending_Reminders = Reminder::where('status',0)->get();
$data = [];
foreach ($pending_Reminders as $reminder){
$data[$reminder->donor_id][] = $reminder->toArray();
}
foreach($data as $donor_id => $pending_Reminders){
$this->sendEmailToUser($donor_id, $pending_Reminders);
}
// dd($data);
}
private function sendEmailToUser($donor_id, $pending_Reminders){
$user = Donor::find($donor_id);
Mail::to($user)->send(new ReminderEmailDigest($pending_Reminders));
// dd($user);
}
}
App->mail->ReminderEmailDigest
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class ReminderEmailDigest extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
private $pending_Reminders;
public function __construct($pending_Reminders)
{
$this->reminders = $pending_Reminders;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('emails.reminder-digest')
->with('pending_Reminders', $this->reminder);
}
}
App->console->kernal
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Console\Commands\SendReminderEmails;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
SendReminderEmails::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('reminder:emails')->everyMinute();
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
Now only the email working when I enter the reminder:emails command in console
How can i automate the mail?? any related suggestions??
You need to schedule your command.
For that, check how to register your command to schedular and how to set up cron job for schedular to run.
More specifically, you can do something like this:
$schedule->command('reminder:emails')->daily();
Just a note on how you could clean up your code.
$pending_Reminders = Reminder::where('status',0)
->get()
->groupBy('donor_id')
->each(function($reminders, $donor_id) {
$user = Donor::find($donor_id);
Mail::to($user)->send(new ReminderEmailDigest($reminders->toArray()));
});
To set the artisan command to run daily,
app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('reminder:emails')->daily();
}
To get that to run sudo crontab -e
* * * * * cd path/to/project && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1

laravel job/notification failing

I am trying to set up a contact form on my site whereby when someone clicks send, then a job is run and in that job, a notification is sent to all admin users. I keep getting this error in my failed jobs table though:
Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [App\Contact]. in /var/www/html/leonsegal/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:412
I have been all over my code and I can't see what I have done wrong. Would anyone be able to help please?
Here is my controller:
<?php
namespace App\Http\Controllers;
use App\Contact;
use App\Jobs\SendContactJob;
class ContactController extends Controller
{
/**
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function create()
{
return view('contact');
}
public function store()
{
request()->validate([
'name' => 'required|max:255',
'email' => 'required|email|unique:contacts|max:255',
'message' => 'required|max:2000',
]);
$contact = Contact::create(
request()->only([
'name',
'email',
'message',
])
);
SendContactJob::dispatch($contact);
return back()->with('success', 'Thank you, I will be in touch as soon as I can');
}
}
my job:
<?php
namespace App\Jobs;
use App\Contact;
use App\Notifications\SendContactNotification;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Notification;
class SendContactJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $contact;
/**
* Create a new job instance.
*
* #param Contact $contact
*/
public function __construct(Contact $contact)
{
$this->contact = $contact;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$users = User::all()
->where('admin', 1)
->where('approved', 1);
Notification::send($users, new SendContactNotification($this->contact));
}
}
my notification:
<?php
namespace App\Notifications;
use App\Contact;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class SendContactNotification extends Notification implements ShouldQueue
{
use Queueable;
protected $contact;
/**
* Create a new notification instance.
*
* #param $contact
*/
public function __construct(Contact $contact)
{
$this->contact = $contact;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line($this->contact->name)
->line($this->contact->email)
->line($this->contact->message);
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
The weird thing is that when I run a die dump in the handle method of the job, it never fires, but the artisan queue worker says it was processed correctly but the subsequent notification is where it is failing. I am not sure why that handle method in the job wouldn't be firing.
I have set my .env file to database queue driver.
I thought it might be that I didn't import the contact model, but you can see I have.
Any help would be appreciated.
Could be that because both the job and the notification are queued, the contact could be getting 'lost in transit' so to speak. try making the job non queueable, and only queue the notification (or the other way around). Or scrap the job altogether and just send the notification from the controller.
Did you check on your model path? Coz for newer laravel the path should be
use App\Models\Contact;

How to properly add external php files in Laravel 5

I have a small websockets chat written, the php part is just 2 files, server.php and Chat.php, they are both inside a bin folder and depend on ratchet and some other libraries which I downloaded to the laravel installation via composer.
server.php
require __DIR__.'/../vendor/autoload.php';
require 'Chat.php';
use Ratchet\Server\IoServer;
use Ratchet\http\HttpServer;
use Ratchet\WebSocket\WsServer;
$server = IoServer::factory(new HttpServer(new WsServer(new Chat)), 8080);
$server->run();
Chat.php
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
protected $clients;
function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
}
public function onMessage(ConnectionInterface $conn, $msg)
{
foreach ($this->clients as $client)
{
if ($client !== $conn ) {
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn)
{
$this->clients->detach($conn);
}
public function onError(ConnectionInterface $conn, \Exception $e)
{
echo 'the following error occured: ' . $e->getMessage();
$conn->close();
}
}
Now, I have that bin folder inside the laravel root, and so I am able to start the server since the server.php is looking for dependencies in vendor one level up, but what I wanna do is use all the laravel goodies within these files, especially within Chat.php.
So now for example if I write use DB in Chat.php it gives an error (which I understand, it has no way of knowing laravel), so my question is how do I include this bin folder and its files so that I can use all the laravel goodies within them?
You do not need to manually load vendor/autoload.php because laravel does that for you.
First you have to create folder inside your YourLaravelRoot/app dir(Let's name that as Services). Then move chat.php into that, rename it to ChatService.php(Change class name also to ChatService) or any appropriate name(reccomanded to ends with xxxxService so it's easier to identify) and namespace it as namespace App\Services;(Assumming that your app name is App).Namespacing correctly is important otherwise you have to manually loads it throught composer.json .Then create a artisan command and move content of server.php into handle method inside command(Let's name it ServerCommand.php). Add use App\Services\ChatService as Chat;. Register the command in Kernal.php on app/console That's it. Now you should be able to access any laravel facade inside ChatService
Summary:
YourLaravelProject
-app
--Console
Kernal.php
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
Commands\ServerCommand::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
}
}
---Commands
----ServerCommand.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use App\Services\ChatService as Chat;
class ServerCommand extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'server:run';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$server = IoServer::factory(new HttpServer(new WsServer(new Chat)), 8080);
$server->run();
}
}
--Services
---ChatService.php
<?php
namespace App\Services;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
/**
*
*/
class ChatService implements MessageComponentInterface {
{
protected $clients;
function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
}
public function onMessage(ConnectionInterface $conn, $msg)
{
foreach ($this->clients as $client)
{
if ($client !== $conn ) {
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn)
{
$this->clients->detach($conn);
}
public function onError(ConnectionInterface $conn, \Exception $e)
{
echo 'the following error occured: ' . $e->getMessage();
$conn->close();
}
}
Execute command php artisan server:run

Laravel 5 Command and Handler issue

I am working one of my project with laravel 5. During the implementation i got struct with one issue which is related to command and handler.
I used artisan command to generate command
php artisan make:command TestCommand --handler
I generated command at app/commands folder "TestCommand.php"
<?php
namespace App\Commands;
use App\Commands\Command;
class TestCommand extends Command
{
public $id;
public $name;
public function __construct($id, $name)
{
$this->id = $id;
$this->name = $name;
}
}
Also my TestCommandHandler.php looks like this
<?php
namespace App\Handlers\Commands;
use App\Commands\TestCommand;
use Illuminate\Queue\InteractsWithQueue;
class TestCommandHandler
{
/**
* Create the command handler.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the command.
*
* #param TestCommand $command
* #return void
*/
public function handle(TestCommand $command)
{
dd($command);
}
}
Whenever dispatch this command from controller it shows following issue
InvalidArgumentException in Dispatcher.php line 335:
No handler registered for command [App\Commands\TestCommand]
Please, Anybody help me to solve this problem. Thank you
By default Laravel 5.1.x does not included BusServiceProvider. So we should create BusServiceProvider.php under provider folder and include that in to config/app.php.
BusServiceProvider.php
<?php namespace App\Providers;
use Illuminate\Bus\Dispatcher;
use Illuminate\Support\ServiceProvider;
class BusServiceProvider extends ServiceProvider {
/**
* Bootstrap any application services.
*
* #param \Illuminate\Bus\Dispatcher $dispatcher
* #return void
*/
public function boot(Dispatcher $dispatcher)
{
$dispatcher->mapUsing(function($command)
{
return Dispatcher::simpleMapping(
$command, 'App\Commands', 'App\Handlers\Commands'
);
});
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
config/app.php
'providers' => [
App\Providers\BusServiceProvider::class
]
So it may help others. Thank you

Resources