laravel add scheduler dynamically - laravel

I have a system where the user can create background tasks via the UI.
The task interval are every few hours (user choice in the UI).
when the user creates a task via the ui i want to add it to the scheduler dynamically.
As the example states, this is static and not dynamic.
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
DB::table('recent_users')->delete();
})->daily();
}
Is it possible? if not, what are the alternatives?
Thanks

I don't see why it wouldn't be possible. The Kernel::schedule method will be run every time php artisan schedule:run is run. If you set it up like the documentation, should be every minute via a cron.
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
With that in mind, I don't see why you can't do something like this:
protected function schedule(Schedule $schedule)
{
// Get all tasks from the database
$tasks = Task::all();
// Go through each task to dynamically set them up.
foreach ($tasks as $task) {
// Use the scheduler to add the task at its desired frequency
$schedule->call(function() use($task) {
// Run your task here
$task->execute();
})->cron($task->frequency);
}
}
Depending on what you store, you can use whatever you like here instead of the CRON method. You might have a string stored in your database that represents one of Laravel's predefined frequencies and in which case you could do something like this:
$frequency = $task->frequency; // everyHour, everyMinute, twiceDaily etc.
$schedule->call(function() {
$task->execute();
})->$frequency();
The main thing to note here, is that the schedule isn't actually scheduling in tasks in the database or in a cron that it manages. Every time the scheduler runs (Every minute) it runs and it determines what to run based on the frequencies you give each task.
Example:
You have a task set up using ->hourly(), that is, to run on the hour, every hour.
At 00:00, the schedule runs, the ->hourly() filter passes, because the time is on the hour, so your task runs.
At 00:01, the schedule runs and but this time the ->hourly() filter fails, so your task does not run.

Related

Laravel Schedule not triggering job

I do have a docker file runing a laravel app and some runners.
The schedule is triggering the command but it is not doing anything.
Whenever I try to run the command manually it works fine.
The command consulta_a1 dispatch a job that is suposed to fail, doing so the supervisor will log it on super.txt.
When the schedule run the command nothing happens, whenever I run the comand on the console it works as expected.
I configured my kernel in the following way:
protected $commands = [
Commands\ConsultaDfeA1Command::class
];
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
if (env("AMBIENTE") == "2") {
$schedule->command('consultar_a1')->dailyAt('12:23');
$schedule->command('consultar_a1')->dailyAt('12:28');
}
if (env("AMBIENTE") == "1") {
$schedule->command('consultar_a1')->cron('0 0,3,6,9,12,18,21 * * *');
}
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
In this screenshot we can se that the scheduler is configured and that I ran the exact command that the schedule is suposed to work.
The cron triggered the schedule.
But whenever I check my supervisor jobs log just the manual actions were triggered.
Crontab -l:
* * * * * /usr/local/bin/php /var/www/artisan schedule:run 1>> /var/log/cron-log 2>&1
I have no idea what is happening and if any other infos are missing.
I know this is old but did you find a solution? I've the same probleme:
$schedule->command(...) and $schedule->exec(...) won't work, no error message, schedule says "Running scheduled command" but nothing happens.
on the other hand $schedule->call(function () {...} will work...
I suspect it has to do with the ovh shared hosting the script is run on but searched the internet for a week now and no solution.

How can I run in background command, which runs only in foreground?

I have the command, which works like php artisan queue:listen. And it can't work in background in common, but I have to add it to cron tab, but it does not work there. Does it possible to do something like php artisan schedule:run ? The most imortant that when I interrupt this command, all functionalyty will stop. What do I have to do in this situation?
Laravel has his own cron. First of all, you should add Laravel cron to Linux system cron
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
then you can add your commands to Laravel cron.
Laravel crons lives inside a file /app/Console/Kernel.php
the are should be inside function
protected function schedule(Schedule $schedule)
for example
protected function schedule(Schedule $schedule)
{
$schedule->command('emails:send Taylor --force')->cron('* * * * *');
}
But if you want your command run as a system process not as a cron you should use supervisors program(supervisord) or you can create for PHP command file a systemd service file and then run as if the are a normal systemd service and even manage this service through monit program in with web interface as well
If your php script is a process it means that the constructor method of class runs only ones when you start your script and if you red db data in the constructor that data in the script would be stale
Your process script should be process something like this
class OpenOrders extends Command
{
public function __construct()
{
parent::__construct();
}
public function handle()
{
$this->initTicker();
$this->updateBalances();
//the Process
while (true) {
//this is the right place to read DB data
$this->getAllOptions();
$this->openOrders = $this->getOpenOrders();
}
return 0;
}
}

how to save data in the background every 2 minutes in Laravel

we're making a web app that's supposed to save the patient's viral signs history in the database, like every two minutes or so in the background. is it possible to do that in laravel if so how can i do it?
I recommend using job:
php artisan make:job PatientViralSignsJob
this command will generate class PatientViralSignsJob in app\Jobs folder.
in the PatientViralSignsJob ... hande() method you could write your logic
public function handle()
{
// write your code here ...
}
finally register your job class in Console\Kernel.php in schedule method:
protected function schedule(Schedule $schedule)
{
$schedule->job(new PatientViralSignsJob())->everyFiveMinutes();
}
this will make your handle method in PatientViralSignsJob executed every five minutes
more details in:
https://laravel.com/docs/7.x/queues#creating-jobs

Laravel scheduler cron options from database

I am new to laravel.
I am finding how can i execute schedules.
The schedule parameters (frequency, command) are stored in a mysql table.
I have thought a solution which is:
Use file_put_contents to write in app/Console/Kernel.
Any better idea would be welcome.
Thanks in advance,
Chris Pappas
The frequency of a certain command is defined on multiple levels. The Cron entry on your server calls the schedular every minute. In your scheduler there are frequency options as well.
One of the possibilities to let paramaters that are stored in the database define the frequency of command executions is to add a executed_at field to the table and a local scope to your Commands model that validates the schedule parameters in your mysql table:
public function scopeReadyToExecute($query)
{
return $query->where('executed_at', '<=', Carbon::now()->subMinutes(5)->toDateTimeString());
}
In this example the frequency is 5 minutes, of course you have to change this value according the the value in the frequency field.
Now, you could for example define master:command in Kernel.php to be executed every minute:
$schedule->command('master:command')->everyMinute()
In the handle of master:command you call the scope function to get the commands that are ready to execute:
public function handle()
{
$commands = Command::readyToExecute()->get();
foreach ($commands as $command) {
$this->call($command->name)
}
}
Each command that is ready to execute according to the parameters defined in your table will be executed.
Good luck!
Here in my solution.
app/Console/Kernel.php
$report_schedules = ReportSchedule::all();
foreach ($report_schedules as $report_schedule) {
$method_name = (string)$report_schedule->report->method_name;
$schedule->call(function () use ($method_name, $report_schedule) {
$emailSchedules = new EmailSchedules();
$email_List=array_unique(array_merge($report_schedule->users()->get()->lists("email")->toArray(), $report_schedule->groups()->with(["users"=>function ($query){$query->select("email");}])->get()->toArray()));
$users=\App\User::whereIn("email",$email_List)->get(["first_name","last_name","email"]);
$users_to=[];
$emails_to=[];
foreach($users as $user){
array_push($users_to,$user->first_name." ".$user->last_name);
array_push($emails_to,$user->email);
}
$emailSchedules->$method_name($emails_to,$users_to);
})->cron($report_schedule->frequency)->name('mail')->timezone("Europe/Athens");
}
Hope that help someone in the future.

running a task every five minutes without overlapping?

Quoting https://laravel.com/docs/5.1/scheduling#preventing-task-overlaps ,
$schedule->command('emails:send')->withoutOverlapping();
In this example, the emails:send Artisan command will be run every
minute if it is not already running.
What if I wanted the task to run every five minutes instead? Could I do this?:
$schedule->command('emails:send')->everyFiveMinutes()->withoutOverlapping();
Yes you can do this. command returns an instance of Event the underlying code for Event has a fluent interface which allows you to chain these together in this way.
You can see this for yourself if you look at the withoutOverlapping method.
/**
* Do not allow the event to overlap each other.
*
* #return $this
*/
public function withoutOverlapping()
{
$this->withoutOverlapping = true;
return $this->skip(function () {
return file_exists($this->mutexPath());
});
}

Resources