Trying to run a function in Laravel that's quite large and fetches a lot of data from Google Places API and stores parts in my database as new entries in a table. The problem is it auto-discovers new entries for me near my current entries, and that creates more jobs.
When I just access the command via GET it times out eventually. I've tried running it as a scheduled command with Redis but to be frank I can't seem to figure out how it works. I've created a job, I tried to queue it with dispatch, but then it tries to run it immediately right now and it times out eventually again.
How do I run this large task without it pausing my entire server?
Thanks
Zach
I is really simple and you do not need to stop server. It is just CRON job. Use Laravel Schedule.
When using the scheduler, you only need to add the following Cron entry to your server.
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
Class example:
namespace App\Console;
use DB;
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 = [
//
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
DB::table('recent_users')->delete();
})->daily();
}
}
More: https://laravel.com/docs/5.6/scheduling
Nice video about laravel scheduling: https://www.youtube.com/watch?v=mp-XZm7INl8
Related
I'm building a project with Laravel 7.28 on localhost. I need to update a PDF every hour. For the beginning I created a command:
<?php
namespace App\Console\Commands;
use App\Event;
use Illuminate\Console\Command;
class PDF extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'pdf:update';
/**
* The console command description.
*
* #var string
*/
protected $description = 'All Country PDFs updated';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
$event = new Event();
$event->user_id = 1;
$event->save();
echo 'done';
}
}
It just insert a record into events table and works fine. Then I edited the Kernel.php under App\Console directory.
<?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\PDF::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('pdf:update')->everyMinute();
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}
}
Finally, I run php artisan schedule:run. I was expecting that the command runs every minute but it just runs once. is this a problem on localhost or did I do something wrong?
The php artisan schedule:run just runs once by its definition:
The schedule:run Artisan command will evaluate all of your scheduled
tasks and determine if they need to run based on the server's current
time.
If you want to do it every minute you should use a scheduled process control system like supervisor or crontab or etc. (more info here)
In case if you are using laravel 8.x and running on a development/local server you can use the following command and it will work for you:
php artisan schedule:work
For Laravel 7 you can also use below command to run in your local
while true; do php artisan schedule:run; sleep 60; done
On windows localhost
First of all set your desired schedule job on the run method inside
App\Console\Kernel More information on the Laravel website page here
Secondly on the command line run the following
command
php artisan schedule:work
I am developing a Laravel application for a client company of mine. That company has a server guy. In the middle of the development process, I asked him to set up a server for the application. But he set up a server without any kind of automated deployments procedure instead he gave me a C-Pannel to deploy the changes manually. The application became so complex and now manual deployments became a very tedious task. I am manually building js and css and uploading them to the server. After a heated argument with him, I finally made him work on automated deployments. Instead of properly putting deployments he has put it this way.
<?php
//app/Console/Commands/GitPull.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class GitPull extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'git:pull';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Get updates from git server';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
exec('git pull origin master');
}
}
<?php
app/Console/Kernel.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\GitPull::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('git:pull')
->everyMinute();
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
Basically he has put a scheduler to execute git pull every minute. Is this the correct way to put deployments? What are the drawbacks in this way? Do the deployments have to be dependent on the application? Is it possible to add automated deployments without the help of the laravel framework? I am not very familiar with dev-ops.
Also, my source code is in bitbucket. I am ready to answer any questions regarding this. Thanks in advance.
I certainly would not use a Laravel command to run deployments. Automated deployments can be as simple or complex as needed, but here are some things I expect a build agent to do:
Listen to changes to master to do a production deploy
Run tests (and alert and stop deployment if they fail)
Build my static assets (js/css/etc)
Copy code to server (several ways to do this)
Run migrations
Restart queues so they are running with latest code
Since you're on bitbucket you could look into pipelines to do your ci/cd.
I'm developing the app for the customer and he wants to start some jobs in special time
I must run it in jobs, that's right?
for example, he wants to publish a post have 2 status published or waiting
and in send page, he can set time for publish post
how I can develop this in jobs?
ScanJob::dispatch($property->Name, $property->Owner, $Scan->id)->delay(Carbon::now()->addHour(Carbon::now()->diffInHours($Time)));
it's my first try
get diff time in hours and add it from delay
There are basically two ways via which you can solve your problem:
Create a Laravel Artisan command(you can use other methods also that Laravel provides, but I found Artisan to be fun and more flexible, helps avoid the rework) and schedule it accordingly.
Create a Queued Job and dispatch it for some later time, but it has some limitation like, the Amazon SQS queue service has a maximum delay time of 15 minutes.
Now, what is to be done:
In my opinion, you should use Solution 1 as it is more flexible and gives you more control.
Queues are used for 2 things. First, ideally, the task you want to perform should be done in the next 30-45 minutes. Second, the task is time intensive and you don't want to block the thread because of that.
Now the FUN part.
Note: You need not worry, Laravel will perform the majority of the steps for you. I am mentioning each and every step for the sake of not skipping the knowledge.
Step 1: Run the following command to create an Artisan Console Command(Remember to be in your project's root path.):
php artisan make:command PublishSomething
The command will now be available for further development at app/Console/Commands.
Step 2: You will see a handle method inside the Class like following, this is where all of your logic will exist.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class PublishSomething extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'something:publish';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Publishes something amazing!';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
}
}
Step 3: Let's add some logic inside our handle method
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$this->info('Publishing something cool!');
// you can add your own custom logic here.
}
Step 4: After you have added your logic, now we need to test it, you can do so like:
php artisan something:publish
Step 5: Our function is running all fine. Now we will schedule the command. Inside app/Console you will find a file Console.php, this class is responsible for all task scheduling registration, in our case.
<?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 = [
//
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
Notice the schedule function here, this is where we will add the schedule logic.
Step 6: Now we will schedule our command to run every 5 minutes. You can change the time period very easily, Laravel provides some pre-made frequency options, and you have your own custom schedule also.
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('something:publish')->everyFiveMinutes(); // our schedule
}
Step 7: Now, Laravel's task scheduler itself is dependent on Cron. So to start the schedule, we will add the following file to our crontab.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
That's it! We are done. You have created your own custom command and scheduled it for every 5 minutes.
You can learn more about Laravel Artisan Command & Laravel Task Scheduling.
Hope it helps!
I have several tasks that I've scheduled to run at various times. Here are those tasks:
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\PostGetter::class
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('post_getter 0 5')
->cron('*/15 * * * *');
$schedule->command('post_getter 5 10')
->cron('*/15 * * * *');
$schedule->command('post_getter 10 20')
->everyThirtyMinutes();
$schedule->command('post_getter 20 30')
->hourly();
}
}
In order to log when each of these tasks is run, I've added the following piece of code in the PostGetter class to log when the task has begun running:
Log::info('Post getter for {arg1} and {arg2} has started.');
Where arg1 and arg2 are the two arguments in the scheduler (e.g. 0 5 or 5 10).
I've noticed in my log file that these scripts don't seem to run at the same time. For example, when the first task is run (post_getter 0 5), the second task (post_getter 5 10) only seems to run after the first task is done, and so on.
How can I make it so that all of the tasks listed in the Kernel class are run at the same time and don't have to wait for the previous task to finish?
Cronjobs / scheduled processes in Laravel are run sequentially.
There is an article about parallel processing of scheduled tasks in Laravel 4.3. Currently there is no parallel processing in Laravel 5.
I solved this by adding custom cron jobs instead of running it through the Laravel scheduler.
From Laravel version 5.7, If you would like to run commands in the background so that they may all run simultaneously, you may use the runInBackground method:
$schedule->command('analytics:report')
->daily()
->runInBackground();
I am building web app in PHP which is used to schedule tasks in the future. In the background I am supposed to Poll the database every 2 min to see if there is any upcoming task. How do I implement polling. Javascript solution is not helpful as the user can be on any of the pages on the webapp, but the system should keep pooling the DB.
Cron is one way but still I have to poll the database to create a cron job. What is the best way to implement it?
Thanks
Create a cron job that is executed once every X minutes and make that job check the DB. If there is a new upcoming task, just make the job launch it.
Create an 'execute:tasks' artisan command, so you can poll your database whenever you need to execute your tasks. You should be able to run it this way:
php artisan execute:tasks
Your command will call some controller action (or a class method) to poll the database and find if there are tasks available to be executed.
Then you just need to create a cron job that will execute that artisan command every 2 minutes:
*/2 * * * * php artisan execute:tasks
This is an example of Artisan command:
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class ExecuteTasksCommand extends Command {
/**
* The console command name.
*
* #var string
*/
protected $name = 'execute:tasks';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Find and execute available tasks.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return void
*/
public function fire()
{
(new ExecuteTasksClass)->findAndExecute();
}
}
You just have to name this file something like app/commands/ExecuteTasksCommand.php
And add this to app\start\artisan.php:
Artisan::add(new ExecuteTasksCommand);