-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a0d00a1
Showing
31 changed files
with
1,141 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
The MIT License (MIT). | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# Okvpn - Cron Bundle | ||
|
||
This bundle provides interfaces for registering scheduled tasks within your Symfony application. | ||
|
||
### Purpose | ||
This is a more simpler alternative of existing cron bundle without doctrine deps, | ||
supporting invoke a service as cron job. | ||
Here also added support middleware for customization handling cron jobs across a cluster install: | ||
(Send jobs to message queue, like Symfony Messenger; locking, etc.) | ||
|
||
Features | ||
-------- | ||
|
||
- Not need doctrine/database. | ||
- Load a cron job from a different storage. | ||
- Support many engines to run cron (in parallel process, message queue, consistently). | ||
- Support many types of cron handlers/command: (services, symfony commands, UNIX commands). | ||
- Middleware and customization. | ||
|
||
Usage | ||
----- | ||
|
||
To regularly run a set of commands from your application, configure your system to run the | ||
oro:cron command every minute. On UNIX-based systems, you can simply set up a crontab entry for this: | ||
|
||
``` | ||
*/1 * * * * /path/to/php /path/to/bin/console okvpn:cron:run --env=prod > /dev/null | ||
``` | ||
|
||
Add cron commands | ||
|
||
``` | ||
services: | ||
app.you_cron_service: | ||
class: App/Cron/YouService | ||
tags: | ||
- { name: okvpn.cron, cron: '*/5 * * * *', lock: true, arguments: {'arg1': 5}, async: true } | ||
``` | ||
|
||
where: | ||
|
||
- `cron` - A cron expression. (Optional). If empty, the command will run always. | ||
- `lock` - Prevent to run the command again, if prev. command is not finished yet. (Optional). | ||
To use it required symfony [lock component](https://symfony.com/doc/4.4/components/lock.html) | ||
- `async` - Run command async in the new process without blocking main thread | ||
- `arguments` - Array command of arguments. (Optional). | ||
- `lockName` - Lock name. (Optional). | ||
- `lockTtl` - Set ttl (Time To Live) for expiring locks. (Optional). | ||
|
||
### Cron Handlers | ||
|
||
1. Service. | ||
|
||
```php | ||
<?php | ||
|
||
namespace App\Cron; | ||
|
||
class MyCron | ||
{ | ||
public function __invoke($arguments) | ||
{ | ||
// processing... | ||
} | ||
} | ||
``` | ||
|
||
``` | ||
services: | ||
App\Cron\MyCron: | ||
tags: | ||
- { name: okvpn.cron, cron: '*/5 * * * *' } | ||
``` | ||
|
||
2. Command | ||
|
||
``` | ||
services: | ||
App\Command\CronCommand: | ||
tags: | ||
- { name: console.command } | ||
- { name: okvpn.cron, cron: '*/5 * * * *' } | ||
``` | ||
|
||
### Custom cron loaders | ||
|
||
```php | ||
<?php declare(strict_types=1); | ||
|
||
use Okvpn\Bundle\CronBundle\Loader\ScheduleLoaderInterface; | ||
|
||
final class DatabaseScheduleLoader implements ScheduleLoaderInterface | ||
{ | ||
private $configuration; | ||
private $factory; | ||
|
||
public function __construct(array $configuration, ScheduleFactoryInterface $factory) | ||
{ | ||
$this->factory = $factory; | ||
$this->configuration = $configuration; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public function getSchedules(): iterable | ||
{ | ||
foreach ($this->configuration as $config) { | ||
yield $this->factory->create($config); | ||
} | ||
} | ||
} | ||
|
||
``` | ||
|
||
License | ||
--- | ||
|
||
MIT License. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
{ | ||
"name": "okvpn/cron-bundle", | ||
"description": "Symfony Cron Bundle for registering and execute scheduled tasks", | ||
"type": "symfony-bundle", | ||
"license": "MIT", | ||
"homepage": "https://github.com/vtsykun/cron-bundle", | ||
"support": { | ||
"email": "[email protected]", | ||
"issues": "https://github.com/vtsykun/cron-bundle/issues", | ||
"source": "https://github.com/vtsykun/cron-bundle/releases" | ||
}, | ||
"keywords": [ | ||
"cron-bundle", | ||
"symfony-cron", | ||
"cron", | ||
"symfony", | ||
"bundle" | ||
], | ||
"authors": [ | ||
{ | ||
"name": "Uladzimir Tsykun", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"require": { | ||
"php": "^7.2.5", | ||
"symfony/framework-bundle": "^3.4|^4.2|^5.0", | ||
"mtdowling/cron-expression": "^1.1" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Okvpn\\Bundle\\CronBundle\\": "src/" | ||
} | ||
}, | ||
"extra": { | ||
"branch-alias": { | ||
"dev-master": "1.0-dev" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Okvpn\Bundle\CronBundle\Command; | ||
|
||
use Okvpn\Bundle\CronBundle\Loader\ScheduleLoaderInterface; | ||
use Okvpn\Bundle\CronBundle\Runner\ScheduleRunnerInterface; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Input\InputOption; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
|
||
class CronCommand extends Command | ||
{ | ||
private $scheduleRunner; | ||
private $loader; | ||
|
||
/** | ||
* @param ScheduleRunnerInterface $scheduleRunner | ||
* @param ScheduleLoaderInterface $loader | ||
*/ | ||
public function __construct(ScheduleRunnerInterface $scheduleRunner, ScheduleLoaderInterface $loader) | ||
{ | ||
$this->scheduleRunner = $scheduleRunner; | ||
$this->loader = $loader; | ||
|
||
parent::__construct(); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function configure(): void | ||
{ | ||
$this->setName('okvpn:cron:run') | ||
->addOption('with', null, InputOption::VALUE_IS_ARRAY, 'StampFqcn to add command stamp to all schedules') | ||
->addOption('without', null, InputOption::VALUE_IS_ARRAY, 'StampFqcn to remove command stamp from all schedules.') | ||
->addOption('command', null, InputOption::VALUE_OPTIONAL, 'Run only selected command') | ||
->setDescription('Runs any currently schedule cron'); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function execute(InputInterface $input, OutputInterface $output) | ||
{ | ||
$command = $input->getOption('command'); | ||
foreach ($this->loader->getSchedules() as $schedule) { | ||
if (null !== $command && $schedule->getCommand() !== $command) { | ||
continue; | ||
} | ||
|
||
$output->writeln(" > Scheduling run for command {$schedule->getCommand()} ..."); | ||
$this->scheduleRunner->execute($schedule); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Okvpn\Bundle\CronBundle\Command; | ||
|
||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
|
||
class CronExecuteCommand extends Command | ||
{ | ||
public static $defaultName = 'okvpn:cron:execute'; | ||
|
||
private $redis; | ||
private $cronEngine; | ||
|
||
public function __construct() | ||
{ | ||
parent::__construct(null); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected function configure() | ||
{ | ||
$this->addArgument('job', InputArgument::REQUIRED, 'Cron job id') | ||
->setDescription('Execute cron command for job id'); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected function execute(InputInterface $input, OutputInterface $output) | ||
{ | ||
$command = $this->redis->get($input->getArgument('job')); | ||
if (empty($command)) { | ||
$output->writeln('Job not found'); | ||
} | ||
$command = json_decode($command, true); | ||
|
||
$this->cronEngine->run($command['command'], $command['arguments'] ?? []); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?php | ||
|
||
namespace Okvpn\Bundle\CronBundle\DependencyInjection; | ||
|
||
use Symfony\Component\Config\Definition\Builder\TreeBuilder; | ||
use Symfony\Component\Config\Definition\ConfigurationInterface; | ||
|
||
/** | ||
* This is the class that validates and merges configuration from your app/config files. | ||
* | ||
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html} | ||
*/ | ||
class Configuration implements ConfigurationInterface | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getConfigTreeBuilder() | ||
{ | ||
$treeBuilder = new TreeBuilder(); | ||
$rootNode = $treeBuilder->root('okvpn_cron'); | ||
|
||
// Here you should define the parameters that are allowed to | ||
// configure your bundle. See the documentation linked above for | ||
// more information on that topic. | ||
|
||
return $treeBuilder; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
namespace Okvpn\Bundle\CronBundle\DependencyInjection; | ||
|
||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
use Symfony\Component\Config\FileLocator; | ||
use Symfony\Component\HttpKernel\DependencyInjection\Extension; | ||
use Symfony\Component\DependencyInjection\Loader; | ||
|
||
/** | ||
* This is the class that loads and manages your bundle configuration. | ||
* | ||
* @link http://symfony.com/doc/current/cookbook/bundles/extension.html | ||
*/ | ||
class OkvpnCronExtension extends Extension | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function load(array $configs, ContainerBuilder $container) | ||
{ | ||
$configuration = new Configuration(); | ||
$config = $this->processConfiguration($configuration, $configs); | ||
|
||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); | ||
$loader->load('services.yml'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Okvpn\Bundle\CronBundle\Loader; | ||
|
||
final class ArrayScheduleLoader implements ScheduleLoaderInterface | ||
{ | ||
private $configuration; | ||
private $factory; | ||
|
||
public function __construct(array $configuration, ScheduleFactoryInterface $factory) | ||
{ | ||
$this->factory = $factory; | ||
$this->configuration = $configuration; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public function getSchedules(): iterable | ||
{ | ||
foreach ($this->configuration as $config) { | ||
yield $this->factory->create($config); | ||
} | ||
} | ||
} |
Oops, something went wrong.