zenstruck / schedule-bundle Goto Github PK
View Code? Open in Web Editor NEWSchedule Cron jobs (commands/callbacks/bash scripts) within your Symfony application.
License: MIT License
Schedule Cron jobs (commands/callbacks/bash scripts) within your Symfony application.
License: MIT License
Are you open to a possibility to configure tasks (only the types that accept string arguments) using a database.
I'm aware this can be created in my app, but having this out of the box would be a great addition to this nice package.
Hi,
I would like to use this bundle on Symfony 3.4 but it doesn't work.
There are problems with DependencyInjection component.
PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\UndefinedMethodException: Attempted to call an undefined method named "getRootNode" of class "Symfony\Component\Config\Definition\Builder\TreeBuilder".
Can you fix that ?
Thx :)
Would it be possible to add configuration for using ionice
and nice
per symfony command? Right now it needs to be set globally, for example in the cron, for all commands/tasks.
Thank you for this really nice bundle!
I was just testing the email notification on failure and I noticed that the subject_prefix
option as documented in the configuration reference https://github.com/zenstruck/schedule-bundle#full-configuration-reference didn't work as expected.
I didn't have time to debug it in detail, but my initial guess is that while the EmailHandler accepts the subject_prefix in the constructor (https://github.com/zenstruck/schedule-bundle/blob/master/src/Schedule/Extension/Handler/EmailHandler.php#L27) this argument is missing in the service definition here https://github.com/zenstruck/schedule-bundle/blob/master/src/Resources/config/mailer.xml.
I will have a better look later and submit a PR if applicable.
I would like to see the possibility to set custom task ids (a bit like the Symfony command names), so it becomes easier and recognisable to force run certain tasks.
Example:
$schedule->skip('Schedule disabled during deploy', fn (): bool => $this->isDeploying());
Becomes:
Filter Schedule callback: Zenstruck\ScheduleBundle\Schedule:165 (Zenstruck\ScheduleBundle\Schedule\Extension\CallbackExtension)
It is not recognisable which schedule this applies to if you have multiple schedules and the description is not shown either. I believe this can be improved by using a dedicated extension class that extends the CallbackExtension
, so the relevant information can be stored in there and show in the overview.
Hi, im using your bundle and want to know, how can i set timeout for bash process with yaml config?
Now i get this error and want to increase timeout;
Exception: ProcessTimedOutException: The process "/home/theillko/work/inked.com.ua/bin/update.sh" exceeded the timeout of 60 seconds.
I have a command that sends a list to group of users. This works fine when I execute the command by hand (bin/console app:MailOpenTodos
) . But in the scheduler it's not fired (the list does not appear).
I can see the entry with schedule:list and when the trigger time has been I can see it is scheduled to the next day, so the cronjob is running the schedule:run command.
What can be wrong?
Here's my schedule class:
class AppScheduleBuilder implements ScheduleBuilder
{
public function buildSchedule(Schedule $schedule): void
{
$schedule
->timezone('Europe/Madrid')
->environments('prod');
$schedule->addCommand('app:MailOpenTodos')
->description('Send the weekly report to users.')
->daily()->at("20:45");
}
}
And this is the output from schedule:list --detail
1 Scheduled Task Configured
===========================
(1/1) CommandTask: Send the weekly report to users.
---------------------------------------------------
------------------- ----------------------------------------------------
Command Name app:MailOpenTodos
Command Arguments (none)
Task ID 9039b82b7428839c1c6ac3e3cfcdeb462c9f703d
Task Class Zenstruck\ScheduleBundle\Schedule\Task\CommandTask
Frequency 45 20 * * *
Next Run Wed, Jul 15, 2020 @ 8:45 (Europe/Madrid +0200)
------------------- ----------------------------------------------------
// 1 Schedule Extension:
* Only run in [prod] environment (Zenstruck\ScheduleBundle\Schedule\Extension\EnvironmentExtension)
[OK] No schedule or task issues.
See #39 (comment)
Throw exception if any tasks are scheduled at the same time. Should help with workaround (2) in #6.
I have a command scheduled to run every minute,
when I type php bin/console schedule:list --detail
I can see next run in 1 mn. But it doesn't run autimarically until I type
php bin/console schedule:run
Any ideas how to make it run automatically ? Thanks
Hello!
I'm not sure I understood how I should configure ping extension options. According to HttpClientInterface::OPTIONS_DEFAULTS, it's
ping_on_success:
options:
json: { "text": "success" }
But in src/DependencyInjection/Configuration.php:331 options is configured as an array of scalar
->arrayNode('options')
->info('See HttpClientInterface::OPTIONS_DEFAULTS')
->scalarPrototype()->end()
->end()
So I tried this way:
ping_on_success:
options:
json: '{ "text": "success" }'
But HTTP client converts " to \u0022.
So I tried to use body option + content-type header
options:
body: '{ "text": "success" }'
headers: '{ "Content-Type": "application/json" }'
And now I have problems with headers:
In HttpClientTrait.php line 235:
[TypeError]
Argument 1 passed to Symfony\Component\HttpClient\CurlHttpClient::normalizeHeaders() must be of the type array, string given, called in /app/vendor/symfony/http-client/HttpClientTrait.php on line 162
So what's the correct way to configure ping options in yaml format?
This is going to sound totally whack, but I have intermittent issues with certain command runs failing. It only happens when the stars align, and multiple tasks run under the same scheduler run. I can't figure out the reproduction conditions, but if you imagine I have the hypothetical:
*/5 * * * * task1
*/10 * * * * task2
What ends up happening, is on ten minute intervals task1, task2, task3 will run together, every 10 minutes, (they share the same common demonitor). On half hours, at midnight, task 4+5 will also run...
You get the idea - anyway, what ends up happening is my Unit of Work with Entity Manager is obviously getting screwed up by my own user-space code and it closes the Entity Manager causing weird problems and essentially commands which might end up never being ran.
It's isn't reproducible so I can't exactly nail down how to fix, but what I'd like to do is actually run the scheduler such that I run scheduler:run but instead of grabbing any task ready to run, it is limited to only task1 and task2 for one cron.
Then I might have another scheduler:run which is only going to run task3 and task4.
Is this something that's currently possible? (I have a worry that it might have problems due to the cache lock factory so likely isn't possible).
My thinking is If I could isolate groups of tasks, I am hoping I can figure out which causes the underlying problem. Other ideas and suggestions are also welcome.
Since symfony/console 6.1: Relying on the static property "$defaultName" for setting a command name is deprecated. Add the "Symfony\Component\Console\Attribute\AsCommand" attribute to the "Zenstruck\ScheduleBundle\Command\ScheduleListCommand" class instead.
Add the ability to mark services with a Schedule
attribute to add to the schedule:
Creates a CallbackTask
that runs daily:
#[Schedule('@daily')]
class MyService
{
public function __invoke()
{
// ...
}
}
Also, an alternative to self-scheduled commands.
Creates a CommandTask
that runs weekly:
#[Schedule('@weekly')]
class MyCommand extends Command // no need to implement SelfSchedulingCommand
{
public function execute(InputInterface $input, OutputInterface $output): int
{
// ...
}
}
Task::getShortId(): string
schedule:list
table (?)Change:
* * * * * cd /path-to-your-project && bin/console schedule:run >> /dev/null 2>&1
To:
* * * * * cd /path-to-your-project && php bin/console schedule:run >> /dev/null 2>&1
(ref #12)
After tasks are run a Result
is created, but some result data is formatted or discarded.
For example if a Process
fails:
return Result::failure(
$task,
"Exit {$process->getExitCode()}: {$process->getExitCodeText()}",
$process->getOutput().$process->getErrorOutput()
);
in ProcessTaskRunner
makes it impossible to get the Process
and for example get the exit code (without extracting it from the description).
I suggest to add an array with metadata as last argument of Result::__construct
and all related static methods which can accept various data regarding the run of the task. The Process
for a process task run, the plain output for a callback task run, the plain output and exit code for a command task run, ...
An alternative would be to add an AfterTaskRun event with the above details of the task that ran and dispatch this in each task runners invoke method.
Ability to add tasks to a "trigger group" like deploy
:
class AppScheduleBuilder implements ScheduleBuilder
{
public function buildSchedule(Schedule $schedule): void
{
$schedule->addCommand('app:warm-cache')
->trigger('deploy')
->unscheduled() // disables task from bring run except when "triggered"
;
$schedule->addCommand('app:health-check')
->hourly() // also runs hourly
->trigger('deploy', priority: 10) // would run before the above task
;
// ...
}
}
Run the trigger (ie in a post deployment script):
bin/console schedule:trigger deploy
Combined with #58:
#[Schedule('@daily', trigger: 'deploy')]
class MyService
{
public function __invoke()
{
// ...
}
}
#[Schedule('@weekly', trigger: 'deploy')]
class MyCommand extends Command
{
public function execute(InputInterface $input, OutputInterface $output): int
{
// ...
}
}
A dedicated Trigger
attribute could be added to make unscheduled invokable service/console command tasks:
#[Trigger('deploy')]
class MyService
{
public function __invoke()
{
// ...
}
}
#[Trigger('deploy')]
class MyCommand extends Command
{
public function execute(InputInterface $input, OutputInterface $output): int
{
// ...
}
}
It would be useful to have documentation on available schedule configurations. In the example, I can see ->hourly() is one, but what about every minute or every five minutes?
Hello! Thanks for sharing this bundle, hope I find it useful in my projects
But for now, I have some questions that haunt me.
Thanks once again
Alias | Converts to |
---|---|
#weekly@midnight |
# #(0-2) * * # (at #midnight some day every week) |
#monthly@midnight |
# #(0-2) # * * (at #midnight on some day, once per month) |
#annually@midnight |
# #(0-2) # # * (at #midnight on some day, once per year) |
#yearly@midnight |
# #(0-2) # # * (at #midnight on some day, once per year) |
--limit=x
exit after running x tasks--memory-limit=x
exit after x memory reached--time-limit=x
exit after x tasks are runschedule:stop-daemon
or schedule:daemon --stop
to stop currently running daemon (for deployment)Only want to execute a certain task the 3rd Monday of March every year
$schedule->addCommand('app:my-command)
->description('My Command')
->skip(
'all other mondays of March',
function () {
return ((new Date('today')) != (new Date('third monday of march')));
}
)
->yearly()
->months(3)
->weeklyOn(1)
->at('09:00');
Currently, all due tasks run synchronously in the same process. Utilizing Symfony Messenger would allow for adding due tasks to a queue to run asynchronously. I believe this could partially solve #6.
Notes:
CompoundTask
's need to always be run synchronously.My provider has installed a standard Ubuntu environment with php7.2. Calling php --version shows this version. I can in parallel install other php interpreters. They can be assigned to a domain and the code is then executed accordingly. However, for symfony commands, I would have to call "kh-php74 console" to run a console command with php7.4. Running "php console" would run under 7.2.
To get this scheduler running under 7.4 I can update the cronfile and use "kh-php74 console", no issue.
Question: If I have updated the cron-file, will all commands executed by the scheduler also be executed under 7.4 or under 7.2 (as php is calling version 7.2)?
I have found when multiple CommandTask
's are due at the same time it can hit your PHP memory limit. I'm not sure what the best way to combat this is. Maybe running tasks in another process somehow?
There are two workarounds I have found:
Wrap the commands in a process:
# instead of
- task: my:command
# use
- task: 'bash:bin/console my:command'
This works but removes the ability to catch exceptions (task will still fail if an exception in the command is thrown).
Also, your environment isn't passed to the command automatically like when running an actual CommandTask
. You would need to pass it as an argument:
- task: 'bash:bin/console my:command --env=prod'
Ensure CommandTask
's do not run at the same time. Even one minute difference in frequency solves the issue. The cron hash expressions can help with this. If using a CompoundTask
to ensure tasks run in a specific order this gets more complex, you need split up the CompoundTask
and schedule the tasks after each other giving enough time for the previous to complete.
Running schedule:run
inside cron in recommended way i.e. * * * * *
and logging output of this command can result in a really long file containing many No tasks due to run.
, same thing goes for the ScheduleLoggerSubscriber
. Those messages are not really useful and are simply annoying with relatively scarce schedules.
IMHO this message is useful mainly for developers and maybe should be displayed only if this command is ran in the dev
(or non-prod
) environment? If for some reason someone 'd want to see that message on production it'd be always possible to just pass -e dev
option.
I am running a website where I need to switch on/off the Cron Tasks, at least sometimes. I am therefore storing the commands in a table of the database and recreate the config file when it changes. This works in dev-environment of Symfony, but fails in prod, as the config file zenstruck_schedule.yaml in config/packages is no longer read. To avoid clearing cache anytime I change something, if would be helpful if one could enter
php bin/console scheduler:run -c path/to/configfile
with configfile e.g. in public. This file contains only the task array, not general configurations.
How can this be achieved?
Hey there, couldn't find anything useful in the source so I thought to ask a question in case I've missed something. Say I've got three tasks scheduled to run every minute that are independent from each other. One task is a few seconds running process where the other two are lasting from 20-30 seconds (due to API wait time) bringing it to almost 60 seconds run-time in total.
I'm curious whether it's somehow possible to configure certain tasks to run asynchronously (through sub-process or something else) and some to continue as one-by-one?
I'm also aware of the fact that sub-process can't survive after main process exited, so a possible implementation might be to wait for all of the sub-processes to exit before terminating the main one.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.