diff --git a/README.md b/README.md index bbccb51..31802f3 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,8 @@ To use this option need to install symfony [lock component](https://symfony.com/ - `arguments` - Array of arguments, used to run symfony console commands or pass arguments to handler. - `priority` - Sorting priority. - `group` - Group name, see Cron Grouping section. +- `jitter` - Random delay 0-60 sec +- `interval` - Run periodic tasks by interval. Examples `10`, `10 seconds`, `1 day`. - `messenger` - Send jobs into Messenger Bus. Default `false`. You also can specify transport here `{routing: async}`, see [Symfony Routing Messages to a Transport](https://symfony.com/doc/current/messenger.html#routing-messages-to-a-transport) @@ -453,10 +455,76 @@ See example of customization ## Use ReactPHP EventLoop You can add your own periodic tasks directly to `Loop`. -The bundle uses a simple wrapper `Okvpn\Bundle\CronBundle\Runner\ScheduleLoopInterface` for the library +The bundle uses a simple wrapper `Okvpn\Bundle\CronBundle\Runner\ScheduleLoopInterface` for the library `react/event-loop` ```php +getDDog(); + $event->getLoop()->addPeriodicTimer(6.0, static function () use ($dataDogS) { + $dataDogS->set('crond', getmypid()); + }); + } +} +``` +#### Configure ReactPHP adapter + +Need to install [react/event-loop](https://github.com/reactphp/event-loop) if you want to use with async I/O, for example for handle websockets, redis. + +``` +composer req react/event-loop +``` + +```yaml +# Add file to config/packages/* +okvpn_cron: + loop_engine: okvpn_cron.react_loop # service name +``` + +```php +timers; + $loop = $event->getLoop(); + + $redis->on('message', static function (string $channel, string $payload) use ($timers, $loop) { + [$command, $args] = unserialize($payload); + if ($timers->hasTimer($envelope = $timers->find($command, $args))) { + [$timer] = $timers->getTimer($envelope); + $loop->futureTick($timer); + } + }); + + Loop::addPeriodicTimer(5.0, static function () use ($redis) { + $redis->ping(); + }); + } +} ``` License diff --git a/src/Command/CronCommand.php b/src/Command/CronCommand.php index 82df850..10f544e 100644 --- a/src/Command/CronCommand.php +++ b/src/Command/CronCommand.php @@ -91,18 +91,12 @@ protected function executeLoop(InputInterface $input, OutputInterface $output): }); } - $test = 0; - $schedulerRunner = function () use ($input, $output, $loop, &$test) { + $schedulerRunner = function () use ($input, $output, $loop) { $runAt = \microtime(true); if ($loop instanceof ReactLoopAdapter) { $loop->setDefaultLoopTime($this->getCurrentDate()); } - if ($runAt - $test < 2) { - $output->writeln("ERROR"); - } - $test = $runAt; - $this->scheduler($input, $output); $output->writeln(sprintf('[%s] All schedule tasks completed in %.3f seconds', $this->getCurrentDate()->format('Y-m-d H:i:s.u'), \microtime(true) - $runAt), OutputInterface::VERBOSITY_VERBOSE); if ($loop instanceof ReactLoopAdapter) { diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 81f47c6..74a210a 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -65,6 +65,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->integerNode('timeout')->end() ->scalarNode('interval')->end() + ->integerNode('jitter')->end() ->end() ->end() ->end(); diff --git a/src/Runner/StandaloneLoop.php b/src/Runner/StandaloneLoop.php index f061559..e618ce1 100644 --- a/src/Runner/StandaloneLoop.php +++ b/src/Runner/StandaloneLoop.php @@ -48,7 +48,6 @@ public function cancelTimer($timer): void } } - $this->timers = \array_values($this->timers); $this->needSort = true; }