From 94ce01d5c585d079da601f575f93f0a3bbd9687d Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Mon, 31 Mar 2014 23:34:21 -0400 Subject: [PATCH 01/25] $scheduler can now schedule with arguments --- src/Indatus/Dispatcher/ConfigResolver.php | 24 ++++++++-- .../Drivers/Cron/ScheduleService.php | 14 +++++- .../Dispatcher/Drivers/Cron/Scheduler.php | 11 ++++- src/Indatus/Dispatcher/Schedulable.php | 32 ++++++++++++- src/Indatus/Dispatcher/ScheduledCommand.php | 2 +- .../Dispatcher/ScheduledCommandInterface.php | 2 +- tests/Drivers/Cron/TestCronScheduler.php | 12 ++++- tests/TestBackgroundProcess.php | 46 ------------------- tests/TestConfigResolver.php | 23 +++++++++- tests/TestSchedulable.php | 44 ++++++++++++++++++ tests/TestScheduledCommand.php | 5 +- 11 files changed, 156 insertions(+), 59 deletions(-) delete mode 100644 tests/TestBackgroundProcess.php create mode 100644 tests/TestSchedulable.php diff --git a/src/Indatus/Dispatcher/ConfigResolver.php b/src/Indatus/Dispatcher/ConfigResolver.php index 471dfb9..395c8c1 100644 --- a/src/Indatus/Dispatcher/ConfigResolver.php +++ b/src/Indatus/Dispatcher/ConfigResolver.php @@ -16,13 +16,31 @@ class ConfigResolver { - public function resolveDriverClass($className) + /** + * Resolve a class based on the driver configuration + * + * @param $className + * @param array $arguments + * + * @return mixed + */ + public function resolveDriverClass($className, $arguments = []) { try { - return App::make(Config::get('dispatcher::driver').'\\'.$className); + return App::make( + Config::get('dispatcher::driver').'\\'.$className, [ + $this, + $arguments + ] + ); } catch (\ReflectionException $e) { $driver = ucwords(strtolower(Config::get('dispatcher::driver'))); - return App::make('Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className); + return App::make( + 'Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className, [ + $this, + $arguments + ] + ); } } diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index dc8aefe..3f8ed65 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -24,8 +24,18 @@ class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { public function isDue(ScheduledCommandInterface $command) { $scheduler = App::make('Indatus\Dispatcher\Schedulable'); - $cron = CronExpression::factory($command->schedule($scheduler)->getSchedule()); - return $cron->isDue(); + $schedules = $command->schedule($scheduler); + if (!is_array($schedules)) { + $schedules = array($schedules); + } + foreach ($schedules as $schedule) { + $cron = CronExpression::factory($schedule->getSchedule()); + if ($cron->isDue()) { + return true; + } + } + + return false; } /** diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index 7bf2f9b..d0de659 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -12,7 +12,7 @@ use Indatus\Dispatcher\Schedulable; -class Scheduler implements Schedulable +class Scheduler extends Schedulable { /** @@ -282,6 +282,15 @@ public function everyWeekday() return $this; } + /** + * @inheritDoc + * @return $this + */ + public function args(array $arguments) + { + return parent::args($arguments); + } + /** * @todo This is a terrible method name */ diff --git a/src/Indatus/Dispatcher/Schedulable.php b/src/Indatus/Dispatcher/Schedulable.php index 173de66..16a92ef 100644 --- a/src/Indatus/Dispatcher/Schedulable.php +++ b/src/Indatus/Dispatcher/Schedulable.php @@ -10,7 +10,37 @@ */ namespace Indatus\Dispatcher; -interface Schedulable +abstract class Schedulable { + protected $configResolver; + protected $arguments; + + public function __construct(ConfigResolver $configResolver, $arguments = []) + { + $this->configResolver = $configResolver; + $this->arguments = $arguments; + } + + /** + * Define arguments for this command when it runs. + * + * @param array $arguments + * + * @return \Indatus\Dispatcher\Schedulable + */ + public function args(array $arguments) + { + return $this->configResolver->resolveDriverClass('Scheduler', $arguments); + } + + /** + * Get the arguments for this command. + * + * @return array + */ + public function getArguments() + { + return $this->arguments; + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/ScheduledCommand.php b/src/Indatus/Dispatcher/ScheduledCommand.php index dcb8ad2..03fc718 100644 --- a/src/Indatus/Dispatcher/ScheduledCommand.php +++ b/src/Indatus/Dispatcher/ScheduledCommand.php @@ -37,7 +37,7 @@ public function user() /** * Environment(s) under which the given command should run * - * @return string + * @return string|array */ public function environment() { diff --git a/src/Indatus/Dispatcher/ScheduledCommandInterface.php b/src/Indatus/Dispatcher/ScheduledCommandInterface.php index d0614ab..7d0452f 100644 --- a/src/Indatus/Dispatcher/ScheduledCommandInterface.php +++ b/src/Indatus/Dispatcher/ScheduledCommandInterface.php @@ -23,7 +23,7 @@ public function schedule(Schedulable $scheduler); /** * Environment(s) under which the given command should run * Defaults to '*' for all environments - * @return string + * @return string|array */ public function environment(); diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index 324b7d7..c3ed99f 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -17,7 +17,7 @@ class TestCronScheduler extends TestCase public function setUp() { parent::setUp(); - $this->scheduler = new Scheduler(); + $this->scheduler = new Scheduler(App::make('Indatus\Dispatcher\ConfigResolver')); } /** @@ -146,4 +146,14 @@ public function testEveryWeekday() $this->assertEquals($this->scheduler->getSchedule(), Scheduler::ANY.' '.Scheduler::ANY.' '.Scheduler::ANY.' '.Scheduler::ANY.' '.Scheduler::MONDAY.'-'.Scheduler::FRIDAY); } + public function testArgs() + { + $args = array('testArgument'); + + /** @var \Indatus\Dispatcher\Scheduleable $scheduler */ + $scheduler = $this->scheduler->args($args); + $this->assertInstanceOf($this->schedularClass, $scheduler); + $this->assertEquals($args, $scheduler->getArguments()); + } + } \ No newline at end of file diff --git a/tests/TestBackgroundProcess.php b/tests/TestBackgroundProcess.php deleted file mode 100644 index fa2e041..0000000 --- a/tests/TestBackgroundProcess.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ - -use Mockery as m; -use Indatus\Dispatcher\Drivers\Cron\Scheduler; -use Indatus\Dispatcher\BackgroundProcess; - -class TestBackgroundProcess extends TestCase -{ - /** - * @var Indatus\Dispatcher\ScheduledCommand - */ - private $scheduledCommand; - - public function setUp() - { - parent::setUp(); - - $this->scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand[schedule]'); - - $this->app->instance('Indatus\Dispatcher\Schedulable', new Scheduler()); - } - - public function tearDown() - { - parent::tearDown(); - m::close(); - } - - public function testSomething() - { - - } - - /*public function testRunAsOnWindows() - { - $platform = m::mock('Indatus\Dispatcher\Platform'); - $platform->shouldReceive('isWindows')->once()->andReturn(false); - $this->app->instance('Indatus\Dispatcher\Platform', $platform); - - $backgroundProcess = new BackgroundProcess(); - //$backgroundProcess->run(); - }*/ -} \ No newline at end of file diff --git a/tests/TestConfigResolver.php b/tests/TestConfigResolver.php index d22b64e..e4909a5 100644 --- a/tests/TestConfigResolver.php +++ b/tests/TestConfigResolver.php @@ -19,14 +19,33 @@ public function tearDown() public function testLoadingPackagedDriver() { $resolver = new ConfigResolver(); - $this->assertInstanceOf('Indatus\Dispatcher\Drivers\Cron\Scheduler', $resolver->resolveDriverClass('Scheduler')); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Drivers\Cron\Scheduler', + $resolver->resolveDriverClass('Scheduler') + ); + } + + public function testLoadingPackagedDriverWithArguments() + { + $args = array('testArgument'); + $resolver = new ConfigResolver(); + + /** @var \Indatus\Dispatcher\Schedulable $scheduler */ + $scheduler = $resolver->resolveDriverClass('Scheduler', $args); + $this->assertEquals( + $args, + $scheduler->getArguments() + ); } public function testLoadingCustomDriver() { Config::shouldReceive('get')->andReturn('Indatus\Dispatcher\Drivers\Cron'); $resolver = new ConfigResolver(); - $this->assertInstanceOf('Indatus\Dispatcher\Schedulable', $resolver->resolveDriverClass('Scheduler')); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Schedulable', + $resolver->resolveDriverClass('Scheduler') + ); } } \ No newline at end of file diff --git a/tests/TestSchedulable.php b/tests/TestSchedulable.php new file mode 100644 index 0000000..aa48624 --- /dev/null +++ b/tests/TestSchedulable.php @@ -0,0 +1,44 @@ + + */ + +use Mockery as m; +use Indatus\Dispatcher\BackgroundProcess; + +class TestSchedulable extends TestCase +{ + + public function tearDown() + { + parent::tearDown(); + m::close(); + } + + public function testArguments() + { + $args = ['type' => 'scheduled']; + /** @var \Indatus\Dispatcher\Schedulable $scheduleable */ + $scheduleable = $this->getMockForAbstractClass( + 'Indatus\Dispatcher\Schedulable', array( + App::make('Indatus\Dispatcher\ConfigResolver') + )); + $newScheduleable = $scheduleable->args($args); + $this->assertEquals($args, $newScheduleable->getArguments()); + } + + public function testArgumentsConstructor() + { + $args = ['type' => 'scheduled']; + + /** @var \Indatus\Dispatcher\Schedulable $scheduleable */ + $scheduleable = $this->getMockForAbstractClass( + 'Indatus\Dispatcher\Schedulable', array( + App::make('Indatus\Dispatcher\ConfigResolver'), + $args + ) + ); + + $this->assertEquals($args, $scheduleable->getArguments()); + } +} \ No newline at end of file diff --git a/tests/TestScheduledCommand.php b/tests/TestScheduledCommand.php index 1a3fc84..9f5bb34 100644 --- a/tests/TestScheduledCommand.php +++ b/tests/TestScheduledCommand.php @@ -19,7 +19,10 @@ public function setUp() $this->scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand[schedule]'); - $this->app->instance('Indatus\Dispatcher\Schedulable', new Scheduler()); + $this->app->instance( + 'Indatus\Dispatcher\Schedulable', + new Scheduler(App::make('Indatus\Dispatcher\ConfigResolver')) + ); } public function tearDown() From 814cc1e4feddb2028d86d3ded635accd15fea299 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Mon, 31 Mar 2014 23:40:36 -0400 Subject: [PATCH 02/25] PHP 5.3 compatibility --- src/Indatus/Dispatcher/ConfigResolver.php | 10 +++++----- src/Indatus/Dispatcher/Schedulable.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Indatus/Dispatcher/ConfigResolver.php b/src/Indatus/Dispatcher/ConfigResolver.php index 395c8c1..f0b84fa 100644 --- a/src/Indatus/Dispatcher/ConfigResolver.php +++ b/src/Indatus/Dispatcher/ConfigResolver.php @@ -24,22 +24,22 @@ class ConfigResolver * * @return mixed */ - public function resolveDriverClass($className, $arguments = []) + public function resolveDriverClass($className, $arguments = array()) { try { return App::make( - Config::get('dispatcher::driver').'\\'.$className, [ + Config::get('dispatcher::driver').'\\'.$className, array( $this, $arguments - ] + ) ); } catch (\ReflectionException $e) { $driver = ucwords(strtolower(Config::get('dispatcher::driver'))); return App::make( - 'Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className, [ + 'Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className, array( $this, $arguments - ] + ) ); } } diff --git a/src/Indatus/Dispatcher/Schedulable.php b/src/Indatus/Dispatcher/Schedulable.php index 16a92ef..d8affb1 100644 --- a/src/Indatus/Dispatcher/Schedulable.php +++ b/src/Indatus/Dispatcher/Schedulable.php @@ -16,7 +16,7 @@ abstract class Schedulable protected $arguments; - public function __construct(ConfigResolver $configResolver, $arguments = []) + public function __construct(ConfigResolver $configResolver, $arguments = array()) { $this->configResolver = $configResolver; $this->arguments = $arguments; From 91d0d91a8b491bf8b23b8614311195aeffcd1253 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Thu, 3 Apr 2014 22:03:26 -0400 Subject: [PATCH 03/25] Moved classes to Scheduling namespace --- README.md | 10 ++-- .../Dispatcher/BackgroundProcessRunner.php | 1 + src/Indatus/Dispatcher/Commands/Make.php | 4 +- src/Indatus/Dispatcher/ConfigResolver.php | 3 +- .../Drivers/Cron/ScheduleService.php | 25 +++++++-- .../Dispatcher/Drivers/Cron/Scheduler.php | 2 +- src/Indatus/Dispatcher/Queue.php | 46 +++++++++++++++++ src/Indatus/Dispatcher/QueueItem.php | 51 +++++++++++++++++++ .../{ => Scheduling}/Schedulable.php | 4 +- .../Scheduling/ScheduleException.php | 16 ++++++ .../{ => Scheduling}/ScheduledCommand.php | 2 +- .../ScheduledCommandInterface.php | 14 +++-- .../Dispatcher/Services/CommandService.php | 20 +++++--- .../Dispatcher/Services/ScheduleService.php | 12 +++-- tests/Commands/TestMake.php | 4 +- .../Drivers/Cron/TestCronScheduleService.php | 16 +++++- tests/Drivers/Cron/TestCronScheduler.php | 2 +- tests/{ => Scheduling}/TestSchedulable.php | 8 +-- .../{ => Scheduling}/TestScheduledCommand.php | 4 +- .../Services/TestBackgroundProcessService.php | 2 +- tests/Services/TestCommandService.php | 2 +- tests/Services/TestScheduleService.php | 14 ++--- tests/TestBackgroundProcessRunner.php | 2 +- tests/TestConfigResolver.php | 4 +- tests/TestQueue.php | 29 +++++++++++ tests/TestQueueItem.php | 29 +++++++++++ 26 files changed, 276 insertions(+), 50 deletions(-) create mode 100644 src/Indatus/Dispatcher/Queue.php create mode 100644 src/Indatus/Dispatcher/QueueItem.php rename src/Indatus/Dispatcher/{ => Scheduling}/Schedulable.php (92%) create mode 100644 src/Indatus/Dispatcher/Scheduling/ScheduleException.php rename src/Indatus/Dispatcher/{ => Scheduling}/ScheduledCommand.php (95%) rename src/Indatus/Dispatcher/{ => Scheduling}/ScheduledCommandInterface.php (74%) rename tests/{ => Scheduling}/TestSchedulable.php (76%) rename tests/{ => Scheduling}/TestScheduledCommand.php (89%) create mode 100644 tests/TestQueue.php create mode 100644 tests/TestQueueItem.php diff --git a/README.md b/README.md index 3183806..097d2cc 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ```php -use Indatus\Dispatcher\ScheduledCommand; +use Indatus\Dispatcher\Scheduling\ScheduledCommand; use Indatus\Dispatcher\Schedulable; use Indatus\Dispatcher\Drivers\Cron\Scheduler; @@ -86,13 +86,13 @@ Use `php artisan scheduled:make` to generate a new scheduled command, the same w ### Scheduling Existing Commands -You may either `implement \Indatus\Dispatcher\ScheduledCommandInterface` or follow the below steps. +You may either `implement \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface` or follow the below steps. -1. `extend \Indatus\Dispatcher\ScheduledCommand` +1. `extend \Indatus\Dispatcher\Scheduling\ScheduledCommand` 2. Add use statements to your command. If you're using a custom driver you will use a different `Scheduler` class. ```php -use Indatus\Dispatcher\ScheduledCommand; -use Indatus\Dispatcher\Schedulable; +use Indatus\Dispatcher\Scheduling\ScheduledCommand; +use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Drivers\Cron\Scheduler; ``` 3. Implement schedule(): diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index d39c32e..a9529ec 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -11,6 +11,7 @@ namespace Indatus\Dispatcher; use App; +use Indatus\Dispatcher\Scheduling\ScheduledCommand; use Indatus\Dispatcher\Services\CommandService; class BackgroundProcessRunner diff --git a/src/Indatus/Dispatcher/Commands/Make.php b/src/Indatus/Dispatcher/Commands/Make.php index 1946305..d89aa6f 100644 --- a/src/Indatus/Dispatcher/Commands/Make.php +++ b/src/Indatus/Dispatcher/Commands/Make.php @@ -53,8 +53,8 @@ protected function writeCommand($file, $stub) { protected function extendStub($stub) { $replacements = array( - 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\ScheduledCommand;\n". - "use Indatus\\Dispatcher\\Schedulable;\n". + 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\Scheduling\\ScheduledCommand;\n". + "use Indatus\\Dispatcher\\Scheduling\\Schedulable;\n". "use Indatus\\Dispatcher\\Drivers\\".ucwords(Config::get('dispatcher::driver'))."\\Scheduler", 'extends Command {' => 'extends ScheduledCommand {', 'parent::__construct();' => $this->getStub() diff --git a/src/Indatus/Dispatcher/ConfigResolver.php b/src/Indatus/Dispatcher/ConfigResolver.php index f0b84fa..1423235 100644 --- a/src/Indatus/Dispatcher/ConfigResolver.php +++ b/src/Indatus/Dispatcher/ConfigResolver.php @@ -1,4 +1,4 @@ -getName().'" is not an instance of Schedulable'); + } + $cron = CronExpression::factory($schedule->getSchedule()); if ($cron->isDue()) { return true; @@ -44,9 +61,9 @@ public function isDue(ScheduledCommandInterface $command) public function printSummary() { $this->table->setHeaders(array('Environment(s)', 'Name', 'Minute', 'Hour', 'Day of Month', 'Month', 'Day of Week', 'Run as')); - /** @var $command \Indatus\Dispatcher\ScheduledCommandInterface */ + /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ foreach ($this->getScheduledCommands() as $command) { - /** @var $command \Indatus\Dispatcher\ScheduledCommandInterface */ + /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Schedulable')); $this->table->addRow(array( diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index d0de659..ac707c2 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -10,7 +10,7 @@ */ namespace Indatus\Dispatcher\Drivers\Cron; -use Indatus\Dispatcher\Schedulable; +use Indatus\Dispatcher\Scheduling\Schedulable; class Scheduler extends Schedulable { diff --git a/src/Indatus/Dispatcher/Queue.php b/src/Indatus/Dispatcher/Queue.php new file mode 100644 index 0000000..d7d1785 --- /dev/null +++ b/src/Indatus/Dispatcher/Queue.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +class Queue +{ + /** @var QueueItem[] */ + protected static $queue = array(); + + /** + * Add an item to the queue + * @param QueueItem $item + */ + public function add(QueueItem $item) + { + self::$queue[] = $item; + } + + /** + * The size of the queue + * @return int + */ + public function size() + { + return count(self::$queue); + } + + /** + * Get all items in the queue + * @return QueueItem[] + */ + public function flush() + { + $queue = self::$queue; + self::$queue = array(); + + return $queue; + } +} diff --git a/src/Indatus/Dispatcher/QueueItem.php b/src/Indatus/Dispatcher/QueueItem.php new file mode 100644 index 0000000..ed69b29 --- /dev/null +++ b/src/Indatus/Dispatcher/QueueItem.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +class QueueItem +{ + /** @var \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ + protected $command; + + /** @var \Indatus\Dispatcher\Scheduling\Schedulable */ + protected $scheduler; + + /** + * @return \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface + */ + public function getCommand() + { + return $this->command; + } + + /** + * @param \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface $command + */ + public function setCommand($command) + { + $this->command = $command; + } + + /** + * @return \Indatus\Dispatcher\Scheduling\Schedulable + */ + public function getScheduler() + { + return $this->scheduler; + } + + /** + * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler + */ + public function setScheduler($scheduler) + { + $this->scheduler = $scheduler; + } +} diff --git a/src/Indatus/Dispatcher/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php similarity index 92% rename from src/Indatus/Dispatcher/Schedulable.php rename to src/Indatus/Dispatcher/Scheduling/Schedulable.php index d8affb1..f907fc7 100644 --- a/src/Indatus/Dispatcher/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -8,7 +8,9 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Indatus\Dispatcher; +namespace Indatus\Dispatcher\Scheduling; + +use Indatus\Dispatcher\ConfigResolver; abstract class Schedulable { diff --git a/src/Indatus/Dispatcher/Scheduling/ScheduleException.php b/src/Indatus/Dispatcher/Scheduling/ScheduleException.php new file mode 100644 index 0000000..2d2a737 --- /dev/null +++ b/src/Indatus/Dispatcher/Scheduling/ScheduleException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Indatus\Dispatcher\Scheduling; + +class ScheduleException extends \Exception +{ + +} \ No newline at end of file diff --git a/src/Indatus/Dispatcher/ScheduledCommand.php b/src/Indatus/Dispatcher/Scheduling/ScheduledCommand.php similarity index 95% rename from src/Indatus/Dispatcher/ScheduledCommand.php rename to src/Indatus/Dispatcher/Scheduling/ScheduledCommand.php index 03fc718..9a5a632 100644 --- a/src/Indatus/Dispatcher/ScheduledCommand.php +++ b/src/Indatus/Dispatcher/Scheduling/ScheduledCommand.php @@ -8,7 +8,7 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Indatus\Dispatcher; +namespace Indatus\Dispatcher\Scheduling; use App; use Illuminate\Console\Command; diff --git a/src/Indatus/Dispatcher/ScheduledCommandInterface.php b/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php similarity index 74% rename from src/Indatus/Dispatcher/ScheduledCommandInterface.php rename to src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php index 7d0452f..cc56fdf 100644 --- a/src/Indatus/Dispatcher/ScheduledCommandInterface.php +++ b/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php @@ -2,10 +2,19 @@ /** * @author Ben Kuhl */ -namespace Indatus\Dispatcher; +namespace Indatus\Dispatcher\Scheduling; + +use Indatus\Dispatcher\Scheduler; +use Indatus\Dispatcher\Scheduling\Schedulable; interface ScheduledCommandInterface { + /** + * Get the name of the command + * @return string + */ + public function getName(); + /** * User to run the command as * @return string Defaults to false to run as default user @@ -14,9 +23,8 @@ public function user(); /** * When a command should run - * * @param Scheduler $scheduler - * @return \Indatus\Dispatcher\Schedulable + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ public function schedule(Schedulable $scheduler); diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 44cc9d6..7f299ce 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -11,7 +11,7 @@ namespace Indatus\Dispatcher\Services; use App; -use Indatus\Dispatcher\ScheduledCommand; +use Indatus\Dispatcher\Scheduling\ScheduledCommand; class CommandService { @@ -41,9 +41,13 @@ public function runDue() /** * Determine if a scheduled command is in the correct environment - * - * @param \Indatus\Dispatcher\ScheduledCommand $command - * @return bool + + +* +*@param \Indatus\Dispatcher\Scheduling\ScheduledCommand $command + +* +*@return bool */ public function runnableInEnvironment(ScheduledCommand $command) { @@ -63,8 +67,12 @@ public function runnableInEnvironment(ScheduledCommand $command) /** * Get a command to run this application - * @param ScheduledCommand $scheduledCommand - * @return string + +* + * @param \Indatus\Dispatcher\Scheduling\ScheduledCommand $scheduledCommand + +* +*@return string */ public function getRunCommand(ScheduledCommand $scheduledCommand) { diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 5d6ea09..4c9eed0 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -12,7 +12,7 @@ use App; use Artisan; -use Indatus\Dispatcher\ScheduledCommandInterface; +use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; use Indatus\Dispatcher\Table; abstract class ScheduleService @@ -28,8 +28,12 @@ public function __construct(Table $table) /** * Determine if a command is due to be run - * @param ScheduledCommandInterface $command - * @return bool + +* +*@param \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface $command + +* +*@return bool */ abstract public function isDue(ScheduledCommandInterface $command); @@ -53,7 +57,7 @@ public function getScheduledCommands() /** * Get all commands that are due to be run * - * @return \Indatus\Dispatcher\ScheduledCommand[] + * @return \Indatus\Dispatcher\Scheduling\ScheduledCommand[] */ public function getDueCommands() { diff --git a/tests/Commands/TestMake.php b/tests/Commands/TestMake.php index b0eba99..aecbf10 100644 --- a/tests/Commands/TestMake.php +++ b/tests/Commands/TestMake.php @@ -63,8 +63,8 @@ public function testExtendStub() $stubContents = file_get_contents($this->getStubPath('command.stub')); $replacements = array( - 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\ScheduledCommand;\n". - "use Indatus\\Dispatcher\\Schedulable;\n". + 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\Scheduling\\ScheduledCommand;\n". + "use Indatus\\Dispatcher\\Scheduling\\Schedulable;\n". "use Indatus\\Dispatcher\\Drivers\\".ucwords(Config::get('dispatcher::driver'))."\\Scheduler", 'extends Command {' => 'extends ScheduledCommand {', 'parent::__construct();' => $stubContents diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index b13ecd5..ab7cfa8 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -3,6 +3,7 @@ * @author Ben Kuhl */ +use \Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Mockery as m; class TestCronScheduleService extends TestCase @@ -18,6 +19,19 @@ public function tearDown() m::close(); } + /** + * @expectedException \Indatus\Dispatcher\Scheduling\ScheduleException + */ + public function testIsDueException() + { + $scheduleService = new ScheduleService(m::mock('Indatus\Dispatcher\Table')); + + $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); + $command->shouldReceive('schedule')->once()->andReturnNull(); + $command->shouldReceive('getName')->once()->andReturn('testCommand'); + $scheduleService->isDue($command); + } + /** * Test that a summary is properly generated * Dangit this is ugly... gotta find a new cli library @@ -29,7 +43,7 @@ public function testPrintSummary() $m->shouldReceive('sort')->once(); $m->shouldReceive('display')->once(); }); - $scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) use ($table) { + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { $table->shouldReceive('addRow')->once(); $m->shouldReceive('getName')->once(); diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index c3ed99f..4c2fb62 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -12,7 +12,7 @@ class TestCronScheduler extends TestCase */ private $scheduler; - private $schedularClass = 'Indatus\Dispatcher\Schedulable'; + private $schedularClass = 'Indatus\Dispatcher\Scheduling\Schedulable'; public function setUp() { diff --git a/tests/TestSchedulable.php b/tests/Scheduling/TestSchedulable.php similarity index 76% rename from tests/TestSchedulable.php rename to tests/Scheduling/TestSchedulable.php index aa48624..cf8b506 100644 --- a/tests/TestSchedulable.php +++ b/tests/Scheduling/TestSchedulable.php @@ -18,9 +18,9 @@ public function tearDown() public function testArguments() { $args = ['type' => 'scheduled']; - /** @var \Indatus\Dispatcher\Schedulable $scheduleable */ + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduleable */ $scheduleable = $this->getMockForAbstractClass( - 'Indatus\Dispatcher\Schedulable', array( + 'Indatus\Dispatcher\Scheduling\Schedulable', array( App::make('Indatus\Dispatcher\ConfigResolver') )); $newScheduleable = $scheduleable->args($args); @@ -31,9 +31,9 @@ public function testArgumentsConstructor() { $args = ['type' => 'scheduled']; - /** @var \Indatus\Dispatcher\Schedulable $scheduleable */ + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduleable */ $scheduleable = $this->getMockForAbstractClass( - 'Indatus\Dispatcher\Schedulable', array( + 'Indatus\Dispatcher\Scheduling\Schedulable', array( App::make('Indatus\Dispatcher\ConfigResolver'), $args ) diff --git a/tests/TestScheduledCommand.php b/tests/Scheduling/TestScheduledCommand.php similarity index 89% rename from tests/TestScheduledCommand.php rename to tests/Scheduling/TestScheduledCommand.php index 9f5bb34..e94d008 100644 --- a/tests/TestScheduledCommand.php +++ b/tests/Scheduling/TestScheduledCommand.php @@ -9,7 +9,7 @@ class TestScheduledCommand extends TestCase { /** - * @var Indatus\Dispatcher\ScheduledCommand + * @var \Indatus\Dispatcher\Scheduling\ScheduledCommand */ private $scheduledCommand; @@ -17,7 +17,7 @@ public function setUp() { parent::setUp(); - $this->scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand[schedule]'); + $this->scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand[schedule]'); $this->app->instance( 'Indatus\Dispatcher\Schedulable', diff --git a/tests/Services/TestBackgroundProcessService.php b/tests/Services/TestBackgroundProcessService.php index 47cbc73..4f31b7a 100644 --- a/tests/Services/TestBackgroundProcessService.php +++ b/tests/Services/TestBackgroundProcessService.php @@ -109,7 +109,7 @@ public function testGetRunCommandAsUser() private function mockCommand ($environment = '*') { - return $class = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) use ($environment) { + return $class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($environment) { $m->shouldReceive('environment')->andReturn($environment); }); } diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index 2b9fa02..2b00796 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -117,7 +117,7 @@ public function testGetRunCommandAsUser() private function mockCommand ($environment = '*') { - return $class = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) use ($environment) { + return $class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($environment) { $m->shouldReceive('environment')->andReturn($environment); }); } diff --git a/tests/Services/TestScheduleService.php b/tests/Services/TestScheduleService.php index 1a85f79..dbeffda 100644 --- a/tests/Services/TestScheduleService.php +++ b/tests/Services/TestScheduleService.php @@ -30,7 +30,7 @@ public function tearDown() public function testGetScheduledCommands() { - $scheduledCommands = array($class = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) { + $scheduledCommands = array($class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Schedulable')); })); @@ -45,7 +45,7 @@ public function testGetDueCommands() new Table() ), function ($m) { $m->shouldReceive('getScheduledCommands')->once() - ->andReturn(array(m::mock('Indatus\Dispatcher\ScheduledCommand'))); + ->andReturn(array(m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'))); $m->shouldReceive('isDue')->once()->andReturn(true); }); @@ -55,23 +55,25 @@ public function testGetDueCommands() public function testIsNotDue() { - $scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduler', function ($m) { + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { + $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { //schedule the cron to run yesterday $dateTime = new DateTime('yesterday'); $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); })); }); + $scheduledCommand->shouldReceive('getName'); $this->assertFalse($this->scheduleService->isDue($scheduledCommand)); } public function testIsDue() { - $scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduler', function ($m) { + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { + $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { $m->shouldReceive('getSchedule')->once()->andReturn('* * * * *'); })); }); + $scheduledCommand->shouldReceive('getName'); $this->assertTrue($this->scheduleService->isDue($scheduledCommand)); } diff --git a/tests/TestBackgroundProcessRunner.php b/tests/TestBackgroundProcessRunner.php index 32f49c0..c8696f6 100644 --- a/tests/TestBackgroundProcessRunner.php +++ b/tests/TestBackgroundProcessRunner.php @@ -25,7 +25,7 @@ public function testRun() $commandService = m::mock('Indatus\Dispatcher\Services\CommandService', function ($m) { $m->shouldReceive('getRunCommand')->once()->andReturn('echo "this is a test"'); }); - $scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand'); + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); $backgroundProcessRunner = new BackgroundProcessRunner($commandService); $this->assertTrue($backgroundProcessRunner->run($scheduledCommand)); diff --git a/tests/TestConfigResolver.php b/tests/TestConfigResolver.php index e4909a5..50dd8c6 100644 --- a/tests/TestConfigResolver.php +++ b/tests/TestConfigResolver.php @@ -30,7 +30,7 @@ public function testLoadingPackagedDriverWithArguments() $args = array('testArgument'); $resolver = new ConfigResolver(); - /** @var \Indatus\Dispatcher\Schedulable $scheduler */ + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ $scheduler = $resolver->resolveDriverClass('Scheduler', $args); $this->assertEquals( $args, @@ -43,7 +43,7 @@ public function testLoadingCustomDriver() Config::shouldReceive('get')->andReturn('Indatus\Dispatcher\Drivers\Cron'); $resolver = new ConfigResolver(); $this->assertInstanceOf( - 'Indatus\Dispatcher\Schedulable', + 'Indatus\Dispatcher\Scheduling\Schedulable', $resolver->resolveDriverClass('Scheduler') ); } diff --git a/tests/TestQueue.php b/tests/TestQueue.php new file mode 100644 index 0000000..7b1e814 --- /dev/null +++ b/tests/TestQueue.php @@ -0,0 +1,29 @@ + + */ + +use Mockery as m; +use Indatus\Dispatcher\Queue; + +class TestQueue extends TestCase +{ + + public function tearDown() + { + parent::tearDown(); + m::close(); + } + + public function testQueue() + { + $item = m::mock('Indatus\Dispatcher\QueueItem'); + + $queue = new Indatus\Dispatcher\Queue(); + $this->assertEquals(0, $queue->size()); + $queue->add($item); + $this->assertEquals(1, $queue->size()); + $this->assertEquals([$item], $queue->flush()); + $this->assertEquals(0, $queue->size()); + } +} \ No newline at end of file diff --git a/tests/TestQueueItem.php b/tests/TestQueueItem.php new file mode 100644 index 0000000..2782adc --- /dev/null +++ b/tests/TestQueueItem.php @@ -0,0 +1,29 @@ + + */ + +use Mockery as m; +use Indatus\Dispatcher\QueueItem; + +class TestQueueItem extends TestCase +{ + + public function tearDown() + { + parent::tearDown(); + m::close(); + } + + public function testQueue() + { + $command = m::mock('Indatus\Dispatcher\Scheduling\Command'); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable'); + + $queueItem = new QueueItem(); + $queueItem->setCommand($command); + $this->assertEquals($command, $queueItem->getCommand()); + $queueItem->setScheduler($scheduler); + $this->assertEquals($scheduler, $queueItem->getScheduler()); + } +} \ No newline at end of file From ee27df44b9a8ab07a2aa7be773a1a0ac39fd4a21 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Thu, 3 Apr 2014 22:12:31 -0400 Subject: [PATCH 04/25] Adjusted namespacing/comments --- .../Dispatcher/BackgroundProcessRunner.php | 5 ++--- src/Indatus/Dispatcher/Commands/Make.php | 4 +--- src/Indatus/Dispatcher/Commands/Run.php | 4 +--- .../Dispatcher/Commands/ScheduleSummary.php | 3 +-- src/Indatus/Dispatcher/ConfigResolver.php | 2 +- .../Drivers/Cron/ScheduleService.php | 18 ++++----------- .../Dispatcher/Drivers/Cron/Scheduler.php | 3 +-- src/Indatus/Dispatcher/Platform.php | 6 ++--- .../Dispatcher/Scheduling/Schedulable.php | 3 +-- .../Scheduling/ScheduleException.php | 5 ++--- .../Scheduling/ScheduledCommand.php | 4 +--- .../Scheduling/ScheduledCommandInterface.php | 6 ++--- src/Indatus/Dispatcher/ServiceProvider.php | 5 ++--- .../Services/BackgroundProcessService.php | 5 ++--- .../Dispatcher/Services/CommandService.php | 22 +++++++------------ .../Dispatcher/Services/ScheduleService.php | 13 +++++------ src/Indatus/Dispatcher/Table.php | 5 ++--- src/Indatus/Dispatcher/TableInterface.php | 12 +++------- 18 files changed, 42 insertions(+), 83 deletions(-) diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index a9529ec..ac9996a 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -1,4 +1,4 @@ - - * @package Indatus\Dispatcher\Commands */ class Make extends CommandMakeCommand { diff --git a/src/Indatus/Dispatcher/Commands/Run.php b/src/Indatus/Dispatcher/Commands/Run.php index b679b67..800a1b9 100644 --- a/src/Indatus/Dispatcher/Commands/Run.php +++ b/src/Indatus/Dispatcher/Commands/Run.php @@ -1,4 +1,4 @@ - - * @package Indatus\Dispatcher\Commands */ class Run extends Command { diff --git a/src/Indatus/Dispatcher/Commands/ScheduleSummary.php b/src/Indatus/Dispatcher/Commands/ScheduleSummary.php index 76fafaa..f1d085b 100644 --- a/src/Indatus/Dispatcher/Commands/ScheduleSummary.php +++ b/src/Indatus/Dispatcher/Commands/ScheduleSummary.php @@ -1,4 +1,4 @@ - */ -namespace Indatus\Dispatcher\Scheduling; use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\Scheduling\Schedulable; @@ -42,4 +42,4 @@ public function environment(); * @return Boolean */ public function isEnabled(); -} \ No newline at end of file +} diff --git a/src/Indatus/Dispatcher/ServiceProvider.php b/src/Indatus/Dispatcher/ServiceProvider.php index b8a8e0c..01a132e 100644 --- a/src/Indatus/Dispatcher/ServiceProvider.php +++ b/src/Indatus/Dispatcher/ServiceProvider.php @@ -1,4 +1,4 @@ -commands('command.scheduled.run'); } -} \ No newline at end of file +} diff --git a/src/Indatus/Dispatcher/Services/BackgroundProcessService.php b/src/Indatus/Dispatcher/Services/BackgroundProcessService.php index ab0890a..53ce1a4 100644 --- a/src/Indatus/Dispatcher/Services/BackgroundProcessService.php +++ b/src/Indatus/Dispatcher/Services/BackgroundProcessService.php @@ -1,4 +1,4 @@ - - * @package Indatus\Dispatcher */ interface TableInterface { @@ -68,10 +65,7 @@ public function resetTable(); /** * Sets the renderer used by this table. * - * @param table\Renderer $renderer The renderer to use for output. - * @see table\Renderer - * @see table\Ascii - * @see table\Tabular + * @param \cli\table\Renderer $renderer The renderer to use for output. */ public function setRenderer(Renderer $renderer); @@ -81,4 +75,4 @@ public function setRenderer(Renderer $renderer); * @param int $column The index of the column to sort by. */ public function sort($column); -} \ No newline at end of file +} From 527b6d74ac7ffc1ed53f99bdaf2049cbcb13ac60 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Thu, 3 Apr 2014 22:53:33 -0400 Subject: [PATCH 05/25] Commands are now queued with their arguments to be run --- README.md | 6 +- .../Dispatcher/Commands/stubs/command.stub | 2 +- .../Drivers/Cron/ScheduleService.php | 12 +++- .../Dispatcher/Scheduling/Schedulable.php | 2 +- src/Indatus/Dispatcher/ServiceProvider.php | 2 +- .../Dispatcher/Services/ScheduleService.php | 7 ++- .../Drivers/Cron/TestCronScheduleService.php | 61 +++++++++++++++++-- tests/Scheduling/TestScheduledCommand.php | 2 +- .../Services/TestBackgroundProcessService.php | 3 +- tests/Services/TestCommandService.php | 3 +- tests/Services/TestScheduleService.php | 34 ++--------- tests/TestConfig.php | 2 +- 12 files changed, 91 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 097d2cc..5fcfde6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ```php use Indatus\Dispatcher\Scheduling\ScheduledCommand; -use Indatus\Dispatcher\Schedulable; +use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Drivers\Cron\Scheduler; class MyCommand extends ScheduledCommand { @@ -101,7 +101,7 @@ use Indatus\Dispatcher\Drivers\Cron\Scheduler; * When a command should run * * @param Scheduler $scheduler - * @return \Indatus\Dispatcher\Schedulable + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ public function schedule(Schedulable $scheduler) { @@ -192,7 +192,7 @@ You may also schedule commands via raw Cron expressions You can build your own drivers or extend a driver that's included. Create a packagepath such as `\MyApp\ScheduleDriver\` and create two classes: - * `Scheduler` that `implements Indatus\Dispatcher\Schedulable`. This class should provide a useful interface for programmers to schedule their commands. + * `Scheduler` that `implements Indatus\Dispatcher\Scheduling\Schedulable`. This class should provide a useful interface for programmers to schedule their commands. * `ScheduleService` that `extends \Indatus\Dispatcher\Services\ScheduleService`. This class contains logic on how to determine if a command is due to run. Publish the configs using `php artisan view:publish indatus/dispatcher`. Then update your driver configuration to reference the package in which these 2 classes are included (do not include a trailing slash): diff --git a/src/Indatus/Dispatcher/Commands/stubs/command.stub b/src/Indatus/Dispatcher/Commands/stubs/command.stub index 8f5989b..c63c614 100644 --- a/src/Indatus/Dispatcher/Commands/stubs/command.stub +++ b/src/Indatus/Dispatcher/Commands/stubs/command.stub @@ -5,7 +5,7 @@ parent::__construct(); * When a command should run * * @param Scheduler $scheduler - * @return \Indatus\Dispatcher\Schedulable + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ public function schedule(Schedulable $scheduler) { diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index f9a2c4f..6ccbff7 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -26,7 +26,7 @@ class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { */ public function isDue(ScheduledCommandInterface $command) { - $scheduler = App::make('Indatus\Dispatcher\Schedulable'); + $scheduler = App::make('Indatus\Dispatcher\Scheduling\Schedulable'); $schedules = $command->schedule($scheduler); if (!is_array($schedules)) { $schedules = array($schedules); @@ -38,6 +38,14 @@ public function isDue(ScheduledCommandInterface $command) $cron = CronExpression::factory($schedule->getSchedule()); if ($cron->isDue()) { + + //add to the queue so we can run it later + /** @var \Indatus\Dispatcher\QueueItem $queueItem */ + $queueItem = App::make('Indatus\Dispatcher\QueueItem'); + $queueItem->setCommand($command); + $queueItem->setScheduler($scheduler); + $this->queue->add($queueItem); + return true; } } @@ -54,7 +62,7 @@ public function printSummary() /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ foreach ($this->getScheduledCommands() as $command) { /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ - $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Schedulable')); + $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Scheduling\Schedulable')); $this->table->addRow(array( is_array($command->environment()) ? implode(',', $command->environment()) : $command->environment(), diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index e1f3058..d11cacb 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -28,7 +28,7 @@ public function __construct(ConfigResolver $configResolver, $arguments = array() * * @param array $arguments * - * @return \Indatus\Dispatcher\Schedulable + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ public function args(array $arguments) { diff --git a/src/Indatus/Dispatcher/ServiceProvider.php b/src/Indatus/Dispatcher/ServiceProvider.php index 01a132e..af65395 100644 --- a/src/Indatus/Dispatcher/ServiceProvider.php +++ b/src/Indatus/Dispatcher/ServiceProvider.php @@ -43,7 +43,7 @@ public function register() $resolver = App::make('\Indatus\Dispatcher\ConfigResolver'); //load the scheduler of the appropriate driver - App::bind('Indatus\Dispatcher\Schedulable', function () use ($resolver) { + App::bind('Indatus\Dispatcher\Scheduling\Schedulable', function () use ($resolver) { return $resolver->resolveDriverClass('Scheduler'); }); diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 5c8b9d9..548862a 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -11,6 +11,7 @@ use App; use Artisan; +use Indatus\Dispatcher\Queue; use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; use Indatus\Dispatcher\Table; @@ -20,9 +21,13 @@ abstract class ScheduleService /** @var \Indatus\Dispatcher\Table */ protected $table; - public function __construct(Table $table) + /** @var \Indatus\Dispatcher\Queue */ + protected $queue; + + public function __construct(Table $table, Queue $queue) { $this->table = $table; + $this->queue = $queue; } /** diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index ab7cfa8..a247fa1 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -8,9 +8,18 @@ class TestCronScheduleService extends TestCase { + /** + * @var Indatus\Dispatcher\ScheduleService + */ + private $scheduleService; + public function setUp() { parent::setUp(); + + $table = m::mock('Indatus\Dispatcher\Table'); + $queue = m::mock('Indatus\Dispatcher\Queue'); + $this->scheduleService = new ScheduleService($table, $queue); } public function tearDown() @@ -24,12 +33,50 @@ public function tearDown() */ public function testIsDueException() { - $scheduleService = new ScheduleService(m::mock('Indatus\Dispatcher\Table')); - $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); $command->shouldReceive('schedule')->once()->andReturnNull(); $command->shouldReceive('getName')->once()->andReturn('testCommand'); - $scheduleService->isDue($command); + $this->scheduleService->isDue($command); + } + + public function testIsNotDue() + { + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { + $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { + //schedule the cron to run yesterday + $dateTime = new DateTime('yesterday'); + $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); + })); + }); + $scheduledCommand->shouldReceive('getName'); + $this->assertFalse($this->scheduleService->isDue($scheduledCommand)); + } + + public function testIsDue() + { + $scheduler = m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { + $m->shouldReceive('getSchedule')->once()->andReturn('* * * * *'); + }); + App::shouldReceive('make')->with('Indatus\Dispatcher\Scheduling\Schedulable') + ->andReturn($scheduler); + + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($scheduler) { + $m->shouldReceive('schedule')->andReturn($scheduler); + }); + $scheduledCommand->shouldReceive('getName'); + + $queueItem = m::mock('Indatus\Dispatcher\QueueItem'); + $queueItem->shouldReceive('setCommand')->with($scheduledCommand)->once(); + $queueItem->shouldReceive('setScheduler')->with($scheduler)->once(); + App::shouldReceive('make')->with('Indatus\Dispatcher\QueueItem') + ->andReturn($queueItem); + + $table = m::mock('Indatus\Dispatcher\Table'); + $queue = m::mock('Indatus\Dispatcher\Queue'); + $queue->shouldReceive('add')->with($queueItem)->once(); + $scheduleService = new ScheduleService($table, $queue); + + $this->assertTrue($scheduleService->isDue($scheduledCommand)); } /** @@ -43,6 +90,11 @@ public function testPrintSummary() $m->shouldReceive('sort')->once(); $m->shouldReceive('display')->once(); }); + $queue = m::mock('Indatus\Dispatcher\Queue', function ($m) { + /*$m->shouldReceive('setHeaders')->once(); + $m->shouldReceive('sort')->once(); + $m->shouldReceive('display')->once();*/ + }); $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { $table->shouldReceive('addRow')->once(); @@ -58,7 +110,8 @@ public function testPrintSummary() })); }); $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService[getScheduledCommands]', array( - $table + $table, + $queue ), function ($m) use ($scheduledCommand) { $m->shouldReceive('getScheduledCommands')->once()->andReturn(array( $scheduledCommand diff --git a/tests/Scheduling/TestScheduledCommand.php b/tests/Scheduling/TestScheduledCommand.php index e94d008..2d8c5fe 100644 --- a/tests/Scheduling/TestScheduledCommand.php +++ b/tests/Scheduling/TestScheduledCommand.php @@ -20,7 +20,7 @@ public function setUp() $this->scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand[schedule]'); $this->app->instance( - 'Indatus\Dispatcher\Schedulable', + 'Indatus\Dispatcher\Scheduling\Schedulable', new Scheduler(App::make('Indatus\Dispatcher\ConfigResolver')) ); } diff --git a/tests/Services/TestBackgroundProcessService.php b/tests/Services/TestBackgroundProcessService.php index 4f31b7a..1d69132 100644 --- a/tests/Services/TestBackgroundProcessService.php +++ b/tests/Services/TestBackgroundProcessService.php @@ -8,6 +8,7 @@ use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Indatus\Dispatcher\Table; use Indatus\Dispatcher\Scheduler; +use Indatus\Dispatcher\Queue; class BackgroundProcessService extends TestCase { @@ -20,7 +21,7 @@ public function setUp() { parent::setUp(); - $scheduleService = new ScheduleService(new Table()); + $scheduleService = new ScheduleService(new Table(), new Queue()); $this->commandService = new CommandService($scheduleService); } diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index 2b00796..4606fe6 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -8,6 +8,7 @@ use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Indatus\Dispatcher\Table; use Indatus\Dispatcher\Scheduler; +use Indatus\Dispatcher\Queue; class TestCommandService extends TestCase { @@ -20,7 +21,7 @@ public function setUp() { parent::setUp(); - $scheduleService = new ScheduleService(new Table()); + $scheduleService = new ScheduleService(new Table(), new Queue()); $this->commandService = new CommandService($scheduleService); } diff --git a/tests/Services/TestScheduleService.php b/tests/Services/TestScheduleService.php index dbeffda..2d583b5 100644 --- a/tests/Services/TestScheduleService.php +++ b/tests/Services/TestScheduleService.php @@ -7,6 +7,7 @@ use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\Table; +use Indatus\Dispatcher\Queue; class TestScheduleService extends TestCase { @@ -19,7 +20,7 @@ public function setUp() { parent::setUp(); - $this->scheduleService = new ScheduleService(new Table()); + $this->scheduleService = new ScheduleService(new Table(), new Queue()); } public function tearDown() @@ -31,7 +32,7 @@ public function tearDown() public function testGetScheduledCommands() { $scheduledCommands = array($class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Schedulable')); + $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable')); })); Artisan::shouldReceive('all')->once()->andReturn($scheduledCommands); @@ -41,8 +42,9 @@ public function testGetScheduledCommands() public function testGetDueCommands() { - $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService[getScheduledCommands,isDue]', array( - new Table() + $scheduleService = m::mock('Indatus\Dispatcher\Services\ScheduleService[getScheduledCommands,isDue]', array( + new Table(), + new Queue() ), function ($m) { $m->shouldReceive('getScheduledCommands')->once() ->andReturn(array(m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'))); @@ -53,28 +55,4 @@ public function testGetDueCommands() $this->assertEquals(1, count($scheduleService->getDueCommands())); } - public function testIsNotDue() - { - $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { - //schedule the cron to run yesterday - $dateTime = new DateTime('yesterday'); - $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); - })); - }); - $scheduledCommand->shouldReceive('getName'); - $this->assertFalse($this->scheduleService->isDue($scheduledCommand)); - } - - public function testIsDue() - { - $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { - $m->shouldReceive('getSchedule')->once()->andReturn('* * * * *'); - })); - }); - $scheduledCommand->shouldReceive('getName'); - $this->assertTrue($this->scheduleService->isDue($scheduledCommand)); - } - } \ No newline at end of file diff --git a/tests/TestConfig.php b/tests/TestConfig.php index 68f9108..c4955a3 100644 --- a/tests/TestConfig.php +++ b/tests/TestConfig.php @@ -22,7 +22,7 @@ public function testDefaultDriver() public function testDefaultSchedulerClass() { - $serviceProvider = App::make('Indatus\Dispatcher\Schedulable'); + $serviceProvider = App::make('Indatus\Dispatcher\Scheduling\Schedulable'); $this->assertInstanceOf('Indatus\Dispatcher\Drivers\Cron\Scheduler', $serviceProvider); } From b44b2934a57873fd529c6384290e5a3d80973e2d Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Mon, 7 Apr 2014 09:14:22 -0400 Subject: [PATCH 06/25] Commands can now be run and scheduled with arguments --- .../Dispatcher/BackgroundProcessRunner.php | 8 +- .../Drivers/Cron/ScheduleService.php | 37 +----- src/Indatus/Dispatcher/Queue.php | 10 +- .../Dispatcher/Scheduling/Schedulable.php | 2 + .../Scheduling/ScheduleException.php | 15 --- .../Dispatcher/Services/CommandService.php | 60 ++++++++- .../Dispatcher/Services/ScheduleService.php | 54 +++++--- .../Drivers/Cron/TestCronScheduleService.php | 52 ++------ .../Services/TestBackgroundProcessService.php | 118 ------------------ tests/Services/TestCommandService.php | 92 +++++++++++++- tests/Services/TestScheduleService.php | 48 +++++-- 11 files changed, 250 insertions(+), 246 deletions(-) delete mode 100644 src/Indatus/Dispatcher/Scheduling/ScheduleException.php delete mode 100644 tests/Services/TestBackgroundProcessService.php diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index ac9996a..a45f861 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -12,6 +12,7 @@ use App; use Indatus\Dispatcher\Scheduling\ScheduledCommand; use Indatus\Dispatcher\Services\CommandService; +use Symfony\Component\Process\Process; class BackgroundProcessRunner { @@ -29,12 +30,13 @@ public function __construct(CommandService $commandService) /** * Run a scheduled command * - * @param ScheduledCommand $scheduledCommand + * @param ScheduledCommand $scheduledCommand + * @param array $arguments * @return bool */ - public function run(ScheduledCommand $scheduledCommand) + public function run(ScheduledCommand $scheduledCommand, array $arguments = array()) { - exec($this->commandService->getRunCommand($scheduledCommand)); + exec($this->commandService->getRunCommand($scheduledCommand), $arguments); return true; } diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index 6ccbff7..86e709e 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -11,46 +11,21 @@ use App; use Cron\CronExpression; -use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; -use Indatus\Dispatcher\Scheduling\ScheduleException; use Indatus\Dispatcher\Scheduling\Schedulable; class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { /** - * Determine if a command is due to be run + * Determine if a schedule is due to be run + * + * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler * - * @param \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface $command - * @throws \Indatus\Dispatcher\Scheduling\ScheduleException * @return bool */ - public function isDue(ScheduledCommandInterface $command) + public function isDue(Schedulable $scheduler) { - $scheduler = App::make('Indatus\Dispatcher\Scheduling\Schedulable'); - $schedules = $command->schedule($scheduler); - if (!is_array($schedules)) { - $schedules = array($schedules); - } - foreach ($schedules as $schedule) { - if (($schedule instanceOf Schedulable) === false) { - throw new ScheduleException('Schedule for "'.$command->getName().'" is not an instance of Schedulable'); - } - - $cron = CronExpression::factory($schedule->getSchedule()); - if ($cron->isDue()) { - - //add to the queue so we can run it later - /** @var \Indatus\Dispatcher\QueueItem $queueItem */ - $queueItem = App::make('Indatus\Dispatcher\QueueItem'); - $queueItem->setCommand($command); - $queueItem->setScheduler($scheduler); - $this->queue->add($queueItem); - - return true; - } - } - - return false; + $cron = CronExpression::factory($scheduler->getSchedule()); + return $cron->isDue(); } /** diff --git a/src/Indatus/Dispatcher/Queue.php b/src/Indatus/Dispatcher/Queue.php index d7d1785..9760969 100644 --- a/src/Indatus/Dispatcher/Queue.php +++ b/src/Indatus/Dispatcher/Queue.php @@ -12,7 +12,7 @@ class Queue { /** @var QueueItem[] */ - protected static $queue = array(); + protected $queue = array(); /** * Add an item to the queue @@ -20,7 +20,7 @@ class Queue */ public function add(QueueItem $item) { - self::$queue[] = $item; + $this->queue[] = $item; } /** @@ -29,7 +29,7 @@ public function add(QueueItem $item) */ public function size() { - return count(self::$queue); + return count($this->queue); } /** @@ -38,8 +38,8 @@ public function size() */ public function flush() { - $queue = self::$queue; - self::$queue = array(); + $queue = $this->queue; + $this->queue = array(); return $queue; } diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index d11cacb..4411827 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -9,7 +9,9 @@ * file that was distributed with this source code. */ +use App; use Indatus\Dispatcher\ConfigResolver; +use Symfony\Component\Console\Input\ArgvInput; abstract class Schedulable { diff --git a/src/Indatus/Dispatcher/Scheduling/ScheduleException.php b/src/Indatus/Dispatcher/Scheduling/ScheduleException.php deleted file mode 100644 index efc8894..0000000 --- a/src/Indatus/Dispatcher/Scheduling/ScheduleException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class ScheduleException extends \Exception -{ - -} diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 5fac1c9..258df25 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -10,6 +10,7 @@ */ use App; +use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Scheduling\ScheduledCommand; class CommandService @@ -30,10 +31,16 @@ function __construct(ScheduleService $scheduleService) */ public function runDue() { + /** @var \Indatus\Dispatcher\BackgroundProcessRunner $backgroundProcessRunner */ $backgroundProcessRunner = App::make('Indatus\Dispatcher\BackgroundProcessRunner'); - foreach ($this->scheduleService->getDueCommands() as $command) { + + /** @var \Indatus\Dispatcher\Queue $queue */ + $queue = $this->scheduleService->getQueue(); + foreach ($queue->flush() as $queueItem) { + $command = $queueItem->getCommand(); + $scheduler = $queueItem->getScheduler(); if ($command->isEnabled() && $this->runnableInEnvironment($command)) { - $backgroundProcessRunner->run($command); + $backgroundProcessRunner->run($command, $scheduler->getArguments()); } } } @@ -61,23 +68,64 @@ public function runnableInEnvironment(ScheduledCommand $command) return false; } + /** + * Prepare a command's arguments for command line usage + * + * @param array $arguments + * + * @return string + */ + public function prepareArguments(array $arguments) + { + $argumentPieces = array(); + foreach ($arguments as $arg => $value) { + //if it's an array of options, throw them in there as well + if (is_array($value)) { + foreach ($value as $argArrayValue) { + $argumentPieces[] = '--'.$arg.'="'.addslashes($argArrayValue).'"'; + } + } else { + $argument = null; + + //option exists with no value + if (is_numeric($arg)) { + $argument = $value; + } elseif (!empty($value)) { + $argument = $arg.'="'.addslashes($value).'"'; + } + + if (!is_null($argument)) { + $argumentPieces[] = '--'.$argument; + } + } + } + + return implode(' ', $argumentPieces); + } + /** * Get a command to run this application * * @param \Indatus\Dispatcher\Scheduling\ScheduledCommand $scheduledCommand + * @param array $arguments * * @return string */ - public function getRunCommand(ScheduledCommand $scheduledCommand) + public function getRunCommand(ScheduledCommand $scheduledCommand, array $arguments = array()) { $commandPieces = array( 'php', base_path().'/artisan', - $scheduledCommand->getName(), - '&', //run in background - '> /dev/null 2>&1' //don't show output, errors can be viewed in the Laravel log + $scheduledCommand->getName() ); + if (count($arguments) > 0) { + $commandPieces[] = $this->prepareArguments($arguments); + } + + $commandPieces[] = '&'; //run in background + $commandPieces[] = '> /dev/null 2>&1'; //don't show output, errors can be viewed in the Laravel log + //run the command as a different user if (is_string($scheduledCommand->user())) { array_unshift($commandPieces, 'sudo -u '.$scheduledCommand->user()); diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 548862a..bc1144a 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -11,9 +11,11 @@ use App; use Artisan; -use Indatus\Dispatcher\Queue; +use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; +use Indatus\Dispatcher\Scheduling\ScheduleException; use Indatus\Dispatcher\Table; +use Symfony\Component\Process\Exception\InvalidArgumentException; abstract class ScheduleService { @@ -21,23 +23,19 @@ abstract class ScheduleService /** @var \Indatus\Dispatcher\Table */ protected $table; - /** @var \Indatus\Dispatcher\Queue */ - protected $queue; - - public function __construct(Table $table, Queue $queue) + public function __construct(Table $table) { $this->table = $table; - $this->queue = $queue; } /** * Determine if a command is due to be run * - * @param \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface $command + * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler * * @return bool */ - abstract public function isDue(ScheduledCommandInterface $command); + abstract public function isDue(Schedulable $scheduler); /** * Get all commands that are scheduled @@ -58,18 +56,44 @@ public function getScheduledCommands() /** * Get all commands that are due to be run - * - * @return \Indatus\Dispatcher\Scheduling\ScheduledCommand[] + * @throws \InvalidArgumentException + * @return \Indatus\Dispatcher\Queue */ - public function getDueCommands() + public function getQueue() { - $commands = array(); + /** @var \Indatus\Dispatcher\Queue $queue */ + $queue = App::make('Indatus\Dispatcher\Queue'); + + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $queue */ + $scheduler = App::make('Indatus\Dispatcher\Scheduling\Schedulable'); + foreach ($this->getScheduledCommands() as $command) { - if ($this->isDue($command)) { - $commands[] = $command; + + //could be multiple schedules based on arguments + $schedules = $command->schedule($scheduler); + if (!is_array($schedules)) { + $schedules = array($schedules); + } + + foreach ($schedules as $schedule) { + if (($schedule instanceOf Schedulable) === false) { + throw new \InvalidArgumentException('Schedule for "'.$command->getName().'" is not an instance of Schedulable'); + } + + if ($this->isDue($schedule)) { + + /** @var \Indatus\Dispatcher\QueueItem $queueItem */ + $queueItem = App::make('Indatus\Dispatcher\QueueItem'); + + $queueItem->setCommand($command); + $queueItem->setScheduler($scheduler); + + $queue->add($queueItem); + } } } - return $commands; + + return $queue; } /** diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index a247fa1..e0c94e4 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -18,8 +18,7 @@ public function setUp() parent::setUp(); $table = m::mock('Indatus\Dispatcher\Table'); - $queue = m::mock('Indatus\Dispatcher\Queue'); - $this->scheduleService = new ScheduleService($table, $queue); + $this->scheduleService = new ScheduleService($table); } public function tearDown() @@ -28,55 +27,22 @@ public function tearDown() m::close(); } - /** - * @expectedException \Indatus\Dispatcher\Scheduling\ScheduleException - */ - public function testIsDueException() - { - $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); - $command->shouldReceive('schedule')->once()->andReturnNull(); - $command->shouldReceive('getName')->once()->andReturn('testCommand'); - $this->scheduleService->isDue($command); - } - public function testIsNotDue() { - $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { - //schedule the cron to run yesterday - $dateTime = new DateTime('yesterday'); - $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); - })); - }); - $scheduledCommand->shouldReceive('getName'); - $this->assertFalse($this->scheduleService->isDue($scheduledCommand)); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { + //schedule the cron to run yesterday + $dateTime = new DateTime('yesterday'); + $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); + }); + $this->assertFalse($this->scheduleService->isDue($scheduler)); } public function testIsDue() { - $scheduler = m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { $m->shouldReceive('getSchedule')->once()->andReturn('* * * * *'); }); - App::shouldReceive('make')->with('Indatus\Dispatcher\Scheduling\Schedulable') - ->andReturn($scheduler); - - $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($scheduler) { - $m->shouldReceive('schedule')->andReturn($scheduler); - }); - $scheduledCommand->shouldReceive('getName'); - - $queueItem = m::mock('Indatus\Dispatcher\QueueItem'); - $queueItem->shouldReceive('setCommand')->with($scheduledCommand)->once(); - $queueItem->shouldReceive('setScheduler')->with($scheduler)->once(); - App::shouldReceive('make')->with('Indatus\Dispatcher\QueueItem') - ->andReturn($queueItem); - - $table = m::mock('Indatus\Dispatcher\Table'); - $queue = m::mock('Indatus\Dispatcher\Queue'); - $queue->shouldReceive('add')->with($queueItem)->once(); - $scheduleService = new ScheduleService($table, $queue); - - $this->assertTrue($scheduleService->isDue($scheduledCommand)); + $this->assertTrue($this->scheduleService->isDue($scheduler)); } /** diff --git a/tests/Services/TestBackgroundProcessService.php b/tests/Services/TestBackgroundProcessService.php deleted file mode 100644 index 1d69132..0000000 --- a/tests/Services/TestBackgroundProcessService.php +++ /dev/null @@ -1,118 +0,0 @@ - - */ - -use Mockery as m; -use Indatus\Dispatcher\Services\CommandService; -use Indatus\Dispatcher\Drivers\Cron\ScheduleService; -use Indatus\Dispatcher\Table; -use Indatus\Dispatcher\Scheduler; -use Indatus\Dispatcher\Queue; - -class BackgroundProcessService extends TestCase -{ - /** - * @var Indatus\Dispatcher\Services\CommandService - */ - private $commandService; - - public function setUp() - { - parent::setUp(); - - $scheduleService = new ScheduleService(new Table(), new Queue()); - $this->commandService = new CommandService($scheduleService); - - } - - public function tearDown() - { - parent::tearDown(); - m::close(); - } - - public function testRunDue() - { - $scheduledCommand = $this->mockCommand(); - $scheduledCommand->shouldReceive('isEnabled')->once()->andReturn(true); - $scheduledCommand->shouldReceive('getName')->once()->andReturn('test:command'); - $scheduledCommand->shouldReceive('user')->once()->andReturn(false); - - $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService'); - $scheduleService->shouldReceive('getDueCommands')->once()->andReturn(array($scheduledCommand)); - $this->app->instance('Indatus\Dispatcher\Services\ScheduleService', $scheduleService); - - $commandService = m::mock('Indatus\Dispatcher\Services\CommandService[runnableInEnvironment,run]', - array($scheduleService), - function ($m) { - $m->shouldReceive('runnableInEnvironment')->andReturn(true); - $m->shouldReceive('run')->andReturnNull(); - }); - - $this->assertNull($commandService->runDue()); - } - - public function testRunnableInAnyEnvironment() - { - $scheduledCommand = $this->mockCommand('*'); - - App::shouldReceive('environment')->andReturn('*'); - $this->assertTrue($this->commandService->runnableInEnvironment($scheduledCommand)); - } - - public function testRunnableInOneEnvironment() - { - $scheduledCommand = $this->mockCommand('local'); - - App::shouldReceive('environment')->andReturn('local'); - $this->assertTrue($this->commandService->runnableInEnvironment($scheduledCommand)); - } - - public function testRunnableInMultipleEnvironments() - { - $scheduledCommand = $this->mockCommand(array('local', 'development')); - - App::shouldReceive('environment')->andReturn('local'); - $this->assertTrue($this->commandService->runnableInEnvironment($scheduledCommand)); - } - - public function testGetRunCommand() - { - $commandName = 'test:command'; - $scheduledCommand = $this->mockCommand(); - $scheduledCommand->shouldReceive('getName')->andReturn($commandName); - $scheduledCommand->shouldReceive('user')->andReturn(false); - $this->assertEquals($this->commandService->getRunCommand($scheduledCommand), implode(' ', array( - 'php', - base_path().'/artisan', - $commandName, - '&', - '> /dev/null 2>&1' - ))); - } - public function testGetRunCommandAsUser() - { - $user = 'myUser'; - $commandName = 'test:command'; - $scheduledCommand = $this->mockCommand(); - $scheduledCommand->shouldReceive('getName')->andReturn($commandName); - $scheduledCommand->shouldReceive('user')->andReturn($user); - $this->assertEquals($this->commandService->getRunCommand($scheduledCommand), implode(' ', array( - 'sudo -u '.$user, - 'php', - base_path().'/artisan', - $commandName, - '&', - '> /dev/null 2>&1' - ))); - } - - private function mockCommand ($environment = '*') - { - return $class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($environment) { - $m->shouldReceive('environment')->andReturn($environment); - }); - } - -} \ No newline at end of file diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index 4606fe6..8601101 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -39,15 +39,24 @@ public function testRunDue() $scheduledCommand->shouldReceive('getName')->once()->andReturn('test:command'); $scheduledCommand->shouldReceive('user')->once()->andReturn(false); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable'); + $scheduler->shouldReceive('getArguments')->once()->andReturn(array()); + $queue = m::mock('Indatus\Dispatcher\Queue', + function ($m) use ($scheduledCommand, $scheduler) { + $item = m::mock('Indatus\Dispatcher\QueueItem'); + $item->shouldReceive('getCommand')->once()->andReturn($scheduledCommand); + $item->shouldReceive('getScheduler')->once()->andReturn($scheduler); + $m->shouldReceive('flush')->once()->andReturn(array($item)); + }); $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService'); - $scheduleService->shouldReceive('getDueCommands')->once()->andReturn(array($scheduledCommand)); + $scheduleService->shouldReceive('getQueue')->once()->andReturn($queue); $this->app->instance('Indatus\Dispatcher\Services\ScheduleService', $scheduleService); $commandService = m::mock('Indatus\Dispatcher\Services\CommandService[runnableInEnvironment,run]', array($scheduleService), - function ($m) { + function ($m) use ($scheduledCommand, $scheduler) { $m->shouldReceive('runnableInEnvironment')->andReturn(true); - $m->shouldReceive('run')->andReturnNull(); + $m->shouldReceive('run')->with($scheduledCommand, $scheduler)->andReturnNull(); }); $this->assertNull($commandService->runDue()); @@ -85,6 +94,59 @@ public function testNotRunnableInEnvironment() $this->assertFalse($this->commandService->runnableInEnvironment($scheduledCommand)); } + public function testPrepareArguments() + { + $arguments = array( + 'test' => 'argument' + ); + $commandService = $this->getMockForAbstractClass('Indatus\Dispatcher\Services\CommandService', + array( + m::mock('Indatus\Dispatcher\Services\ScheduleService') + )); + + $this->assertEquals( + '--test="argument"', + $commandService->prepareArguments($arguments) + ); + } + + public function testPrepareArgumentsKeyOnly() + { + $arguments = array( + 'test' => 'argument', + 'keyOnly' + ); + $commandService = $this->getMockForAbstractClass('Indatus\Dispatcher\Services\CommandService', + array( + m::mock('Indatus\Dispatcher\Services\ScheduleService') + )); + + $this->assertEquals( + '--test="argument" --keyOnly', + $commandService->prepareArguments($arguments) + ); + } + + public function testPrepareArgumentsArrayValue() + { + $arguments = array( + 'test' => 'argument', + 'option' => array( + 'value1', + 'value2' + ) + ); + $commandService = $this->getMockForAbstractClass('Indatus\Dispatcher\Services\CommandService', + array( + m::mock('Indatus\Dispatcher\Services\ScheduleService') + )); + + $this->assertEquals( + '--test="argument" --option="value1" --option="value2"', + $commandService->prepareArguments($arguments) + ); + } + public function testGetRunCommand() { $commandName = 'test:command'; @@ -99,6 +161,30 @@ public function testGetRunCommand() '> /dev/null 2>&1' ))); } + + public function testGetRunCommandWithArguments() + { + $commandName = 'test:command'; + $scheduledCommand = $this->mockCommand(); + $scheduledCommand->shouldReceive('getName')->andReturn($commandName); + $scheduledCommand->shouldReceive('user')->andReturn(false); + $this->assertEquals( + $this->commandService->getRunCommand( + $scheduledCommand, + array( + 'option' => 'value' + ) + ), + implode(' ', array( + 'php', + base_path().'/artisan', + $commandName, + '--option="value"', + '&', + '> /dev/null 2>&1' + ))); + } + public function testGetRunCommandAsUser() { $user = 'myUser'; diff --git a/tests/Services/TestScheduleService.php b/tests/Services/TestScheduleService.php index 2d583b5..61929f1 100644 --- a/tests/Services/TestScheduleService.php +++ b/tests/Services/TestScheduleService.php @@ -20,7 +20,7 @@ public function setUp() { parent::setUp(); - $this->scheduleService = new ScheduleService(new Table(), new Queue()); + $this->scheduleService = new ScheduleService(new Table()); } public function tearDown() @@ -40,19 +40,53 @@ public function testGetScheduledCommands() $this->assertSameSize($scheduledCommands, $this->scheduleService->getScheduledCommands()); } - public function testGetDueCommands() + public function testGetQueue() { $scheduleService = m::mock('Indatus\Dispatcher\Services\ScheduleService[getScheduledCommands,isDue]', array( - new Table(), - new Queue() + new Table() ), function ($m) { + $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable'); + $command->shouldReceive('schedule')->once() + ->andReturn($scheduler); + $m->shouldReceive('getScheduledCommands')->once() - ->andReturn(array(m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'))); - $m->shouldReceive('isDue')->once()->andReturn(true); + ->andReturn(array($command)); + $m->shouldReceive('isDue')->once()->with($scheduler) + ->andReturn(true); + + }); + + $queue = $scheduleService->getQueue(); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Queue', + $queue + ); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testGetQueueException() + { + $scheduleService = m::mock('Indatus\Dispatcher\Services\ScheduleService[getScheduledCommands,isDue]', array( + new Table() + ), function ($m) { + $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); + $command->shouldReceive('schedule')->once() + ->andReturn(array(1)); + $command->shouldReceive('getName')->once() + ->andReturn('asdf'); + $m->shouldReceive('getScheduledCommands')->once() + ->andReturn(array($command)); }); - $this->assertEquals(1, count($scheduleService->getDueCommands())); + $queue = $scheduleService->getQueue(); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Queue', + $queue + ); } } \ No newline at end of file From 9b61264390e2cbde7950805b31de93ca94844606 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Mon, 7 Apr 2014 23:27:04 -0400 Subject: [PATCH 07/25] Resolved dependency issue --- src/Indatus/Dispatcher/ConfigResolver.php | 42 +++++++++++++----- .../Dispatcher/Drivers/Cron/Scheduler.php | 3 +- .../Dispatcher/Scheduling/Schedulable.php | 24 ++++++++-- src/Indatus/Dispatcher/ServiceProvider.php | 6 +-- tests/Drivers/Cron/TestCronScheduler.php | 4 +- tests/Scheduling/TestSchedulable.php | 44 ------------------- tests/TestConfigResolver.php | 32 ++++++++------ 7 files changed, 76 insertions(+), 79 deletions(-) delete mode 100644 tests/Scheduling/TestSchedulable.php diff --git a/src/Indatus/Dispatcher/ConfigResolver.php b/src/Indatus/Dispatcher/ConfigResolver.php index 839ac47..4f98fd7 100644 --- a/src/Indatus/Dispatcher/ConfigResolver.php +++ b/src/Indatus/Dispatcher/ConfigResolver.php @@ -18,29 +18,47 @@ class ConfigResolver /** * Resolve a class based on the driver configuration * - * @param $className - * @param array $arguments - * - * @return mixed + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ - public function resolveDriverClass($className, $arguments = array()) + public function resolveSchedulerClass() { try { return App::make( - Config::get('dispatcher::driver').'\\'.$className, array( - $this, - $arguments + Config::get('dispatcher::driver').'\\Scheduler', array( + $this ) ); } catch (\ReflectionException $e) { - $driver = ucwords(strtolower(Config::get('dispatcher::driver'))); return App::make( - 'Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className, array( - $this, - $arguments + 'Indatus\Dispatcher\Drivers\\'.$this->getDriver().'\\Scheduler', array( + $this ) ); } } + /** + * Resolve a class based on the driver configuration + * + * @return \Indatus\Dispatcher\Scheduling\ScheduleService + */ + public function resolveServiceClass() + { + try { + return App::make(Config::get('dispatcher::driver').'\\ScheduleService'); + } catch (\ReflectionException $e) { + return App::make('Indatus\Dispatcher\Drivers\\'.$this->getDriver().'\\ScheduleService'); + } + } + + /** + * Get the dispatcher driver class + * + * @return string + */ + public function getDriver() + { + return ucwords(strtolower(Config::get('dispatcher::driver'))); + } + } diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index 32ee4b1..66acff0 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -291,7 +291,8 @@ public function args(array $arguments) } /** - * @todo This is a terrible method name + * If an array of values is used, convert it + * to a comma separated value. */ private function parseTimeParameter($parameter) { diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index 4411827..363acd8 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -15,14 +15,15 @@ abstract class Schedulable { + /** @var \Indatus\Dispatcher\ConfigResolver $configResolver */ protected $configResolver; - protected $arguments; + /** @var array $arguments */ + protected $arguments = array(); - public function __construct(ConfigResolver $configResolver, $arguments = array()) + public function __construct(ConfigResolver $configResolver) { $this->configResolver = $configResolver; - $this->arguments = $arguments; } /** @@ -34,7 +35,10 @@ public function __construct(ConfigResolver $configResolver, $arguments = array() */ public function args(array $arguments) { - return $this->configResolver->resolveDriverClass('Scheduler', $arguments); + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ + $scheduler = $this->configResolver->resolveSchedulerClass(); + $scheduler->setArguments($arguments); + return $scheduler; } /** @@ -46,4 +50,16 @@ public function getArguments() { return $this->arguments; } + + /** + * Set the schedule's arguments + * + * This method is only to be used internally by Dispatcher. + * + * @param array $arguments + */ + public function setArguments($arguments) + { + $this->arguments = $arguments; + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/ServiceProvider.php b/src/Indatus/Dispatcher/ServiceProvider.php index af65395..4733077 100644 --- a/src/Indatus/Dispatcher/ServiceProvider.php +++ b/src/Indatus/Dispatcher/ServiceProvider.php @@ -44,12 +44,12 @@ public function register() //load the scheduler of the appropriate driver App::bind('Indatus\Dispatcher\Scheduling\Schedulable', function () use ($resolver) { - return $resolver->resolveDriverClass('Scheduler'); + return $resolver->resolveSchedulerClass(); }); - //load the scheduler of the appropriate driver + //load the schedule service of the appropriate driver App::bind('Indatus\Dispatcher\Services\ScheduleService', function () use ($resolver) { - return $resolver->resolveDriverClass('ScheduleService'); + return $resolver->resolveServiceClass(); }); $this->registerCommands(); diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index 4c2fb62..f2dfd9f 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -8,7 +8,7 @@ class TestCronScheduler extends TestCase { /** - * @var Indatus\Dispatcher\Scheduler + * @var Indatus\Dispatcher\Drivers\Cron\Scheduler */ private $scheduler; @@ -150,7 +150,7 @@ public function testArgs() { $args = array('testArgument'); - /** @var \Indatus\Dispatcher\Scheduleable $scheduler */ + /** @var \Indatus\Dispatcher\Drivers\Cron\Scheduler $scheduler */ $scheduler = $this->scheduler->args($args); $this->assertInstanceOf($this->schedularClass, $scheduler); $this->assertEquals($args, $scheduler->getArguments()); diff --git a/tests/Scheduling/TestSchedulable.php b/tests/Scheduling/TestSchedulable.php deleted file mode 100644 index cf8b506..0000000 --- a/tests/Scheduling/TestSchedulable.php +++ /dev/null @@ -1,44 +0,0 @@ - - */ - -use Mockery as m; -use Indatus\Dispatcher\BackgroundProcess; - -class TestSchedulable extends TestCase -{ - - public function tearDown() - { - parent::tearDown(); - m::close(); - } - - public function testArguments() - { - $args = ['type' => 'scheduled']; - /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduleable */ - $scheduleable = $this->getMockForAbstractClass( - 'Indatus\Dispatcher\Scheduling\Schedulable', array( - App::make('Indatus\Dispatcher\ConfigResolver') - )); - $newScheduleable = $scheduleable->args($args); - $this->assertEquals($args, $newScheduleable->getArguments()); - } - - public function testArgumentsConstructor() - { - $args = ['type' => 'scheduled']; - - /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduleable */ - $scheduleable = $this->getMockForAbstractClass( - 'Indatus\Dispatcher\Scheduling\Schedulable', array( - App::make('Indatus\Dispatcher\ConfigResolver'), - $args - ) - ); - - $this->assertEquals($args, $scheduleable->getArguments()); - } -} \ No newline at end of file diff --git a/tests/TestConfigResolver.php b/tests/TestConfigResolver.php index 50dd8c6..70a32d4 100644 --- a/tests/TestConfigResolver.php +++ b/tests/TestConfigResolver.php @@ -16,35 +16,41 @@ public function tearDown() m::close(); } - public function testLoadingPackagedDriver() + public function testLoadingSchedulerPackagedDriver() { $resolver = new ConfigResolver(); $this->assertInstanceOf( 'Indatus\Dispatcher\Drivers\Cron\Scheduler', - $resolver->resolveDriverClass('Scheduler') + $resolver->resolveSchedulerClass() ); } - public function testLoadingPackagedDriverWithArguments() + public function testLoadingServiceCustomDriver() { - $args = array('testArgument'); + Config::shouldReceive('get')->andReturn('cron'); $resolver = new ConfigResolver(); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Scheduling\Schedulable', + $resolver->resolveSchedulerClass() + ); + } - /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ - $scheduler = $resolver->resolveDriverClass('Scheduler', $args); - $this->assertEquals( - $args, - $scheduler->getArguments() + public function testLoadingServicePackagedDriver() + { + $resolver = new ConfigResolver(); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Services\ScheduleService', + $resolver->resolveServiceClass() ); } - public function testLoadingCustomDriver() + public function testLoadingSchedulerCustomDriver() { - Config::shouldReceive('get')->andReturn('Indatus\Dispatcher\Drivers\Cron'); + Config::shouldReceive('get')->andReturn('cron'); $resolver = new ConfigResolver(); $this->assertInstanceOf( - 'Indatus\Dispatcher\Scheduling\Schedulable', - $resolver->resolveDriverClass('Scheduler') + 'Indatus\Dispatcher\Services\ScheduleService', + $resolver->resolveServiceClass() ); } From a59e32e22d7292b26cd7848f3f50e8ce9ee0f618 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Tue, 8 Apr 2014 20:49:46 -0400 Subject: [PATCH 08/25] Commands can now be scheduled with arguments and options --- .../Dispatcher/BackgroundProcessRunner.php | 10 ++- .../Drivers/Cron/ScheduleService.php | 87 +++++++++++++++---- .../Dispatcher/Drivers/Cron/Scheduler.php | 9 ++ .../Dispatcher/Scheduling/Schedulable.php | 62 ++++++++++++- .../Scheduling/ScheduledCommandInterface.php | 1 - .../Dispatcher/Services/CommandService.php | 45 +++++++--- .../Dispatcher/Services/ScheduleService.php | 2 +- .../Drivers/Cron/TestCronScheduleService.php | 51 +++++++++-- tests/Drivers/Cron/TestCronScheduler.php | 17 ++++ tests/Services/TestCommandService.php | 40 +++++++-- 10 files changed, 271 insertions(+), 53 deletions(-) diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index a45f861..bdf3281 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -32,11 +32,15 @@ public function __construct(CommandService $commandService) * * @param ScheduledCommand $scheduledCommand * @param array $arguments + * @param array $options * @return bool */ - public function run(ScheduledCommand $scheduledCommand, array $arguments = array()) - { - exec($this->commandService->getRunCommand($scheduledCommand), $arguments); + public function run( + ScheduledCommand $scheduledCommand, + array $arguments = array(), + array $options = array() + ) { + exec($this->commandService->getRunCommand($scheduledCommand, $arguments, $options)); return true; } diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index 86e709e..9657637 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -12,20 +12,28 @@ use App; use Cron\CronExpression; use Indatus\Dispatcher\Scheduling\Schedulable; +use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; +use Log; class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { /** * Determine if a schedule is due to be run * - * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler + * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler * * @return bool */ public function isDue(Schedulable $scheduler) { - $cron = CronExpression::factory($scheduler->getSchedule()); - return $cron->isDue(); + try { + $cron = CronExpression::factory($scheduler->getSchedule()); + return $cron->isDue(); + } catch (\Exception $e) { + Log::error($e->getMessage()); + } + + return false; } /** @@ -33,27 +41,72 @@ public function isDue(Schedulable $scheduler) */ public function printSummary() { - $this->table->setHeaders(array('Environment(s)', 'Name', 'Minute', 'Hour', 'Day of Month', 'Month', 'Day of Week', 'Run as')); + $this->table->setHeaders(array('Environment(s)', 'Name', 'Args/Opts', 'Minute', 'Hour', 'Day of Month', 'Month', 'Day of Week', 'Run as')); /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ foreach ($this->getScheduledCommands() as $command) { /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Scheduling\Schedulable')); - $this->table->addRow(array( - is_array($command->environment()) ? implode(',', $command->environment()) : $command->environment(), - $command->getName(), - $scheduler->getScheduleMinute(), - $scheduler->getScheduleHour(), - $scheduler->getScheduleDayOfMonth(), - $scheduler->getScheduleMonth(), - $scheduler->getScheduleDayOfWeek(), - $command->user() - )); + //if there's only one schedule, print just the command + if (!is_array($scheduler)) { + $this->printCommand($command, $scheduler); + } else { + if ($this->printCommandLabel($command)) { + foreach ($scheduler as $schedule) { + $this->printSchedule($command, $schedule); + } + } + } } - //sort by first column - $this->table->sort(0); - $this->table->display(); } + + protected function printCommand(ScheduledCommandInterface $command, Schedulable $scheduler) + { + $this->table->addRow(array( + is_array($command->environment()) ? implode(',', $command->environment()) : $command->environment(), + $command->getName(), + '', + $scheduler->getScheduleMinute(), + $scheduler->getScheduleHour(), + $scheduler->getScheduleDayOfMonth(), + $scheduler->getScheduleMonth(), + $scheduler->getScheduleDayOfWeek(), + $command->user() + )); + } + + protected function printCommandLabel(ScheduledCommandInterface $command) + { + $this->table->addRow(array( + is_array($command->environment()) ? implode(',', $command->environment()) : $command->environment(), + $command->getName(), + '', + '', + '', + '', + '', + '', + $command->user() + )); + return true; + } + + protected function printSchedule(ScheduledCommandInterface $command, Schedulable $scheduler) + { + $commandService = App::make('Indatus\Dispatcher\Services\CommandService'); + + $this->table->addRow(array( + '', + '', + trim($commandService->prepareArguments($scheduler->getArguments()).' '.$commandService->prepareOptions($scheduler->getOptions())), + $scheduler->getScheduleMinute(), + $scheduler->getScheduleHour(), + $scheduler->getScheduleDayOfMonth(), + $scheduler->getScheduleMonth(), + $scheduler->getScheduleDayOfWeek(), + '' + )); + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index 66acff0..5fbcc0c 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -290,6 +290,15 @@ public function args(array $arguments) return parent::args($arguments); } + /** + * @inheritDoc + * @return $this + */ + public function opts(array $options) + { + return parent::opts($options); + } + /** * If an array of values is used, convert it * to a comma separated value. diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index 363acd8..0213c44 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -21,6 +21,12 @@ abstract class Schedulable /** @var array $arguments */ protected $arguments = array(); + /** @var array $options */ + protected $options = array(); + + /** @var bool Instantiate a new instance when using args() or opts() */ + protected $instantiateNew = true; + public function __construct(ConfigResolver $configResolver) { $this->configResolver = $configResolver; @@ -35,8 +41,7 @@ public function __construct(ConfigResolver $configResolver) */ public function args(array $arguments) { - /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ - $scheduler = $this->configResolver->resolveSchedulerClass(); + $scheduler = $this->getClass(); $scheduler->setArguments($arguments); return $scheduler; } @@ -62,4 +67,57 @@ public function setArguments($arguments) { $this->arguments = $arguments; } + + /** + * Define options for this command when it runs. + * + * @param array $options + * + * @return \Indatus\Dispatcher\Scheduling\Schedulable + */ + public function opts(array $options) + { + $scheduler = $this->getClass(); + $scheduler->setOptions($options); + return $scheduler; + } + + /** + * Get the options for this command. + * + * @return array + */ + public function getOptions() + { + return $this->options; + } + + /** + * Set the schedule's options + * + * This method is only to be used internally by Dispatcher. + * + * @param array $options + */ + public function setOptions($options) + { + $this->options = $options; + } + + /** + * Get a scheduler class + * + * @return $this|Schedulable + */ + public function getClass() + { + //use the existing one if we've already instantiated + if ($this->instantiateNew === false) { + return $this; + } + + $this->instantiateNew = false; + + return $this; + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php b/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php index 7af20da..279f952 100644 --- a/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php +++ b/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php @@ -5,7 +5,6 @@ */ use Indatus\Dispatcher\Scheduler; -use Indatus\Dispatcher\Scheduling\Schedulable; interface ScheduledCommandInterface { diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 258df25..46f7686 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -10,7 +10,6 @@ */ use App; -use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Scheduling\ScheduledCommand; class CommandService @@ -77,30 +76,42 @@ public function runnableInEnvironment(ScheduledCommand $command) */ public function prepareArguments(array $arguments) { - $argumentPieces = array(); - foreach ($arguments as $arg => $value) { + return implode(' ', $arguments); + } + + /** + * Prepare a command's options for command line usage + * + * @param array $options + * + * @return string + */ + public function prepareOptions(array $options) + { + $optionPieces = array(); + foreach ($options as $opt => $value) { //if it's an array of options, throw them in there as well if (is_array($value)) { - foreach ($value as $argArrayValue) { - $argumentPieces[] = '--'.$arg.'="'.addslashes($argArrayValue).'"'; + foreach ($value as $optArrayValue) { + $optionPieces[] = '--'.$opt.'="'.addslashes($optArrayValue).'"'; } } else { - $argument = null; + $option = null; //option exists with no value - if (is_numeric($arg)) { - $argument = $value; + if (is_numeric($opt)) { + $option = $value; } elseif (!empty($value)) { - $argument = $arg.'="'.addslashes($value).'"'; + $option = $opt.'="'.addslashes($value).'"'; } - if (!is_null($argument)) { - $argumentPieces[] = '--'.$argument; + if (!is_null($option)) { + $optionPieces[] = '--'.$option; } } } - return implode(' ', $argumentPieces); + return implode(' ', $optionPieces); } /** @@ -108,10 +119,14 @@ public function prepareArguments(array $arguments) * * @param \Indatus\Dispatcher\Scheduling\ScheduledCommand $scheduledCommand * @param array $arguments + * @param array $options * * @return string */ - public function getRunCommand(ScheduledCommand $scheduledCommand, array $arguments = array()) + public function getRunCommand( + ScheduledCommand $scheduledCommand, + array $arguments = array(), + array $options = array()) { $commandPieces = array( 'php', @@ -123,6 +138,10 @@ public function getRunCommand(ScheduledCommand $scheduledCommand, array $argumen $commandPieces[] = $this->prepareArguments($arguments); } + if (count($options) > 0) { + $commandPieces[] = $this->prepareOptions($options); + } + $commandPieces[] = '&'; //run in background $commandPieces[] = '> /dev/null 2>&1'; //don't show output, errors can be viewed in the Laravel log diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index bc1144a..21d128f 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -20,7 +20,7 @@ abstract class ScheduleService { - /** @var \Indatus\Dispatcher\Table */ + /** @var \Indatus\Dispatcher\Table */ protected $table; public function __construct(Table $table) diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index e0c94e4..db430b9 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -37,6 +37,15 @@ public function testIsNotDue() $this->assertFalse($this->scheduleService->isDue($scheduler)); } + public function testIsDueException() + { + Log::shouldReceive('error')->once(); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { + $m->shouldReceive('getSchedule')->once()->andReturn('asdf'); + }); + $this->assertFalse($this->scheduleService->isDue($scheduler)); + } + public function testIsDue() { $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { @@ -53,7 +62,6 @@ public function testPrintSummary() { $table = m::mock('Indatus\Dispatcher\Table', function ($m) { $m->shouldReceive('setHeaders')->once(); - $m->shouldReceive('sort')->once(); $m->shouldReceive('display')->once(); }); $queue = m::mock('Indatus\Dispatcher\Queue', function ($m) { @@ -61,25 +69,50 @@ public function testPrintSummary() $m->shouldReceive('sort')->once(); $m->shouldReceive('display')->once();*/ }); + + $scheduledCommandWithMultipleSchedulers = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { + $table->shouldReceive('addRow')->times(3); + + $scheduler = m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { + $m->shouldReceive('getScheduleMinute'); + $m->shouldReceive('getScheduleHour'); + $m->shouldReceive('getScheduleDayOfMonth'); + $m->shouldReceive('getScheduleMonth'); + $m->shouldReceive('getScheduleDayOfWeek'); + $m->shouldReceive('getArguments')->twice()->andReturn(array()); + $m->shouldReceive('getOptions')->twice()->andReturn(array()); + }); + + $m->shouldReceive('getName')->once(); + $m->shouldReceive('user')->once(); + $m->shouldReceive('environment')->twice(); + $m->shouldReceive('schedule')->once()->andReturn([ + $scheduler, + $scheduler + ]); + }); $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { $table->shouldReceive('addRow')->once(); + $scheduler = m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { + $m->shouldReceive('getScheduleMinute'); + $m->shouldReceive('getScheduleHour'); + $m->shouldReceive('getScheduleDayOfMonth'); + $m->shouldReceive('getScheduleMonth'); + $m->shouldReceive('getScheduleDayOfWeek'); + }); + $m->shouldReceive('getName')->once(); $m->shouldReceive('user')->once(); $m->shouldReceive('environment')->twice(); - $m->shouldReceive('schedule')->once()->andReturn(m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { - $m->shouldReceive('getScheduleMinute'); - $m->shouldReceive('getScheduleHour'); - $m->shouldReceive('getScheduleDayOfMonth'); - $m->shouldReceive('getScheduleMonth'); - $m->shouldReceive('getScheduleDayOfWeek'); - })); + $m->shouldReceive('schedule')->once()->andReturn($scheduler); }); $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService[getScheduledCommands]', array( $table, $queue - ), function ($m) use ($scheduledCommand) { + ), function ($m) use ($scheduledCommand, $scheduledCommandWithMultipleSchedulers) { $m->shouldReceive('getScheduledCommands')->once()->andReturn(array( + $scheduledCommandWithMultipleSchedulers, $scheduledCommand )); }); diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index f2dfd9f..133bc17 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -156,4 +156,21 @@ public function testArgs() $this->assertEquals($args, $scheduler->getArguments()); } + public function testOpts() + { + $opts = array( + 'testOpt', + 'option' => 'value' + ); + $args = array( + 'testArgument' + ); + + /** @var \Indatus\Dispatcher\Drivers\Cron\Scheduler $scheduler */ + $scheduler = $this->scheduler->args($args)->opts($opts); + $this->assertInstanceOf($this->schedularClass, $scheduler); + $this->assertEquals($args, $scheduler->getArguments()); + $this->assertEquals($opts, $scheduler->getOptions()); + } + } \ No newline at end of file diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index 8601101..f314f4f 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -97,7 +97,7 @@ public function testNotRunnableInEnvironment() public function testPrepareArguments() { $arguments = array( - 'test' => 'argument' + 'argument' ); $commandService = $this->getMockForAbstractClass('Indatus\Dispatcher\Services\CommandService', array( @@ -105,12 +105,12 @@ public function testPrepareArguments() )); $this->assertEquals( - '--test="argument"', + 'argument', $commandService->prepareArguments($arguments) ); } - public function testPrepareArgumentsKeyOnly() + public function testPrepareOptions() { $arguments = array( 'test' => 'argument', @@ -123,11 +123,11 @@ public function testPrepareArgumentsKeyOnly() $this->assertEquals( '--test="argument" --keyOnly', - $commandService->prepareArguments($arguments) + $commandService->prepareOptions($arguments) ); } - public function testPrepareArgumentsArrayValue() + public function testPrepareOptionsArrayValue() { $arguments = array( 'test' => 'argument', @@ -143,7 +143,7 @@ public function testPrepareArgumentsArrayValue() $this->assertEquals( '--test="argument" --option="value1" --option="value2"', - $commandService->prepareArguments($arguments) + $commandService->prepareOptions($arguments) ); } @@ -172,7 +172,32 @@ public function testGetRunCommandWithArguments() $this->commandService->getRunCommand( $scheduledCommand, array( - 'option' => 'value' + 'option' + ) + ), + implode(' ', array( + 'php', + base_path().'/artisan', + $commandName, + 'option', + '&', + '> /dev/null 2>&1' + ))); + } + + public function testGetRunCommandWithOptions() + { + $commandName = 'test:command'; + $scheduledCommand = $this->mockCommand(); + $scheduledCommand->shouldReceive('getName')->andReturn($commandName); + $scheduledCommand->shouldReceive('user')->andReturn(false); + $this->assertEquals( + $this->commandService->getRunCommand( + $scheduledCommand, + array(), + array( + 'option' => 'value', + 'anotherOption' ) ), implode(' ', array( @@ -180,6 +205,7 @@ public function testGetRunCommandWithArguments() base_path().'/artisan', $commandName, '--option="value"', + '--anotherOption', '&', '> /dev/null 2>&1' ))); From f578f8e726947932915135e7312eb5a23e853a3e Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Tue, 8 Apr 2014 21:59:30 -0400 Subject: [PATCH 09/25] Options are now properly passed to the command --- .../Dispatcher/BackgroundProcessRunner.php | 1 + src/Indatus/Dispatcher/Commands/Run.php | 1 + .../Dispatcher/Scheduling/Schedulable.php | 34 +++++++++++-------- .../Dispatcher/Services/CommandService.php | 8 +++-- .../Dispatcher/Services/ScheduleService.php | 2 +- tests/Drivers/Cron/TestCronScheduler.php | 6 ++++ 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index bdf3281..f4a77ba 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -40,6 +40,7 @@ public function run( array $arguments = array(), array $options = array() ) { + \Log::debug($scheduledCommand->getName(), [$this->commandService->getRunCommand($scheduledCommand, $arguments, $options)]); exec($this->commandService->getRunCommand($scheduledCommand, $arguments, $options)); return true; diff --git a/src/Indatus/Dispatcher/Commands/Run.php b/src/Indatus/Dispatcher/Commands/Run.php index 800a1b9..d6c67ec 100644 --- a/src/Indatus/Dispatcher/Commands/Run.php +++ b/src/Indatus/Dispatcher/Commands/Run.php @@ -50,6 +50,7 @@ public function __construct(CommandService $commandService) */ public function fire() { + $this->commandService->runDue(); } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index 0213c44..206e6c5 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -41,9 +41,14 @@ public function __construct(ConfigResolver $configResolver) */ public function args(array $arguments) { - $scheduler = $this->getClass(); - $scheduler->setArguments($arguments); - return $scheduler; + if (count($this->getOptions()) == 0) { + $scheduler = $this->getNewSchedulerClass(); + $scheduler->setArguments($arguments); + return $scheduler; + } + + $this->setArguments($arguments); + return $this; } /** @@ -77,9 +82,14 @@ public function setArguments($arguments) */ public function opts(array $options) { - $scheduler = $this->getClass(); - $scheduler->setOptions($options); - return $scheduler; + if (count($this->getArguments()) == 0) { + $scheduler = $this->getNewSchedulerClass(); + $scheduler->setOptions($options); + return $scheduler; + } + + $this->setOptions($options); + return $this; } /** @@ -109,15 +119,11 @@ public function setOptions($options) * * @return $this|Schedulable */ - public function getClass() + public function getNewSchedulerClass() { - //use the existing one if we've already instantiated - if ($this->instantiateNew === false) { - return $this; - } + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ + $scheduler = $this->configResolver->resolveSchedulerClass(); - $this->instantiateNew = false; - - return $this; + return $scheduler; } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 46f7686..82e9725 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -35,11 +35,15 @@ public function runDue() /** @var \Indatus\Dispatcher\Queue $queue */ $queue = $this->scheduleService->getQueue(); + \Log::debug('runCommand', [$queue->size()]); foreach ($queue->flush() as $queueItem) { $command = $queueItem->getCommand(); - $scheduler = $queueItem->getScheduler(); + if ($command->isEnabled() && $this->runnableInEnvironment($command)) { - $backgroundProcessRunner->run($command, $scheduler->getArguments()); + $scheduler = $queueItem->getScheduler(); + + \Log::debug('runCommand', [$command->getName(), $scheduler->getArguments(), $scheduler->getOptions()]); + $backgroundProcessRunner->run($command, $scheduler->getArguments(), $scheduler->getOptions()); } } } diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 21d128f..0dc8e18 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -86,7 +86,7 @@ public function getQueue() $queueItem = App::make('Indatus\Dispatcher\QueueItem'); $queueItem->setCommand($command); - $queueItem->setScheduler($scheduler); + $queueItem->setScheduler($schedule); $queue->add($queueItem); } diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index 133bc17..216933c 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -171,6 +171,12 @@ public function testOpts() $this->assertInstanceOf($this->schedularClass, $scheduler); $this->assertEquals($args, $scheduler->getArguments()); $this->assertEquals($opts, $scheduler->getOptions()); + + /** @var \Indatus\Dispatcher\Drivers\Cron\Scheduler $scheduler */ + $scheduler = $this->scheduler->opts($opts)->args($args); + $this->assertInstanceOf($this->schedularClass, $scheduler); + $this->assertEquals($args, $scheduler->getArguments()); + $this->assertEquals($opts, $scheduler->getOptions()); } } \ No newline at end of file From dc9b185ecde9e4fc9e24425c899448626de0bec5 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Wed, 9 Apr 2014 09:32:47 -0400 Subject: [PATCH 10/25] all variations of arguments and options are now fully accepted --- README.md | 53 ++++++++++++++++++- .../Dispatcher/BackgroundProcessRunner.php | 3 +- .../Drivers/Cron/ScheduleService.php | 2 +- .../Dispatcher/Drivers/Cron/Scheduler.php | 8 +++ .../Dispatcher/Services/CommandService.php | 2 - .../Dispatcher/Services/ScheduleService.php | 1 - tests/Commands/TestMake.php | 2 +- tests/Commands/TestRun.php | 2 +- tests/Commands/TestScheduleSummary.php | 2 +- .../Drivers/Cron/TestCronScheduleService.php | 2 +- tests/Drivers/Cron/TestCronScheduler.php | 3 +- tests/Scheduling/TestScheduledCommand.php | 2 +- tests/Services/TestCommandService.php | 9 ++-- tests/Services/TestScheduleService.php | 3 +- tests/TestBackgroundProcessRunner.php | 2 +- tests/TestConfig.php | 2 +- tests/TestConfigResolver.php | 4 +- tests/TestQueue.php | 1 - tests/TestQueueItem.php | 2 +- tests/TestServiceProvider.php | 4 +- 20 files changed, 82 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 5fcfde6..0358e77 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ class MyCommand extends ScheduledCommand { * [Generating New Scheduled Commands](#new-commands) * [Scheduling Existing Commands](#scheduling-commands) * [Running Commands As Users](#commands-as-users) - * [Environment-specific commands](#environment-commands) + * [Environment-Specific Commands](#environment-commands) + * [Advanced Scheduling](#advanced-scheduling) * [Drivers](#drivers) * [Cron](#Cron) * [Custom Drivers](#custom-drivers) @@ -126,7 +127,7 @@ You may override `user()` to run a given artisan command as a specific user. En > This feature may not be supported by all drivers. -### Environment-specific commands +### Environment-Specific Commands You may override `environment()` to ensure your command is only scheduled in specific environments. It should provide a single environment or an array of environments. @@ -137,7 +138,55 @@ You may override `environment()` to ensure your command is only scheduled in spe } ``` + +### Advanced scheduling +You may schedule a given command to to run at multiple times by `schedule()` returning multiple `Schedulable` instances. + +```php + public function schedule(Schedulable $scheduler) + { + return [ + // 5am Mon-Fri + $scheduler->everyWeekday()->hours(5), + + // 2am every Saturday + App::make(get_class($scheduler)) + ->daysOfTheWeek(Scheduler::SATURDAY) + ->hours(2) + ]; + } +``` + +You may also schedule a command to run with arguments and options. + +```php + + public function schedule(Schedulable $scheduler) + { + return [ + // equivalent to: php /path/to/artisan command:name /path/to/file + $scheduler->args(['/path/to/file']) + ->everyWeekday() + ->hours(5), + + // equivalent to: php /path/to/artisan command:name /path/to/file --force --toDelete="expired" --exclude="admins" --exclude="developers" + $scheduler->args(['/path/to/file']) + ->opts([ + 'force', + 'toDelete' => 'expired', + 'exclude' => [ + 'admins', + 'developers' + ] + ]) + ->daysOfTheMonth([1, 15]) + ->hours(2) + ]; + } +``` + +> Both `args()` and `opts()`, whichever is called first, will internally create a new `Schedulable` instance for you, so be sure you call those prior to any scheduling methods. ## Drivers diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index f4a77ba..1c6f104 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -40,7 +40,8 @@ public function run( array $arguments = array(), array $options = array() ) { - \Log::debug($scheduledCommand->getName(), [$this->commandService->getRunCommand($scheduledCommand, $arguments, $options)]); + + \Log::debug('runCommand', [$this->commandService->getRunCommand($scheduledCommand, $arguments, $options)]); exec($this->commandService->getRunCommand($scheduledCommand, $arguments, $options)); return true; diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index 9657637..83fb8ac 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -18,7 +18,7 @@ class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { /** - * Determine if a schedule is due to be run + * Determine if a schedule is due to be run. * * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler * diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index 5fbcc0c..49c531c 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -391,4 +391,12 @@ public function getScheduleMonth() { return $this->scheduleMonth; } + + /** + * @return string + */ + public function __toString() + { + return $this->getSchedule(); + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 82e9725..c6507cf 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -35,14 +35,12 @@ public function runDue() /** @var \Indatus\Dispatcher\Queue $queue */ $queue = $this->scheduleService->getQueue(); - \Log::debug('runCommand', [$queue->size()]); foreach ($queue->flush() as $queueItem) { $command = $queueItem->getCommand(); if ($command->isEnabled() && $this->runnableInEnvironment($command)) { $scheduler = $queueItem->getScheduler(); - \Log::debug('runCommand', [$command->getName(), $scheduler->getArguments(), $scheduler->getOptions()]); $backgroundProcessRunner->run($command, $scheduler->getArguments(), $scheduler->getOptions()); } } diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 0dc8e18..372cc21 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -81,7 +81,6 @@ public function getQueue() } if ($this->isDue($schedule)) { - /** @var \Indatus\Dispatcher\QueueItem $queueItem */ $queueItem = App::make('Indatus\Dispatcher\QueueItem'); diff --git a/tests/Commands/TestMake.php b/tests/Commands/TestMake.php index aecbf10..40f8405 100644 --- a/tests/Commands/TestMake.php +++ b/tests/Commands/TestMake.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Commands\Make; +use Mockery as m; class TestMake extends TestCase { diff --git a/tests/Commands/TestRun.php b/tests/Commands/TestRun.php index c991684..016e9f8 100644 --- a/tests/Commands/TestRun.php +++ b/tests/Commands/TestRun.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Commands\Run; +use Mockery as m; class TestRun extends TestCase { diff --git a/tests/Commands/TestScheduleSummary.php b/tests/Commands/TestScheduleSummary.php index 2264ffa..9e1517d 100644 --- a/tests/Commands/TestScheduleSummary.php +++ b/tests/Commands/TestScheduleSummary.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Commands\ScheduleSummary; +use Mockery as m; class TestScheduleSummary extends TestCase { diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index db430b9..43d61ad 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -3,7 +3,7 @@ * @author Ben Kuhl */ -use \Indatus\Dispatcher\Drivers\Cron\ScheduleService; +use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Mockery as m; class TestCronScheduleService extends TestCase diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index 216933c..ef3eec8 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -3,7 +3,7 @@ * @author Ben Kuhl */ -use \Indatus\Dispatcher\Drivers\Cron\Scheduler; +use Indatus\Dispatcher\Drivers\Cron\Scheduler; class TestCronScheduler extends TestCase { @@ -26,6 +26,7 @@ public function setUp() public function testBuildingSchedule() { $this->assertEquals($this->scheduler->getSchedule(), '* * * * *'); + $this->assertEquals($this->scheduler.'', '* * * * *'); } public function testSetSchedule() diff --git a/tests/Scheduling/TestScheduledCommand.php b/tests/Scheduling/TestScheduledCommand.php index 2d8c5fe..b605d9d 100644 --- a/tests/Scheduling/TestScheduledCommand.php +++ b/tests/Scheduling/TestScheduledCommand.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Drivers\Cron\Scheduler; +use Mockery as m; class TestScheduledCommand extends TestCase { diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index f314f4f..5c17015 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -3,12 +3,12 @@ * @author Ben Kuhl */ -use Mockery as m; -use Indatus\Dispatcher\Services\CommandService; use Indatus\Dispatcher\Drivers\Cron\ScheduleService; -use Indatus\Dispatcher\Table; -use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\Queue; +use Indatus\Dispatcher\Scheduler; +use Indatus\Dispatcher\Services\CommandService; +use Indatus\Dispatcher\Table; +use Mockery as m; class TestCommandService extends TestCase { @@ -41,6 +41,7 @@ public function testRunDue() $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable'); $scheduler->shouldReceive('getArguments')->once()->andReturn(array()); + $scheduler->shouldReceive('getOptions')->once()->andReturn(array()); $queue = m::mock('Indatus\Dispatcher\Queue', function ($m) use ($scheduledCommand, $scheduler) { $item = m::mock('Indatus\Dispatcher\QueueItem'); diff --git a/tests/Services/TestScheduleService.php b/tests/Services/TestScheduleService.php index 61929f1..f07f2fc 100644 --- a/tests/Services/TestScheduleService.php +++ b/tests/Services/TestScheduleService.php @@ -3,11 +3,10 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\Table; -use Indatus\Dispatcher\Queue; +use Mockery as m; class TestScheduleService extends TestCase { diff --git a/tests/TestBackgroundProcessRunner.php b/tests/TestBackgroundProcessRunner.php index c8696f6..97c6036 100644 --- a/tests/TestBackgroundProcessRunner.php +++ b/tests/TestBackgroundProcessRunner.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ +use Indatus\Dispatcher\BackgroundProcessRunner; use Mockery as m; -use \Indatus\Dispatcher\BackgroundProcessRunner; class TestBackgroundProcessRunner extends TestCase { diff --git a/tests/TestConfig.php b/tests/TestConfig.php index c4955a3..782cb96 100644 --- a/tests/TestConfig.php +++ b/tests/TestConfig.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Scheduler; +use Mockery as m; class TestConfig extends TestCase { diff --git a/tests/TestConfigResolver.php b/tests/TestConfigResolver.php index 70a32d4..f1e5ab9 100644 --- a/tests/TestConfigResolver.php +++ b/tests/TestConfigResolver.php @@ -3,9 +3,9 @@ * @author Ben Kuhl */ -use Mockery as m; -use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\ConfigResolver; +use Indatus\Dispatcher\Scheduler; +use Mockery as m; class TestConfigResolver extends TestCase { diff --git a/tests/TestQueue.php b/tests/TestQueue.php index 7b1e814..d4f310a 100644 --- a/tests/TestQueue.php +++ b/tests/TestQueue.php @@ -4,7 +4,6 @@ */ use Mockery as m; -use Indatus\Dispatcher\Queue; class TestQueue extends TestCase { diff --git a/tests/TestQueueItem.php b/tests/TestQueueItem.php index 2782adc..32013b6 100644 --- a/tests/TestQueueItem.php +++ b/tests/TestQueueItem.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\QueueItem; +use Mockery as m; class TestQueueItem extends TestCase { diff --git a/tests/TestServiceProvider.php b/tests/TestServiceProvider.php index 74197e5..fd38037 100644 --- a/tests/TestServiceProvider.php +++ b/tests/TestServiceProvider.php @@ -3,9 +3,9 @@ * @author Ben Kuhl */ -use Mockery as m; -use Indatus\Dispatcher\ServiceProvider; use Indatus\Dispatcher\BackgroundProcess; +use Indatus\Dispatcher\ServiceProvider; +use Mockery as m; class TestServiceProvider extends TestCase { From 81e7077848a67ccea4868999a0f76d9eb10958c0 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Wed, 26 Mar 2014 09:30:21 -0400 Subject: [PATCH 11/25] Resolved an issue with the command stub and improved documentation --- README.md | 74 ++++++++-- src/Indatus/Dispatcher/Commands/Make.php | 4 +- .../Dispatcher/Commands/stubs/command.stub | 2 +- src/Indatus/Dispatcher/Schedulable.php | 139 ------------------ .../Dispatcher/ScheduledCommandInterface.php | 3 +- tests/Commands/TestMake.php | 3 +- 6 files changed, 67 insertions(+), 158 deletions(-) diff --git a/README.md b/README.md index 0496ff2..4f4b552 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,19 @@ ```php - @@ -62,11 +69,7 @@ Add this line to the providers array in your `app/config/app.php` file : 'Indatus\Dispatcher\ServiceProvider', ``` -Add the following cron. If you'd like for scheduled commands to be able to run as different users, be sure to add this to the root crontab. Otherwise all commands run as the user whose crontab you've added this to. - -```php -* * * * * php /path/to/artisan scheduled:run 1>> /dev/null 2>&1 -``` +To use with Cron, see the [Cron driver](#Cron) section. ## Usage @@ -88,7 +91,46 @@ Use `php artisan scheduled:make` to generate a new scheduled command, the same w ### Scheduling Existing Commands -Simply `extend \Indatus\Dispatcher\ScheduledCommand` and implement the `schedule()` method within your command or `implement \Indatus\Dispatcher\ScheduledCommandInterface`. This method is injected with a `Schedulable` which provides a simple interface for scheduling your commands. +You may either `implement \Indatus\Dispatcher\ScheduledCommandInterface` or follow the below steps. + +1. `extend \Indatus\Dispatcher\ScheduledCommand` +2. Add use statements to your command. If you're using a custom driver you will use a different `Scheduler` class. +```php +use Indatus\Dispatcher\ScheduledCommand; +use Indatus\Dispatcher\Schedulable; +use Indatus\Dispatcher\Drivers\Cron\Scheduler; +``` +3. Implement schedule(): +```php + /** + * When a command should run + * + * @param Scheduler $scheduler + * @return \Indatus\Dispatcher\Schedulable + */ + public function schedule(Schedulable $scheduler) + { + return $scheduler; + } +``` + + +#### Drivers + +While Cron is the default driver for Dispatcher, it can be used with any scheduling tool that can run artisan commands. See [building custom drivers](#custom-drivers). + + +##### Cron (Default) + +Add the following to your Crontab: + +```php +* * * * * php /path/to/artisan scheduled:run 1>> /dev/null 2>&1 +``` + +> If you'd like for scheduled commands to be able to run as different users, be sure to add this to the root Crontab. Otherwise all commands run as the user whose Crontab you've added this to. + +Examples of how to schedule: ```php public function schedule(Schedulable $scheduler) @@ -110,7 +152,7 @@ Simply `extend \Indatus\Dispatcher\ScheduledCommand` and implement the `schedule } ``` -You may also schedule commands via raw cron expressions +You may also schedule commands via raw Cron expressions ```php public function schedule(Schedulable $scheduler) @@ -132,6 +174,8 @@ You may override `user()` to run a given artisan command as a specific user. En } ``` +> This feature may not be supported by all drivers. + ### Environment-specific commands @@ -144,15 +188,15 @@ You may override `environment()` to ensure your command is only scheduled in spe } ``` - -## Custom Schedule Drivers + +## Custom Drivers You can build your own drivers or extend a driver that's included. Create a packagepath such as `\MyApp\ScheduleDriver\` and create two classes: - * `Scheduler` that `implements Indatus\Dispatcher\Schedulable` - * `ScheduleService` that `extends \Indatus\Dispatcher\Services\ScheduleService` + * `Scheduler` that `implements Indatus\Dispatcher\Schedulable`. This class should provide a useful interface for programmers to schedule their commands. + * `ScheduleService` that `extends \Indatus\Dispatcher\Services\ScheduleService`. This class contains logic on how to determine if a command is due to run. - Then update your driver configuration to reference the package in which these 2 classes are included (do not include a trailing slash): +Publish the configs using `php artisan view:publish indatus/dispatcher`. Then update your driver configuration to reference the package in which these 2 classes are included (do not include a trailing slash): ```php 'driver' => '\MyApp\ScheduleDriver' diff --git a/src/Indatus/Dispatcher/Commands/Make.php b/src/Indatus/Dispatcher/Commands/Make.php index 44d2315..1946305 100644 --- a/src/Indatus/Dispatcher/Commands/Make.php +++ b/src/Indatus/Dispatcher/Commands/Make.php @@ -10,6 +10,7 @@ */ namespace Indatus\Dispatcher\Commands; +use Config; use Illuminate\Console\Command; use Illuminate\Foundation\Console\CommandMakeCommand; @@ -53,7 +54,8 @@ protected function extendStub($stub) { $replacements = array( 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\ScheduledCommand;\n". - "use Indatus\\Dispatcher\\Scheduler", + "use Indatus\\Dispatcher\\Schedulable;\n". + "use Indatus\\Dispatcher\\Drivers\\".ucwords(Config::get('dispatcher::driver'))."\\Scheduler", 'extends Command {' => 'extends ScheduledCommand {', 'parent::__construct();' => $this->getStub() ); diff --git a/src/Indatus/Dispatcher/Commands/stubs/command.stub b/src/Indatus/Dispatcher/Commands/stubs/command.stub index 15f509e..8f5989b 100644 --- a/src/Indatus/Dispatcher/Commands/stubs/command.stub +++ b/src/Indatus/Dispatcher/Commands/stubs/command.stub @@ -4,7 +4,7 @@ parent::__construct(); /** * When a command should run * - * @param Schedulable $scheduler + * @param Scheduler $scheduler * @return \Indatus\Dispatcher\Schedulable */ public function schedule(Schedulable $scheduler) diff --git a/src/Indatus/Dispatcher/Schedulable.php b/src/Indatus/Dispatcher/Schedulable.php index a1943ba..173de66 100644 --- a/src/Indatus/Dispatcher/Schedulable.php +++ b/src/Indatus/Dispatcher/Schedulable.php @@ -12,144 +12,5 @@ interface Schedulable { - /** - * Run every weekday - * @return $this - */ - public function everyWeekday(); - /** - * Run once an hour at the beginning of the hour - * - * @return $this - */ - public function hourly(); - - /** - * Set the days of the week under which this command will run - * @param mixed $daysOfTheWeek - * @return $this - */ - public function daysOfTheWeek($daysOfTheWeek); - - /** - * Set the months under which this command will run - * @param mixed $monthsIntoTheYear - * @return $this - */ - public function months($monthsIntoTheYear); - - /** - * Set the days of the month under which this command will run - * @param mixed $hoursIntoTheDay - * @return $this - */ - public function daysOfTheMonth($hoursIntoTheDay); - - /** - * Manually set a command's execution schedule - * - * @param mixed $minute - * @param mixed $hour - * @param mixed $dayOfMonth - * @param mixed $month - * @param mixed $dayOfWeek - * @return $this - */ - public function setSchedule($minute, $hour, $dayOfMonth, $month, $dayOfWeek); - - /** - * Run once a day at midnight - * - * @return $this - */ - public function daily(); - - /** - * Run once a month at midnight in the morning of the first day of the month - * - * @return $this - */ - public function monthly(); - - /** - * Set the hours under which this command will run - * @param mixed $hoursIntoTheDay - * @return $this - */ - public function hours($hoursIntoTheDay); - - /** - * Set the minutes under which this command will run - * @param mixed $minutesIntoTheHour - * @return $this - */ - public function minutes($minutesIntoTheHour); - - /** - * Run a command every X hours - * @param $hours - * @return $this - */ - public function everyHours($hours); - - /** - * Run once a month at midnight in the morning of the first day of the month - * - * @return $this - */ - public function weekly(); - - /** - * Run a command every X months - * @param $months - * @return $this - */ - public function everyMonths($months); - - /** - * Run once a year at midnight in the morning of January 1 - * - * @return $this - */ - public function yearly(); - - /** - * Get the scheduling definition for the crontab - * - * @return string - */ - public function getSchedule(); - - /** - * Run a command every X minutes - * @param $minutes - * @return $this - */ - public function everyMinutes($minutes); - - /** - * @return string - */ - public function getScheduleDayOfMonth(); - - /** - * @return string - */ - public function getScheduleDayOfWeek(); - - /** - * @return string - */ - public function getScheduleHour(); - - /** - * @return string - */ - public function getScheduleMinute(); - - /** - * @return string - */ - public function getScheduleMonth(); } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/ScheduledCommandInterface.php b/src/Indatus/Dispatcher/ScheduledCommandInterface.php index d0acc16..d0614ab 100644 --- a/src/Indatus/Dispatcher/ScheduledCommandInterface.php +++ b/src/Indatus/Dispatcher/ScheduledCommandInterface.php @@ -14,7 +14,8 @@ public function user(); /** * When a command should run - * @param Schedulable $scheduler + * + * @param Scheduler $scheduler * @return \Indatus\Dispatcher\Schedulable */ public function schedule(Schedulable $scheduler); diff --git a/tests/Commands/TestMake.php b/tests/Commands/TestMake.php index 17f2d24..b0eba99 100644 --- a/tests/Commands/TestMake.php +++ b/tests/Commands/TestMake.php @@ -64,7 +64,8 @@ public function testExtendStub() $replacements = array( 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\ScheduledCommand;\n". - "use Indatus\\Dispatcher\\Scheduler", + "use Indatus\\Dispatcher\\Schedulable;\n". + "use Indatus\\Dispatcher\\Drivers\\".ucwords(Config::get('dispatcher::driver'))."\\Scheduler", 'extends Command {' => 'extends ScheduledCommand {', 'parent::__construct();' => $stubContents ); From 022fc9f1192165fe9bcaef9ae7698b8b784aa29c Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Wed, 26 Mar 2014 09:35:38 -0400 Subject: [PATCH 12/25] Updated readme --- README.md | 71 +++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 4f4b552..4f774e0 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,6 @@ class MyCommand extends ScheduledCommand { //your command name, description etc. - /** - * When a command should run - * @param Scheduler $scheduler - * @return \Indatus\Dispatcher\Schedulable - */ public function schedule(Schedulable $scheduler) { //every day at 4:17am @@ -37,11 +32,11 @@ class MyCommand extends ScheduledCommand { * [Usage](#usage) * [Generating New Scheduled Commands](#new-commands) * [Scheduling Existing Commands](#scheduling-commands) - * [Drivers](#drivers) - * [Cron](#Cron) * [Running Commands As Users](#commands-as-users) * [Environment-specific commands](#environment-commands) -* [Custom Schedule Drivers](#custom-drivers) +* [Drivers](#drivers) + * [Cron](#Cron) +* [Custom Drivers](#custom-drivers) * [FAQ](#faq) @@ -114,13 +109,43 @@ use Indatus\Dispatcher\Drivers\Cron\Scheduler; } ``` +For details and examples on how to schedule, see [Cron](#Cron). + + +### Running Commands As Users + +You may override `user()` to run a given artisan command as a specific user. Ensure your `scheduled:run` artisan command is running as root. + +```php + public function user() + { + return 'backup'; + } +``` + +> This feature may not be supported by all drivers. + + +### Environment-specific commands + +You may override `environment()` to ensure your command is only scheduled in specific environments. It should provide a single environment or an array of environments. + +```php + public function environment() + { + return ['development','staging']; + } +``` + + + -#### Drivers +## Drivers While Cron is the default driver for Dispatcher, it can be used with any scheduling tool that can run artisan commands. See [building custom drivers](#custom-drivers). -##### Cron (Default) +### Cron (Default) Add the following to your Crontab: @@ -162,32 +187,6 @@ You may also schedule commands via raw Cron expressions } ``` - -### Running Commands As Users - -You may override `user()` to run a given artisan command as a specific user. Ensure your `scheduled:run` artisan command is running as root. - -```php - public function user() - { - return 'backup'; - } -``` - -> This feature may not be supported by all drivers. - - -### Environment-specific commands - -You may override `environment()` to ensure your command is only scheduled in specific environments. It should provide a single environment or an array of environments. - -```php - public function environment() - { - return ['development','staging']; - } -``` - ## Custom Drivers From cab82d547c9c8bf61b9e4aa2e4e7d991398ff88a Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Mon, 31 Mar 2014 23:34:21 -0400 Subject: [PATCH 13/25] $scheduler can now schedule with arguments --- src/Indatus/Dispatcher/ConfigResolver.php | 24 ++++++++-- .../Drivers/Cron/ScheduleService.php | 14 +++++- .../Dispatcher/Drivers/Cron/Scheduler.php | 11 ++++- src/Indatus/Dispatcher/Schedulable.php | 32 ++++++++++++- src/Indatus/Dispatcher/ScheduledCommand.php | 2 +- .../Dispatcher/ScheduledCommandInterface.php | 2 +- tests/Drivers/Cron/TestCronScheduler.php | 12 ++++- tests/TestBackgroundProcess.php | 46 ------------------- tests/TestConfigResolver.php | 23 +++++++++- tests/TestSchedulable.php | 44 ++++++++++++++++++ tests/TestScheduledCommand.php | 5 +- 11 files changed, 156 insertions(+), 59 deletions(-) delete mode 100644 tests/TestBackgroundProcess.php create mode 100644 tests/TestSchedulable.php diff --git a/src/Indatus/Dispatcher/ConfigResolver.php b/src/Indatus/Dispatcher/ConfigResolver.php index 471dfb9..395c8c1 100644 --- a/src/Indatus/Dispatcher/ConfigResolver.php +++ b/src/Indatus/Dispatcher/ConfigResolver.php @@ -16,13 +16,31 @@ class ConfigResolver { - public function resolveDriverClass($className) + /** + * Resolve a class based on the driver configuration + * + * @param $className + * @param array $arguments + * + * @return mixed + */ + public function resolveDriverClass($className, $arguments = []) { try { - return App::make(Config::get('dispatcher::driver').'\\'.$className); + return App::make( + Config::get('dispatcher::driver').'\\'.$className, [ + $this, + $arguments + ] + ); } catch (\ReflectionException $e) { $driver = ucwords(strtolower(Config::get('dispatcher::driver'))); - return App::make('Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className); + return App::make( + 'Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className, [ + $this, + $arguments + ] + ); } } diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index dc8aefe..3f8ed65 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -24,8 +24,18 @@ class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { public function isDue(ScheduledCommandInterface $command) { $scheduler = App::make('Indatus\Dispatcher\Schedulable'); - $cron = CronExpression::factory($command->schedule($scheduler)->getSchedule()); - return $cron->isDue(); + $schedules = $command->schedule($scheduler); + if (!is_array($schedules)) { + $schedules = array($schedules); + } + foreach ($schedules as $schedule) { + $cron = CronExpression::factory($schedule->getSchedule()); + if ($cron->isDue()) { + return true; + } + } + + return false; } /** diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index 7bf2f9b..d0de659 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -12,7 +12,7 @@ use Indatus\Dispatcher\Schedulable; -class Scheduler implements Schedulable +class Scheduler extends Schedulable { /** @@ -282,6 +282,15 @@ public function everyWeekday() return $this; } + /** + * @inheritDoc + * @return $this + */ + public function args(array $arguments) + { + return parent::args($arguments); + } + /** * @todo This is a terrible method name */ diff --git a/src/Indatus/Dispatcher/Schedulable.php b/src/Indatus/Dispatcher/Schedulable.php index 173de66..16a92ef 100644 --- a/src/Indatus/Dispatcher/Schedulable.php +++ b/src/Indatus/Dispatcher/Schedulable.php @@ -10,7 +10,37 @@ */ namespace Indatus\Dispatcher; -interface Schedulable +abstract class Schedulable { + protected $configResolver; + protected $arguments; + + public function __construct(ConfigResolver $configResolver, $arguments = []) + { + $this->configResolver = $configResolver; + $this->arguments = $arguments; + } + + /** + * Define arguments for this command when it runs. + * + * @param array $arguments + * + * @return \Indatus\Dispatcher\Schedulable + */ + public function args(array $arguments) + { + return $this->configResolver->resolveDriverClass('Scheduler', $arguments); + } + + /** + * Get the arguments for this command. + * + * @return array + */ + public function getArguments() + { + return $this->arguments; + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/ScheduledCommand.php b/src/Indatus/Dispatcher/ScheduledCommand.php index dcb8ad2..03fc718 100644 --- a/src/Indatus/Dispatcher/ScheduledCommand.php +++ b/src/Indatus/Dispatcher/ScheduledCommand.php @@ -37,7 +37,7 @@ public function user() /** * Environment(s) under which the given command should run * - * @return string + * @return string|array */ public function environment() { diff --git a/src/Indatus/Dispatcher/ScheduledCommandInterface.php b/src/Indatus/Dispatcher/ScheduledCommandInterface.php index d0614ab..7d0452f 100644 --- a/src/Indatus/Dispatcher/ScheduledCommandInterface.php +++ b/src/Indatus/Dispatcher/ScheduledCommandInterface.php @@ -23,7 +23,7 @@ public function schedule(Schedulable $scheduler); /** * Environment(s) under which the given command should run * Defaults to '*' for all environments - * @return string + * @return string|array */ public function environment(); diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index 324b7d7..c3ed99f 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -17,7 +17,7 @@ class TestCronScheduler extends TestCase public function setUp() { parent::setUp(); - $this->scheduler = new Scheduler(); + $this->scheduler = new Scheduler(App::make('Indatus\Dispatcher\ConfigResolver')); } /** @@ -146,4 +146,14 @@ public function testEveryWeekday() $this->assertEquals($this->scheduler->getSchedule(), Scheduler::ANY.' '.Scheduler::ANY.' '.Scheduler::ANY.' '.Scheduler::ANY.' '.Scheduler::MONDAY.'-'.Scheduler::FRIDAY); } + public function testArgs() + { + $args = array('testArgument'); + + /** @var \Indatus\Dispatcher\Scheduleable $scheduler */ + $scheduler = $this->scheduler->args($args); + $this->assertInstanceOf($this->schedularClass, $scheduler); + $this->assertEquals($args, $scheduler->getArguments()); + } + } \ No newline at end of file diff --git a/tests/TestBackgroundProcess.php b/tests/TestBackgroundProcess.php deleted file mode 100644 index fa2e041..0000000 --- a/tests/TestBackgroundProcess.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ - -use Mockery as m; -use Indatus\Dispatcher\Drivers\Cron\Scheduler; -use Indatus\Dispatcher\BackgroundProcess; - -class TestBackgroundProcess extends TestCase -{ - /** - * @var Indatus\Dispatcher\ScheduledCommand - */ - private $scheduledCommand; - - public function setUp() - { - parent::setUp(); - - $this->scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand[schedule]'); - - $this->app->instance('Indatus\Dispatcher\Schedulable', new Scheduler()); - } - - public function tearDown() - { - parent::tearDown(); - m::close(); - } - - public function testSomething() - { - - } - - /*public function testRunAsOnWindows() - { - $platform = m::mock('Indatus\Dispatcher\Platform'); - $platform->shouldReceive('isWindows')->once()->andReturn(false); - $this->app->instance('Indatus\Dispatcher\Platform', $platform); - - $backgroundProcess = new BackgroundProcess(); - //$backgroundProcess->run(); - }*/ -} \ No newline at end of file diff --git a/tests/TestConfigResolver.php b/tests/TestConfigResolver.php index d22b64e..e4909a5 100644 --- a/tests/TestConfigResolver.php +++ b/tests/TestConfigResolver.php @@ -19,14 +19,33 @@ public function tearDown() public function testLoadingPackagedDriver() { $resolver = new ConfigResolver(); - $this->assertInstanceOf('Indatus\Dispatcher\Drivers\Cron\Scheduler', $resolver->resolveDriverClass('Scheduler')); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Drivers\Cron\Scheduler', + $resolver->resolveDriverClass('Scheduler') + ); + } + + public function testLoadingPackagedDriverWithArguments() + { + $args = array('testArgument'); + $resolver = new ConfigResolver(); + + /** @var \Indatus\Dispatcher\Schedulable $scheduler */ + $scheduler = $resolver->resolveDriverClass('Scheduler', $args); + $this->assertEquals( + $args, + $scheduler->getArguments() + ); } public function testLoadingCustomDriver() { Config::shouldReceive('get')->andReturn('Indatus\Dispatcher\Drivers\Cron'); $resolver = new ConfigResolver(); - $this->assertInstanceOf('Indatus\Dispatcher\Schedulable', $resolver->resolveDriverClass('Scheduler')); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Schedulable', + $resolver->resolveDriverClass('Scheduler') + ); } } \ No newline at end of file diff --git a/tests/TestSchedulable.php b/tests/TestSchedulable.php new file mode 100644 index 0000000..aa48624 --- /dev/null +++ b/tests/TestSchedulable.php @@ -0,0 +1,44 @@ + + */ + +use Mockery as m; +use Indatus\Dispatcher\BackgroundProcess; + +class TestSchedulable extends TestCase +{ + + public function tearDown() + { + parent::tearDown(); + m::close(); + } + + public function testArguments() + { + $args = ['type' => 'scheduled']; + /** @var \Indatus\Dispatcher\Schedulable $scheduleable */ + $scheduleable = $this->getMockForAbstractClass( + 'Indatus\Dispatcher\Schedulable', array( + App::make('Indatus\Dispatcher\ConfigResolver') + )); + $newScheduleable = $scheduleable->args($args); + $this->assertEquals($args, $newScheduleable->getArguments()); + } + + public function testArgumentsConstructor() + { + $args = ['type' => 'scheduled']; + + /** @var \Indatus\Dispatcher\Schedulable $scheduleable */ + $scheduleable = $this->getMockForAbstractClass( + 'Indatus\Dispatcher\Schedulable', array( + App::make('Indatus\Dispatcher\ConfigResolver'), + $args + ) + ); + + $this->assertEquals($args, $scheduleable->getArguments()); + } +} \ No newline at end of file diff --git a/tests/TestScheduledCommand.php b/tests/TestScheduledCommand.php index 1a3fc84..9f5bb34 100644 --- a/tests/TestScheduledCommand.php +++ b/tests/TestScheduledCommand.php @@ -19,7 +19,10 @@ public function setUp() $this->scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand[schedule]'); - $this->app->instance('Indatus\Dispatcher\Schedulable', new Scheduler()); + $this->app->instance( + 'Indatus\Dispatcher\Schedulable', + new Scheduler(App::make('Indatus\Dispatcher\ConfigResolver')) + ); } public function tearDown() From 0b8cd601466136f6444eb1f9ede712cb3c3c9e57 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Mon, 31 Mar 2014 23:40:36 -0400 Subject: [PATCH 14/25] PHP 5.3 compatibility --- src/Indatus/Dispatcher/ConfigResolver.php | 10 +++++----- src/Indatus/Dispatcher/Schedulable.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Indatus/Dispatcher/ConfigResolver.php b/src/Indatus/Dispatcher/ConfigResolver.php index 395c8c1..f0b84fa 100644 --- a/src/Indatus/Dispatcher/ConfigResolver.php +++ b/src/Indatus/Dispatcher/ConfigResolver.php @@ -24,22 +24,22 @@ class ConfigResolver * * @return mixed */ - public function resolveDriverClass($className, $arguments = []) + public function resolveDriverClass($className, $arguments = array()) { try { return App::make( - Config::get('dispatcher::driver').'\\'.$className, [ + Config::get('dispatcher::driver').'\\'.$className, array( $this, $arguments - ] + ) ); } catch (\ReflectionException $e) { $driver = ucwords(strtolower(Config::get('dispatcher::driver'))); return App::make( - 'Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className, [ + 'Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className, array( $this, $arguments - ] + ) ); } } diff --git a/src/Indatus/Dispatcher/Schedulable.php b/src/Indatus/Dispatcher/Schedulable.php index 16a92ef..d8affb1 100644 --- a/src/Indatus/Dispatcher/Schedulable.php +++ b/src/Indatus/Dispatcher/Schedulable.php @@ -16,7 +16,7 @@ abstract class Schedulable protected $arguments; - public function __construct(ConfigResolver $configResolver, $arguments = []) + public function __construct(ConfigResolver $configResolver, $arguments = array()) { $this->configResolver = $configResolver; $this->arguments = $arguments; From d164b873ccaa5bc37f589b1158658b02736d6990 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Thu, 3 Apr 2014 22:03:26 -0400 Subject: [PATCH 15/25] Moved classes to Scheduling namespace --- README.md | 10 ++-- .../Dispatcher/BackgroundProcessRunner.php | 1 + src/Indatus/Dispatcher/Commands/Make.php | 4 +- src/Indatus/Dispatcher/ConfigResolver.php | 3 +- .../Drivers/Cron/ScheduleService.php | 25 +++++++-- .../Dispatcher/Drivers/Cron/Scheduler.php | 2 +- src/Indatus/Dispatcher/Queue.php | 46 +++++++++++++++++ src/Indatus/Dispatcher/QueueItem.php | 51 +++++++++++++++++++ .../{ => Scheduling}/Schedulable.php | 4 +- .../Scheduling/ScheduleException.php | 16 ++++++ .../{ => Scheduling}/ScheduledCommand.php | 2 +- .../ScheduledCommandInterface.php | 14 +++-- .../Dispatcher/Services/CommandService.php | 20 +++++--- .../Dispatcher/Services/ScheduleService.php | 12 +++-- tests/Commands/TestMake.php | 4 +- .../Drivers/Cron/TestCronScheduleService.php | 16 +++++- tests/Drivers/Cron/TestCronScheduler.php | 2 +- tests/{ => Scheduling}/TestSchedulable.php | 8 +-- .../{ => Scheduling}/TestScheduledCommand.php | 4 +- .../Services/TestBackgroundProcessService.php | 2 +- tests/Services/TestCommandService.php | 2 +- tests/Services/TestScheduleService.php | 14 ++--- tests/TestBackgroundProcessRunner.php | 2 +- tests/TestConfigResolver.php | 4 +- tests/TestQueue.php | 29 +++++++++++ tests/TestQueueItem.php | 29 +++++++++++ 26 files changed, 276 insertions(+), 50 deletions(-) create mode 100644 src/Indatus/Dispatcher/Queue.php create mode 100644 src/Indatus/Dispatcher/QueueItem.php rename src/Indatus/Dispatcher/{ => Scheduling}/Schedulable.php (92%) create mode 100644 src/Indatus/Dispatcher/Scheduling/ScheduleException.php rename src/Indatus/Dispatcher/{ => Scheduling}/ScheduledCommand.php (95%) rename src/Indatus/Dispatcher/{ => Scheduling}/ScheduledCommandInterface.php (74%) rename tests/{ => Scheduling}/TestSchedulable.php (76%) rename tests/{ => Scheduling}/TestScheduledCommand.php (89%) create mode 100644 tests/TestQueue.php create mode 100644 tests/TestQueueItem.php diff --git a/README.md b/README.md index 4f774e0..fcc6358 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ```php -use Indatus\Dispatcher\ScheduledCommand; +use Indatus\Dispatcher\Scheduling\ScheduledCommand; use Indatus\Dispatcher\Schedulable; use Indatus\Dispatcher\Drivers\Cron\Scheduler; @@ -86,13 +86,13 @@ Use `php artisan scheduled:make` to generate a new scheduled command, the same w ### Scheduling Existing Commands -You may either `implement \Indatus\Dispatcher\ScheduledCommandInterface` or follow the below steps. +You may either `implement \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface` or follow the below steps. -1. `extend \Indatus\Dispatcher\ScheduledCommand` +1. `extend \Indatus\Dispatcher\Scheduling\ScheduledCommand` 2. Add use statements to your command. If you're using a custom driver you will use a different `Scheduler` class. ```php -use Indatus\Dispatcher\ScheduledCommand; -use Indatus\Dispatcher\Schedulable; +use Indatus\Dispatcher\Scheduling\ScheduledCommand; +use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Drivers\Cron\Scheduler; ``` 3. Implement schedule(): diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index d39c32e..a9529ec 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -11,6 +11,7 @@ namespace Indatus\Dispatcher; use App; +use Indatus\Dispatcher\Scheduling\ScheduledCommand; use Indatus\Dispatcher\Services\CommandService; class BackgroundProcessRunner diff --git a/src/Indatus/Dispatcher/Commands/Make.php b/src/Indatus/Dispatcher/Commands/Make.php index 1946305..d89aa6f 100644 --- a/src/Indatus/Dispatcher/Commands/Make.php +++ b/src/Indatus/Dispatcher/Commands/Make.php @@ -53,8 +53,8 @@ protected function writeCommand($file, $stub) { protected function extendStub($stub) { $replacements = array( - 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\ScheduledCommand;\n". - "use Indatus\\Dispatcher\\Schedulable;\n". + 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\Scheduling\\ScheduledCommand;\n". + "use Indatus\\Dispatcher\\Scheduling\\Schedulable;\n". "use Indatus\\Dispatcher\\Drivers\\".ucwords(Config::get('dispatcher::driver'))."\\Scheduler", 'extends Command {' => 'extends ScheduledCommand {', 'parent::__construct();' => $this->getStub() diff --git a/src/Indatus/Dispatcher/ConfigResolver.php b/src/Indatus/Dispatcher/ConfigResolver.php index f0b84fa..1423235 100644 --- a/src/Indatus/Dispatcher/ConfigResolver.php +++ b/src/Indatus/Dispatcher/ConfigResolver.php @@ -1,4 +1,4 @@ -getName().'" is not an instance of Schedulable'); + } + $cron = CronExpression::factory($schedule->getSchedule()); if ($cron->isDue()) { return true; @@ -44,9 +61,9 @@ public function isDue(ScheduledCommandInterface $command) public function printSummary() { $this->table->setHeaders(array('Environment(s)', 'Name', 'Minute', 'Hour', 'Day of Month', 'Month', 'Day of Week', 'Run as')); - /** @var $command \Indatus\Dispatcher\ScheduledCommandInterface */ + /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ foreach ($this->getScheduledCommands() as $command) { - /** @var $command \Indatus\Dispatcher\ScheduledCommandInterface */ + /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Schedulable')); $this->table->addRow(array( diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index d0de659..ac707c2 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -10,7 +10,7 @@ */ namespace Indatus\Dispatcher\Drivers\Cron; -use Indatus\Dispatcher\Schedulable; +use Indatus\Dispatcher\Scheduling\Schedulable; class Scheduler extends Schedulable { diff --git a/src/Indatus/Dispatcher/Queue.php b/src/Indatus/Dispatcher/Queue.php new file mode 100644 index 0000000..d7d1785 --- /dev/null +++ b/src/Indatus/Dispatcher/Queue.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +class Queue +{ + /** @var QueueItem[] */ + protected static $queue = array(); + + /** + * Add an item to the queue + * @param QueueItem $item + */ + public function add(QueueItem $item) + { + self::$queue[] = $item; + } + + /** + * The size of the queue + * @return int + */ + public function size() + { + return count(self::$queue); + } + + /** + * Get all items in the queue + * @return QueueItem[] + */ + public function flush() + { + $queue = self::$queue; + self::$queue = array(); + + return $queue; + } +} diff --git a/src/Indatus/Dispatcher/QueueItem.php b/src/Indatus/Dispatcher/QueueItem.php new file mode 100644 index 0000000..ed69b29 --- /dev/null +++ b/src/Indatus/Dispatcher/QueueItem.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +class QueueItem +{ + /** @var \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ + protected $command; + + /** @var \Indatus\Dispatcher\Scheduling\Schedulable */ + protected $scheduler; + + /** + * @return \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface + */ + public function getCommand() + { + return $this->command; + } + + /** + * @param \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface $command + */ + public function setCommand($command) + { + $this->command = $command; + } + + /** + * @return \Indatus\Dispatcher\Scheduling\Schedulable + */ + public function getScheduler() + { + return $this->scheduler; + } + + /** + * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler + */ + public function setScheduler($scheduler) + { + $this->scheduler = $scheduler; + } +} diff --git a/src/Indatus/Dispatcher/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php similarity index 92% rename from src/Indatus/Dispatcher/Schedulable.php rename to src/Indatus/Dispatcher/Scheduling/Schedulable.php index d8affb1..f907fc7 100644 --- a/src/Indatus/Dispatcher/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -8,7 +8,9 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Indatus\Dispatcher; +namespace Indatus\Dispatcher\Scheduling; + +use Indatus\Dispatcher\ConfigResolver; abstract class Schedulable { diff --git a/src/Indatus/Dispatcher/Scheduling/ScheduleException.php b/src/Indatus/Dispatcher/Scheduling/ScheduleException.php new file mode 100644 index 0000000..2d2a737 --- /dev/null +++ b/src/Indatus/Dispatcher/Scheduling/ScheduleException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Indatus\Dispatcher\Scheduling; + +class ScheduleException extends \Exception +{ + +} \ No newline at end of file diff --git a/src/Indatus/Dispatcher/ScheduledCommand.php b/src/Indatus/Dispatcher/Scheduling/ScheduledCommand.php similarity index 95% rename from src/Indatus/Dispatcher/ScheduledCommand.php rename to src/Indatus/Dispatcher/Scheduling/ScheduledCommand.php index 03fc718..9a5a632 100644 --- a/src/Indatus/Dispatcher/ScheduledCommand.php +++ b/src/Indatus/Dispatcher/Scheduling/ScheduledCommand.php @@ -8,7 +8,7 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Indatus\Dispatcher; +namespace Indatus\Dispatcher\Scheduling; use App; use Illuminate\Console\Command; diff --git a/src/Indatus/Dispatcher/ScheduledCommandInterface.php b/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php similarity index 74% rename from src/Indatus/Dispatcher/ScheduledCommandInterface.php rename to src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php index 7d0452f..cc56fdf 100644 --- a/src/Indatus/Dispatcher/ScheduledCommandInterface.php +++ b/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php @@ -2,10 +2,19 @@ /** * @author Ben Kuhl */ -namespace Indatus\Dispatcher; +namespace Indatus\Dispatcher\Scheduling; + +use Indatus\Dispatcher\Scheduler; +use Indatus\Dispatcher\Scheduling\Schedulable; interface ScheduledCommandInterface { + /** + * Get the name of the command + * @return string + */ + public function getName(); + /** * User to run the command as * @return string Defaults to false to run as default user @@ -14,9 +23,8 @@ public function user(); /** * When a command should run - * * @param Scheduler $scheduler - * @return \Indatus\Dispatcher\Schedulable + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ public function schedule(Schedulable $scheduler); diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 44cc9d6..7f299ce 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -11,7 +11,7 @@ namespace Indatus\Dispatcher\Services; use App; -use Indatus\Dispatcher\ScheduledCommand; +use Indatus\Dispatcher\Scheduling\ScheduledCommand; class CommandService { @@ -41,9 +41,13 @@ public function runDue() /** * Determine if a scheduled command is in the correct environment - * - * @param \Indatus\Dispatcher\ScheduledCommand $command - * @return bool + + +* +*@param \Indatus\Dispatcher\Scheduling\ScheduledCommand $command + +* +*@return bool */ public function runnableInEnvironment(ScheduledCommand $command) { @@ -63,8 +67,12 @@ public function runnableInEnvironment(ScheduledCommand $command) /** * Get a command to run this application - * @param ScheduledCommand $scheduledCommand - * @return string + +* + * @param \Indatus\Dispatcher\Scheduling\ScheduledCommand $scheduledCommand + +* +*@return string */ public function getRunCommand(ScheduledCommand $scheduledCommand) { diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 5d6ea09..4c9eed0 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -12,7 +12,7 @@ use App; use Artisan; -use Indatus\Dispatcher\ScheduledCommandInterface; +use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; use Indatus\Dispatcher\Table; abstract class ScheduleService @@ -28,8 +28,12 @@ public function __construct(Table $table) /** * Determine if a command is due to be run - * @param ScheduledCommandInterface $command - * @return bool + +* +*@param \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface $command + +* +*@return bool */ abstract public function isDue(ScheduledCommandInterface $command); @@ -53,7 +57,7 @@ public function getScheduledCommands() /** * Get all commands that are due to be run * - * @return \Indatus\Dispatcher\ScheduledCommand[] + * @return \Indatus\Dispatcher\Scheduling\ScheduledCommand[] */ public function getDueCommands() { diff --git a/tests/Commands/TestMake.php b/tests/Commands/TestMake.php index b0eba99..aecbf10 100644 --- a/tests/Commands/TestMake.php +++ b/tests/Commands/TestMake.php @@ -63,8 +63,8 @@ public function testExtendStub() $stubContents = file_get_contents($this->getStubPath('command.stub')); $replacements = array( - 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\ScheduledCommand;\n". - "use Indatus\\Dispatcher\\Schedulable;\n". + 'use Illuminate\Console\Command' => "use Indatus\\Dispatcher\\Scheduling\\ScheduledCommand;\n". + "use Indatus\\Dispatcher\\Scheduling\\Schedulable;\n". "use Indatus\\Dispatcher\\Drivers\\".ucwords(Config::get('dispatcher::driver'))."\\Scheduler", 'extends Command {' => 'extends ScheduledCommand {', 'parent::__construct();' => $stubContents diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index b13ecd5..ab7cfa8 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -3,6 +3,7 @@ * @author Ben Kuhl */ +use \Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Mockery as m; class TestCronScheduleService extends TestCase @@ -18,6 +19,19 @@ public function tearDown() m::close(); } + /** + * @expectedException \Indatus\Dispatcher\Scheduling\ScheduleException + */ + public function testIsDueException() + { + $scheduleService = new ScheduleService(m::mock('Indatus\Dispatcher\Table')); + + $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); + $command->shouldReceive('schedule')->once()->andReturnNull(); + $command->shouldReceive('getName')->once()->andReturn('testCommand'); + $scheduleService->isDue($command); + } + /** * Test that a summary is properly generated * Dangit this is ugly... gotta find a new cli library @@ -29,7 +43,7 @@ public function testPrintSummary() $m->shouldReceive('sort')->once(); $m->shouldReceive('display')->once(); }); - $scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) use ($table) { + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { $table->shouldReceive('addRow')->once(); $m->shouldReceive('getName')->once(); diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index c3ed99f..4c2fb62 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -12,7 +12,7 @@ class TestCronScheduler extends TestCase */ private $scheduler; - private $schedularClass = 'Indatus\Dispatcher\Schedulable'; + private $schedularClass = 'Indatus\Dispatcher\Scheduling\Schedulable'; public function setUp() { diff --git a/tests/TestSchedulable.php b/tests/Scheduling/TestSchedulable.php similarity index 76% rename from tests/TestSchedulable.php rename to tests/Scheduling/TestSchedulable.php index aa48624..cf8b506 100644 --- a/tests/TestSchedulable.php +++ b/tests/Scheduling/TestSchedulable.php @@ -18,9 +18,9 @@ public function tearDown() public function testArguments() { $args = ['type' => 'scheduled']; - /** @var \Indatus\Dispatcher\Schedulable $scheduleable */ + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduleable */ $scheduleable = $this->getMockForAbstractClass( - 'Indatus\Dispatcher\Schedulable', array( + 'Indatus\Dispatcher\Scheduling\Schedulable', array( App::make('Indatus\Dispatcher\ConfigResolver') )); $newScheduleable = $scheduleable->args($args); @@ -31,9 +31,9 @@ public function testArgumentsConstructor() { $args = ['type' => 'scheduled']; - /** @var \Indatus\Dispatcher\Schedulable $scheduleable */ + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduleable */ $scheduleable = $this->getMockForAbstractClass( - 'Indatus\Dispatcher\Schedulable', array( + 'Indatus\Dispatcher\Scheduling\Schedulable', array( App::make('Indatus\Dispatcher\ConfigResolver'), $args ) diff --git a/tests/TestScheduledCommand.php b/tests/Scheduling/TestScheduledCommand.php similarity index 89% rename from tests/TestScheduledCommand.php rename to tests/Scheduling/TestScheduledCommand.php index 9f5bb34..e94d008 100644 --- a/tests/TestScheduledCommand.php +++ b/tests/Scheduling/TestScheduledCommand.php @@ -9,7 +9,7 @@ class TestScheduledCommand extends TestCase { /** - * @var Indatus\Dispatcher\ScheduledCommand + * @var \Indatus\Dispatcher\Scheduling\ScheduledCommand */ private $scheduledCommand; @@ -17,7 +17,7 @@ public function setUp() { parent::setUp(); - $this->scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand[schedule]'); + $this->scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand[schedule]'); $this->app->instance( 'Indatus\Dispatcher\Schedulable', diff --git a/tests/Services/TestBackgroundProcessService.php b/tests/Services/TestBackgroundProcessService.php index 47cbc73..4f31b7a 100644 --- a/tests/Services/TestBackgroundProcessService.php +++ b/tests/Services/TestBackgroundProcessService.php @@ -109,7 +109,7 @@ public function testGetRunCommandAsUser() private function mockCommand ($environment = '*') { - return $class = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) use ($environment) { + return $class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($environment) { $m->shouldReceive('environment')->andReturn($environment); }); } diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index 2b9fa02..2b00796 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -117,7 +117,7 @@ public function testGetRunCommandAsUser() private function mockCommand ($environment = '*') { - return $class = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) use ($environment) { + return $class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($environment) { $m->shouldReceive('environment')->andReturn($environment); }); } diff --git a/tests/Services/TestScheduleService.php b/tests/Services/TestScheduleService.php index 1a85f79..dbeffda 100644 --- a/tests/Services/TestScheduleService.php +++ b/tests/Services/TestScheduleService.php @@ -30,7 +30,7 @@ public function tearDown() public function testGetScheduledCommands() { - $scheduledCommands = array($class = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) { + $scheduledCommands = array($class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Schedulable')); })); @@ -45,7 +45,7 @@ public function testGetDueCommands() new Table() ), function ($m) { $m->shouldReceive('getScheduledCommands')->once() - ->andReturn(array(m::mock('Indatus\Dispatcher\ScheduledCommand'))); + ->andReturn(array(m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'))); $m->shouldReceive('isDue')->once()->andReturn(true); }); @@ -55,23 +55,25 @@ public function testGetDueCommands() public function testIsNotDue() { - $scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduler', function ($m) { + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { + $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { //schedule the cron to run yesterday $dateTime = new DateTime('yesterday'); $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); })); }); + $scheduledCommand->shouldReceive('getName'); $this->assertFalse($this->scheduleService->isDue($scheduledCommand)); } public function testIsDue() { - $scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduler', function ($m) { + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { + $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { $m->shouldReceive('getSchedule')->once()->andReturn('* * * * *'); })); }); + $scheduledCommand->shouldReceive('getName'); $this->assertTrue($this->scheduleService->isDue($scheduledCommand)); } diff --git a/tests/TestBackgroundProcessRunner.php b/tests/TestBackgroundProcessRunner.php index 32f49c0..c8696f6 100644 --- a/tests/TestBackgroundProcessRunner.php +++ b/tests/TestBackgroundProcessRunner.php @@ -25,7 +25,7 @@ public function testRun() $commandService = m::mock('Indatus\Dispatcher\Services\CommandService', function ($m) { $m->shouldReceive('getRunCommand')->once()->andReturn('echo "this is a test"'); }); - $scheduledCommand = m::mock('Indatus\Dispatcher\ScheduledCommand'); + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); $backgroundProcessRunner = new BackgroundProcessRunner($commandService); $this->assertTrue($backgroundProcessRunner->run($scheduledCommand)); diff --git a/tests/TestConfigResolver.php b/tests/TestConfigResolver.php index e4909a5..50dd8c6 100644 --- a/tests/TestConfigResolver.php +++ b/tests/TestConfigResolver.php @@ -30,7 +30,7 @@ public function testLoadingPackagedDriverWithArguments() $args = array('testArgument'); $resolver = new ConfigResolver(); - /** @var \Indatus\Dispatcher\Schedulable $scheduler */ + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ $scheduler = $resolver->resolveDriverClass('Scheduler', $args); $this->assertEquals( $args, @@ -43,7 +43,7 @@ public function testLoadingCustomDriver() Config::shouldReceive('get')->andReturn('Indatus\Dispatcher\Drivers\Cron'); $resolver = new ConfigResolver(); $this->assertInstanceOf( - 'Indatus\Dispatcher\Schedulable', + 'Indatus\Dispatcher\Scheduling\Schedulable', $resolver->resolveDriverClass('Scheduler') ); } diff --git a/tests/TestQueue.php b/tests/TestQueue.php new file mode 100644 index 0000000..7b1e814 --- /dev/null +++ b/tests/TestQueue.php @@ -0,0 +1,29 @@ + + */ + +use Mockery as m; +use Indatus\Dispatcher\Queue; + +class TestQueue extends TestCase +{ + + public function tearDown() + { + parent::tearDown(); + m::close(); + } + + public function testQueue() + { + $item = m::mock('Indatus\Dispatcher\QueueItem'); + + $queue = new Indatus\Dispatcher\Queue(); + $this->assertEquals(0, $queue->size()); + $queue->add($item); + $this->assertEquals(1, $queue->size()); + $this->assertEquals([$item], $queue->flush()); + $this->assertEquals(0, $queue->size()); + } +} \ No newline at end of file diff --git a/tests/TestQueueItem.php b/tests/TestQueueItem.php new file mode 100644 index 0000000..2782adc --- /dev/null +++ b/tests/TestQueueItem.php @@ -0,0 +1,29 @@ + + */ + +use Mockery as m; +use Indatus\Dispatcher\QueueItem; + +class TestQueueItem extends TestCase +{ + + public function tearDown() + { + parent::tearDown(); + m::close(); + } + + public function testQueue() + { + $command = m::mock('Indatus\Dispatcher\Scheduling\Command'); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable'); + + $queueItem = new QueueItem(); + $queueItem->setCommand($command); + $this->assertEquals($command, $queueItem->getCommand()); + $queueItem->setScheduler($scheduler); + $this->assertEquals($scheduler, $queueItem->getScheduler()); + } +} \ No newline at end of file From 5fc247bc9c225d3f0a5e92039715391a60b59f1e Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Thu, 3 Apr 2014 22:12:31 -0400 Subject: [PATCH 16/25] Adjusted namespacing/comments --- .../Dispatcher/BackgroundProcessRunner.php | 5 ++--- src/Indatus/Dispatcher/Commands/Make.php | 4 +--- src/Indatus/Dispatcher/Commands/Run.php | 4 +--- .../Dispatcher/Commands/ScheduleSummary.php | 3 +-- src/Indatus/Dispatcher/ConfigResolver.php | 2 +- .../Drivers/Cron/ScheduleService.php | 18 ++++----------- .../Dispatcher/Drivers/Cron/Scheduler.php | 3 +-- src/Indatus/Dispatcher/Platform.php | 6 ++--- .../Dispatcher/Scheduling/Schedulable.php | 3 +-- .../Scheduling/ScheduleException.php | 5 ++--- .../Scheduling/ScheduledCommand.php | 4 +--- .../Scheduling/ScheduledCommandInterface.php | 6 ++--- src/Indatus/Dispatcher/ServiceProvider.php | 5 ++--- .../Services/BackgroundProcessService.php | 5 ++--- .../Dispatcher/Services/CommandService.php | 22 +++++++------------ .../Dispatcher/Services/ScheduleService.php | 13 +++++------ src/Indatus/Dispatcher/Table.php | 5 ++--- src/Indatus/Dispatcher/TableInterface.php | 12 +++------- 18 files changed, 42 insertions(+), 83 deletions(-) diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index a9529ec..ac9996a 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -1,4 +1,4 @@ - - * @package Indatus\Dispatcher\Commands */ class Make extends CommandMakeCommand { diff --git a/src/Indatus/Dispatcher/Commands/Run.php b/src/Indatus/Dispatcher/Commands/Run.php index b679b67..800a1b9 100644 --- a/src/Indatus/Dispatcher/Commands/Run.php +++ b/src/Indatus/Dispatcher/Commands/Run.php @@ -1,4 +1,4 @@ - - * @package Indatus\Dispatcher\Commands */ class Run extends Command { diff --git a/src/Indatus/Dispatcher/Commands/ScheduleSummary.php b/src/Indatus/Dispatcher/Commands/ScheduleSummary.php index 76fafaa..f1d085b 100644 --- a/src/Indatus/Dispatcher/Commands/ScheduleSummary.php +++ b/src/Indatus/Dispatcher/Commands/ScheduleSummary.php @@ -1,4 +1,4 @@ - */ -namespace Indatus\Dispatcher\Scheduling; use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\Scheduling\Schedulable; @@ -42,4 +42,4 @@ public function environment(); * @return Boolean */ public function isEnabled(); -} \ No newline at end of file +} diff --git a/src/Indatus/Dispatcher/ServiceProvider.php b/src/Indatus/Dispatcher/ServiceProvider.php index b8a8e0c..01a132e 100644 --- a/src/Indatus/Dispatcher/ServiceProvider.php +++ b/src/Indatus/Dispatcher/ServiceProvider.php @@ -1,4 +1,4 @@ -commands('command.scheduled.run'); } -} \ No newline at end of file +} diff --git a/src/Indatus/Dispatcher/Services/BackgroundProcessService.php b/src/Indatus/Dispatcher/Services/BackgroundProcessService.php index ab0890a..53ce1a4 100644 --- a/src/Indatus/Dispatcher/Services/BackgroundProcessService.php +++ b/src/Indatus/Dispatcher/Services/BackgroundProcessService.php @@ -1,4 +1,4 @@ - - * @package Indatus\Dispatcher */ interface TableInterface { @@ -68,10 +65,7 @@ public function resetTable(); /** * Sets the renderer used by this table. * - * @param table\Renderer $renderer The renderer to use for output. - * @see table\Renderer - * @see table\Ascii - * @see table\Tabular + * @param \cli\table\Renderer $renderer The renderer to use for output. */ public function setRenderer(Renderer $renderer); @@ -81,4 +75,4 @@ public function setRenderer(Renderer $renderer); * @param int $column The index of the column to sort by. */ public function sort($column); -} \ No newline at end of file +} From 24100d83e312873ebec1427d5dd6667e45a0fa9f Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Thu, 3 Apr 2014 22:53:33 -0400 Subject: [PATCH 17/25] Commands are now queued with their arguments to be run --- README.md | 6 +- .../Dispatcher/Commands/stubs/command.stub | 2 +- .../Drivers/Cron/ScheduleService.php | 12 +++- .../Dispatcher/Scheduling/Schedulable.php | 2 +- src/Indatus/Dispatcher/ServiceProvider.php | 2 +- .../Dispatcher/Services/ScheduleService.php | 7 ++- .../Drivers/Cron/TestCronScheduleService.php | 61 +++++++++++++++++-- tests/Scheduling/TestScheduledCommand.php | 2 +- .../Services/TestBackgroundProcessService.php | 3 +- tests/Services/TestCommandService.php | 3 +- tests/Services/TestScheduleService.php | 34 ++--------- tests/TestConfig.php | 2 +- 12 files changed, 91 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index fcc6358..ceaf908 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ```php use Indatus\Dispatcher\Scheduling\ScheduledCommand; -use Indatus\Dispatcher\Schedulable; +use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Drivers\Cron\Scheduler; class MyCommand extends ScheduledCommand { @@ -101,7 +101,7 @@ use Indatus\Dispatcher\Drivers\Cron\Scheduler; * When a command should run * * @param Scheduler $scheduler - * @return \Indatus\Dispatcher\Schedulable + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ public function schedule(Schedulable $scheduler) { @@ -192,7 +192,7 @@ You may also schedule commands via raw Cron expressions You can build your own drivers or extend a driver that's included. Create a packagepath such as `\MyApp\ScheduleDriver\` and create two classes: - * `Scheduler` that `implements Indatus\Dispatcher\Schedulable`. This class should provide a useful interface for programmers to schedule their commands. + * `Scheduler` that `implements Indatus\Dispatcher\Scheduling\Schedulable`. This class should provide a useful interface for programmers to schedule their commands. * `ScheduleService` that `extends \Indatus\Dispatcher\Services\ScheduleService`. This class contains logic on how to determine if a command is due to run. Publish the configs using `php artisan view:publish indatus/dispatcher`. Then update your driver configuration to reference the package in which these 2 classes are included (do not include a trailing slash): diff --git a/src/Indatus/Dispatcher/Commands/stubs/command.stub b/src/Indatus/Dispatcher/Commands/stubs/command.stub index 8f5989b..c63c614 100644 --- a/src/Indatus/Dispatcher/Commands/stubs/command.stub +++ b/src/Indatus/Dispatcher/Commands/stubs/command.stub @@ -5,7 +5,7 @@ parent::__construct(); * When a command should run * * @param Scheduler $scheduler - * @return \Indatus\Dispatcher\Schedulable + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ public function schedule(Schedulable $scheduler) { diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index f9a2c4f..6ccbff7 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -26,7 +26,7 @@ class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { */ public function isDue(ScheduledCommandInterface $command) { - $scheduler = App::make('Indatus\Dispatcher\Schedulable'); + $scheduler = App::make('Indatus\Dispatcher\Scheduling\Schedulable'); $schedules = $command->schedule($scheduler); if (!is_array($schedules)) { $schedules = array($schedules); @@ -38,6 +38,14 @@ public function isDue(ScheduledCommandInterface $command) $cron = CronExpression::factory($schedule->getSchedule()); if ($cron->isDue()) { + + //add to the queue so we can run it later + /** @var \Indatus\Dispatcher\QueueItem $queueItem */ + $queueItem = App::make('Indatus\Dispatcher\QueueItem'); + $queueItem->setCommand($command); + $queueItem->setScheduler($scheduler); + $this->queue->add($queueItem); + return true; } } @@ -54,7 +62,7 @@ public function printSummary() /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ foreach ($this->getScheduledCommands() as $command) { /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ - $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Schedulable')); + $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Scheduling\Schedulable')); $this->table->addRow(array( is_array($command->environment()) ? implode(',', $command->environment()) : $command->environment(), diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index e1f3058..d11cacb 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -28,7 +28,7 @@ public function __construct(ConfigResolver $configResolver, $arguments = array() * * @param array $arguments * - * @return \Indatus\Dispatcher\Schedulable + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ public function args(array $arguments) { diff --git a/src/Indatus/Dispatcher/ServiceProvider.php b/src/Indatus/Dispatcher/ServiceProvider.php index 01a132e..af65395 100644 --- a/src/Indatus/Dispatcher/ServiceProvider.php +++ b/src/Indatus/Dispatcher/ServiceProvider.php @@ -43,7 +43,7 @@ public function register() $resolver = App::make('\Indatus\Dispatcher\ConfigResolver'); //load the scheduler of the appropriate driver - App::bind('Indatus\Dispatcher\Schedulable', function () use ($resolver) { + App::bind('Indatus\Dispatcher\Scheduling\Schedulable', function () use ($resolver) { return $resolver->resolveDriverClass('Scheduler'); }); diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 5c8b9d9..548862a 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -11,6 +11,7 @@ use App; use Artisan; +use Indatus\Dispatcher\Queue; use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; use Indatus\Dispatcher\Table; @@ -20,9 +21,13 @@ abstract class ScheduleService /** @var \Indatus\Dispatcher\Table */ protected $table; - public function __construct(Table $table) + /** @var \Indatus\Dispatcher\Queue */ + protected $queue; + + public function __construct(Table $table, Queue $queue) { $this->table = $table; + $this->queue = $queue; } /** diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index ab7cfa8..a247fa1 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -8,9 +8,18 @@ class TestCronScheduleService extends TestCase { + /** + * @var Indatus\Dispatcher\ScheduleService + */ + private $scheduleService; + public function setUp() { parent::setUp(); + + $table = m::mock('Indatus\Dispatcher\Table'); + $queue = m::mock('Indatus\Dispatcher\Queue'); + $this->scheduleService = new ScheduleService($table, $queue); } public function tearDown() @@ -24,12 +33,50 @@ public function tearDown() */ public function testIsDueException() { - $scheduleService = new ScheduleService(m::mock('Indatus\Dispatcher\Table')); - $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); $command->shouldReceive('schedule')->once()->andReturnNull(); $command->shouldReceive('getName')->once()->andReturn('testCommand'); - $scheduleService->isDue($command); + $this->scheduleService->isDue($command); + } + + public function testIsNotDue() + { + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { + $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { + //schedule the cron to run yesterday + $dateTime = new DateTime('yesterday'); + $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); + })); + }); + $scheduledCommand->shouldReceive('getName'); + $this->assertFalse($this->scheduleService->isDue($scheduledCommand)); + } + + public function testIsDue() + { + $scheduler = m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { + $m->shouldReceive('getSchedule')->once()->andReturn('* * * * *'); + }); + App::shouldReceive('make')->with('Indatus\Dispatcher\Scheduling\Schedulable') + ->andReturn($scheduler); + + $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($scheduler) { + $m->shouldReceive('schedule')->andReturn($scheduler); + }); + $scheduledCommand->shouldReceive('getName'); + + $queueItem = m::mock('Indatus\Dispatcher\QueueItem'); + $queueItem->shouldReceive('setCommand')->with($scheduledCommand)->once(); + $queueItem->shouldReceive('setScheduler')->with($scheduler)->once(); + App::shouldReceive('make')->with('Indatus\Dispatcher\QueueItem') + ->andReturn($queueItem); + + $table = m::mock('Indatus\Dispatcher\Table'); + $queue = m::mock('Indatus\Dispatcher\Queue'); + $queue->shouldReceive('add')->with($queueItem)->once(); + $scheduleService = new ScheduleService($table, $queue); + + $this->assertTrue($scheduleService->isDue($scheduledCommand)); } /** @@ -43,6 +90,11 @@ public function testPrintSummary() $m->shouldReceive('sort')->once(); $m->shouldReceive('display')->once(); }); + $queue = m::mock('Indatus\Dispatcher\Queue', function ($m) { + /*$m->shouldReceive('setHeaders')->once(); + $m->shouldReceive('sort')->once(); + $m->shouldReceive('display')->once();*/ + }); $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { $table->shouldReceive('addRow')->once(); @@ -58,7 +110,8 @@ public function testPrintSummary() })); }); $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService[getScheduledCommands]', array( - $table + $table, + $queue ), function ($m) use ($scheduledCommand) { $m->shouldReceive('getScheduledCommands')->once()->andReturn(array( $scheduledCommand diff --git a/tests/Scheduling/TestScheduledCommand.php b/tests/Scheduling/TestScheduledCommand.php index e94d008..2d8c5fe 100644 --- a/tests/Scheduling/TestScheduledCommand.php +++ b/tests/Scheduling/TestScheduledCommand.php @@ -20,7 +20,7 @@ public function setUp() $this->scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand[schedule]'); $this->app->instance( - 'Indatus\Dispatcher\Schedulable', + 'Indatus\Dispatcher\Scheduling\Schedulable', new Scheduler(App::make('Indatus\Dispatcher\ConfigResolver')) ); } diff --git a/tests/Services/TestBackgroundProcessService.php b/tests/Services/TestBackgroundProcessService.php index 4f31b7a..1d69132 100644 --- a/tests/Services/TestBackgroundProcessService.php +++ b/tests/Services/TestBackgroundProcessService.php @@ -8,6 +8,7 @@ use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Indatus\Dispatcher\Table; use Indatus\Dispatcher\Scheduler; +use Indatus\Dispatcher\Queue; class BackgroundProcessService extends TestCase { @@ -20,7 +21,7 @@ public function setUp() { parent::setUp(); - $scheduleService = new ScheduleService(new Table()); + $scheduleService = new ScheduleService(new Table(), new Queue()); $this->commandService = new CommandService($scheduleService); } diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index 2b00796..4606fe6 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -8,6 +8,7 @@ use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Indatus\Dispatcher\Table; use Indatus\Dispatcher\Scheduler; +use Indatus\Dispatcher\Queue; class TestCommandService extends TestCase { @@ -20,7 +21,7 @@ public function setUp() { parent::setUp(); - $scheduleService = new ScheduleService(new Table()); + $scheduleService = new ScheduleService(new Table(), new Queue()); $this->commandService = new CommandService($scheduleService); } diff --git a/tests/Services/TestScheduleService.php b/tests/Services/TestScheduleService.php index dbeffda..2d583b5 100644 --- a/tests/Services/TestScheduleService.php +++ b/tests/Services/TestScheduleService.php @@ -7,6 +7,7 @@ use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\Table; +use Indatus\Dispatcher\Queue; class TestScheduleService extends TestCase { @@ -19,7 +20,7 @@ public function setUp() { parent::setUp(); - $this->scheduleService = new ScheduleService(new Table()); + $this->scheduleService = new ScheduleService(new Table(), new Queue()); } public function tearDown() @@ -31,7 +32,7 @@ public function tearDown() public function testGetScheduledCommands() { $scheduledCommands = array($class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Schedulable')); + $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable')); })); Artisan::shouldReceive('all')->once()->andReturn($scheduledCommands); @@ -41,8 +42,9 @@ public function testGetScheduledCommands() public function testGetDueCommands() { - $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService[getScheduledCommands,isDue]', array( - new Table() + $scheduleService = m::mock('Indatus\Dispatcher\Services\ScheduleService[getScheduledCommands,isDue]', array( + new Table(), + new Queue() ), function ($m) { $m->shouldReceive('getScheduledCommands')->once() ->andReturn(array(m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'))); @@ -53,28 +55,4 @@ public function testGetDueCommands() $this->assertEquals(1, count($scheduleService->getDueCommands())); } - public function testIsNotDue() - { - $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { - //schedule the cron to run yesterday - $dateTime = new DateTime('yesterday'); - $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); - })); - }); - $scheduledCommand->shouldReceive('getName'); - $this->assertFalse($this->scheduleService->isDue($scheduledCommand)); - } - - public function testIsDue() - { - $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { - $m->shouldReceive('getSchedule')->once()->andReturn('* * * * *'); - })); - }); - $scheduledCommand->shouldReceive('getName'); - $this->assertTrue($this->scheduleService->isDue($scheduledCommand)); - } - } \ No newline at end of file diff --git a/tests/TestConfig.php b/tests/TestConfig.php index 68f9108..c4955a3 100644 --- a/tests/TestConfig.php +++ b/tests/TestConfig.php @@ -22,7 +22,7 @@ public function testDefaultDriver() public function testDefaultSchedulerClass() { - $serviceProvider = App::make('Indatus\Dispatcher\Schedulable'); + $serviceProvider = App::make('Indatus\Dispatcher\Scheduling\Schedulable'); $this->assertInstanceOf('Indatus\Dispatcher\Drivers\Cron\Scheduler', $serviceProvider); } From a7a50f6dc2d03b7f8c957c28e1946c76613510eb Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Mon, 7 Apr 2014 09:14:22 -0400 Subject: [PATCH 18/25] Commands can now be run and scheduled with arguments --- .../Dispatcher/BackgroundProcessRunner.php | 8 +- .../Drivers/Cron/ScheduleService.php | 37 +----- src/Indatus/Dispatcher/Queue.php | 10 +- .../Dispatcher/Scheduling/Schedulable.php | 2 + .../Scheduling/ScheduleException.php | 15 --- .../Dispatcher/Services/CommandService.php | 60 ++++++++- .../Dispatcher/Services/ScheduleService.php | 54 +++++--- .../Drivers/Cron/TestCronScheduleService.php | 52 ++------ .../Services/TestBackgroundProcessService.php | 118 ------------------ tests/Services/TestCommandService.php | 92 +++++++++++++- tests/Services/TestScheduleService.php | 48 +++++-- 11 files changed, 250 insertions(+), 246 deletions(-) delete mode 100644 src/Indatus/Dispatcher/Scheduling/ScheduleException.php delete mode 100644 tests/Services/TestBackgroundProcessService.php diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index ac9996a..a45f861 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -12,6 +12,7 @@ use App; use Indatus\Dispatcher\Scheduling\ScheduledCommand; use Indatus\Dispatcher\Services\CommandService; +use Symfony\Component\Process\Process; class BackgroundProcessRunner { @@ -29,12 +30,13 @@ public function __construct(CommandService $commandService) /** * Run a scheduled command * - * @param ScheduledCommand $scheduledCommand + * @param ScheduledCommand $scheduledCommand + * @param array $arguments * @return bool */ - public function run(ScheduledCommand $scheduledCommand) + public function run(ScheduledCommand $scheduledCommand, array $arguments = array()) { - exec($this->commandService->getRunCommand($scheduledCommand)); + exec($this->commandService->getRunCommand($scheduledCommand), $arguments); return true; } diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index 6ccbff7..86e709e 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -11,46 +11,21 @@ use App; use Cron\CronExpression; -use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; -use Indatus\Dispatcher\Scheduling\ScheduleException; use Indatus\Dispatcher\Scheduling\Schedulable; class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { /** - * Determine if a command is due to be run + * Determine if a schedule is due to be run + * + * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler * - * @param \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface $command - * @throws \Indatus\Dispatcher\Scheduling\ScheduleException * @return bool */ - public function isDue(ScheduledCommandInterface $command) + public function isDue(Schedulable $scheduler) { - $scheduler = App::make('Indatus\Dispatcher\Scheduling\Schedulable'); - $schedules = $command->schedule($scheduler); - if (!is_array($schedules)) { - $schedules = array($schedules); - } - foreach ($schedules as $schedule) { - if (($schedule instanceOf Schedulable) === false) { - throw new ScheduleException('Schedule for "'.$command->getName().'" is not an instance of Schedulable'); - } - - $cron = CronExpression::factory($schedule->getSchedule()); - if ($cron->isDue()) { - - //add to the queue so we can run it later - /** @var \Indatus\Dispatcher\QueueItem $queueItem */ - $queueItem = App::make('Indatus\Dispatcher\QueueItem'); - $queueItem->setCommand($command); - $queueItem->setScheduler($scheduler); - $this->queue->add($queueItem); - - return true; - } - } - - return false; + $cron = CronExpression::factory($scheduler->getSchedule()); + return $cron->isDue(); } /** diff --git a/src/Indatus/Dispatcher/Queue.php b/src/Indatus/Dispatcher/Queue.php index d7d1785..9760969 100644 --- a/src/Indatus/Dispatcher/Queue.php +++ b/src/Indatus/Dispatcher/Queue.php @@ -12,7 +12,7 @@ class Queue { /** @var QueueItem[] */ - protected static $queue = array(); + protected $queue = array(); /** * Add an item to the queue @@ -20,7 +20,7 @@ class Queue */ public function add(QueueItem $item) { - self::$queue[] = $item; + $this->queue[] = $item; } /** @@ -29,7 +29,7 @@ public function add(QueueItem $item) */ public function size() { - return count(self::$queue); + return count($this->queue); } /** @@ -38,8 +38,8 @@ public function size() */ public function flush() { - $queue = self::$queue; - self::$queue = array(); + $queue = $this->queue; + $this->queue = array(); return $queue; } diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index d11cacb..4411827 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -9,7 +9,9 @@ * file that was distributed with this source code. */ +use App; use Indatus\Dispatcher\ConfigResolver; +use Symfony\Component\Console\Input\ArgvInput; abstract class Schedulable { diff --git a/src/Indatus/Dispatcher/Scheduling/ScheduleException.php b/src/Indatus/Dispatcher/Scheduling/ScheduleException.php deleted file mode 100644 index efc8894..0000000 --- a/src/Indatus/Dispatcher/Scheduling/ScheduleException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class ScheduleException extends \Exception -{ - -} diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 5fac1c9..258df25 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -10,6 +10,7 @@ */ use App; +use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Scheduling\ScheduledCommand; class CommandService @@ -30,10 +31,16 @@ function __construct(ScheduleService $scheduleService) */ public function runDue() { + /** @var \Indatus\Dispatcher\BackgroundProcessRunner $backgroundProcessRunner */ $backgroundProcessRunner = App::make('Indatus\Dispatcher\BackgroundProcessRunner'); - foreach ($this->scheduleService->getDueCommands() as $command) { + + /** @var \Indatus\Dispatcher\Queue $queue */ + $queue = $this->scheduleService->getQueue(); + foreach ($queue->flush() as $queueItem) { + $command = $queueItem->getCommand(); + $scheduler = $queueItem->getScheduler(); if ($command->isEnabled() && $this->runnableInEnvironment($command)) { - $backgroundProcessRunner->run($command); + $backgroundProcessRunner->run($command, $scheduler->getArguments()); } } } @@ -61,23 +68,64 @@ public function runnableInEnvironment(ScheduledCommand $command) return false; } + /** + * Prepare a command's arguments for command line usage + * + * @param array $arguments + * + * @return string + */ + public function prepareArguments(array $arguments) + { + $argumentPieces = array(); + foreach ($arguments as $arg => $value) { + //if it's an array of options, throw them in there as well + if (is_array($value)) { + foreach ($value as $argArrayValue) { + $argumentPieces[] = '--'.$arg.'="'.addslashes($argArrayValue).'"'; + } + } else { + $argument = null; + + //option exists with no value + if (is_numeric($arg)) { + $argument = $value; + } elseif (!empty($value)) { + $argument = $arg.'="'.addslashes($value).'"'; + } + + if (!is_null($argument)) { + $argumentPieces[] = '--'.$argument; + } + } + } + + return implode(' ', $argumentPieces); + } + /** * Get a command to run this application * * @param \Indatus\Dispatcher\Scheduling\ScheduledCommand $scheduledCommand + * @param array $arguments * * @return string */ - public function getRunCommand(ScheduledCommand $scheduledCommand) + public function getRunCommand(ScheduledCommand $scheduledCommand, array $arguments = array()) { $commandPieces = array( 'php', base_path().'/artisan', - $scheduledCommand->getName(), - '&', //run in background - '> /dev/null 2>&1' //don't show output, errors can be viewed in the Laravel log + $scheduledCommand->getName() ); + if (count($arguments) > 0) { + $commandPieces[] = $this->prepareArguments($arguments); + } + + $commandPieces[] = '&'; //run in background + $commandPieces[] = '> /dev/null 2>&1'; //don't show output, errors can be viewed in the Laravel log + //run the command as a different user if (is_string($scheduledCommand->user())) { array_unshift($commandPieces, 'sudo -u '.$scheduledCommand->user()); diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 548862a..bc1144a 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -11,9 +11,11 @@ use App; use Artisan; -use Indatus\Dispatcher\Queue; +use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; +use Indatus\Dispatcher\Scheduling\ScheduleException; use Indatus\Dispatcher\Table; +use Symfony\Component\Process\Exception\InvalidArgumentException; abstract class ScheduleService { @@ -21,23 +23,19 @@ abstract class ScheduleService /** @var \Indatus\Dispatcher\Table */ protected $table; - /** @var \Indatus\Dispatcher\Queue */ - protected $queue; - - public function __construct(Table $table, Queue $queue) + public function __construct(Table $table) { $this->table = $table; - $this->queue = $queue; } /** * Determine if a command is due to be run * - * @param \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface $command + * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler * * @return bool */ - abstract public function isDue(ScheduledCommandInterface $command); + abstract public function isDue(Schedulable $scheduler); /** * Get all commands that are scheduled @@ -58,18 +56,44 @@ public function getScheduledCommands() /** * Get all commands that are due to be run - * - * @return \Indatus\Dispatcher\Scheduling\ScheduledCommand[] + * @throws \InvalidArgumentException + * @return \Indatus\Dispatcher\Queue */ - public function getDueCommands() + public function getQueue() { - $commands = array(); + /** @var \Indatus\Dispatcher\Queue $queue */ + $queue = App::make('Indatus\Dispatcher\Queue'); + + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $queue */ + $scheduler = App::make('Indatus\Dispatcher\Scheduling\Schedulable'); + foreach ($this->getScheduledCommands() as $command) { - if ($this->isDue($command)) { - $commands[] = $command; + + //could be multiple schedules based on arguments + $schedules = $command->schedule($scheduler); + if (!is_array($schedules)) { + $schedules = array($schedules); + } + + foreach ($schedules as $schedule) { + if (($schedule instanceOf Schedulable) === false) { + throw new \InvalidArgumentException('Schedule for "'.$command->getName().'" is not an instance of Schedulable'); + } + + if ($this->isDue($schedule)) { + + /** @var \Indatus\Dispatcher\QueueItem $queueItem */ + $queueItem = App::make('Indatus\Dispatcher\QueueItem'); + + $queueItem->setCommand($command); + $queueItem->setScheduler($scheduler); + + $queue->add($queueItem); + } } } - return $commands; + + return $queue; } /** diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index a247fa1..e0c94e4 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -18,8 +18,7 @@ public function setUp() parent::setUp(); $table = m::mock('Indatus\Dispatcher\Table'); - $queue = m::mock('Indatus\Dispatcher\Queue'); - $this->scheduleService = new ScheduleService($table, $queue); + $this->scheduleService = new ScheduleService($table); } public function tearDown() @@ -28,55 +27,22 @@ public function tearDown() m::close(); } - /** - * @expectedException \Indatus\Dispatcher\Scheduling\ScheduleException - */ - public function testIsDueException() - { - $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); - $command->shouldReceive('schedule')->once()->andReturnNull(); - $command->shouldReceive('getName')->once()->andReturn('testCommand'); - $this->scheduleService->isDue($command); - } - public function testIsNotDue() { - $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) { - $m->shouldReceive('schedule')->andReturn(m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { - //schedule the cron to run yesterday - $dateTime = new DateTime('yesterday'); - $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); - })); - }); - $scheduledCommand->shouldReceive('getName'); - $this->assertFalse($this->scheduleService->isDue($scheduledCommand)); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { + //schedule the cron to run yesterday + $dateTime = new DateTime('yesterday'); + $m->shouldReceive('getSchedule')->once()->andReturn('* * * * '.$dateTime->format('N')); + }); + $this->assertFalse($this->scheduleService->isDue($scheduler)); } public function testIsDue() { - $scheduler = m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { $m->shouldReceive('getSchedule')->once()->andReturn('* * * * *'); }); - App::shouldReceive('make')->with('Indatus\Dispatcher\Scheduling\Schedulable') - ->andReturn($scheduler); - - $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($scheduler) { - $m->shouldReceive('schedule')->andReturn($scheduler); - }); - $scheduledCommand->shouldReceive('getName'); - - $queueItem = m::mock('Indatus\Dispatcher\QueueItem'); - $queueItem->shouldReceive('setCommand')->with($scheduledCommand)->once(); - $queueItem->shouldReceive('setScheduler')->with($scheduler)->once(); - App::shouldReceive('make')->with('Indatus\Dispatcher\QueueItem') - ->andReturn($queueItem); - - $table = m::mock('Indatus\Dispatcher\Table'); - $queue = m::mock('Indatus\Dispatcher\Queue'); - $queue->shouldReceive('add')->with($queueItem)->once(); - $scheduleService = new ScheduleService($table, $queue); - - $this->assertTrue($scheduleService->isDue($scheduledCommand)); + $this->assertTrue($this->scheduleService->isDue($scheduler)); } /** diff --git a/tests/Services/TestBackgroundProcessService.php b/tests/Services/TestBackgroundProcessService.php deleted file mode 100644 index 1d69132..0000000 --- a/tests/Services/TestBackgroundProcessService.php +++ /dev/null @@ -1,118 +0,0 @@ - - */ - -use Mockery as m; -use Indatus\Dispatcher\Services\CommandService; -use Indatus\Dispatcher\Drivers\Cron\ScheduleService; -use Indatus\Dispatcher\Table; -use Indatus\Dispatcher\Scheduler; -use Indatus\Dispatcher\Queue; - -class BackgroundProcessService extends TestCase -{ - /** - * @var Indatus\Dispatcher\Services\CommandService - */ - private $commandService; - - public function setUp() - { - parent::setUp(); - - $scheduleService = new ScheduleService(new Table(), new Queue()); - $this->commandService = new CommandService($scheduleService); - - } - - public function tearDown() - { - parent::tearDown(); - m::close(); - } - - public function testRunDue() - { - $scheduledCommand = $this->mockCommand(); - $scheduledCommand->shouldReceive('isEnabled')->once()->andReturn(true); - $scheduledCommand->shouldReceive('getName')->once()->andReturn('test:command'); - $scheduledCommand->shouldReceive('user')->once()->andReturn(false); - - $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService'); - $scheduleService->shouldReceive('getDueCommands')->once()->andReturn(array($scheduledCommand)); - $this->app->instance('Indatus\Dispatcher\Services\ScheduleService', $scheduleService); - - $commandService = m::mock('Indatus\Dispatcher\Services\CommandService[runnableInEnvironment,run]', - array($scheduleService), - function ($m) { - $m->shouldReceive('runnableInEnvironment')->andReturn(true); - $m->shouldReceive('run')->andReturnNull(); - }); - - $this->assertNull($commandService->runDue()); - } - - public function testRunnableInAnyEnvironment() - { - $scheduledCommand = $this->mockCommand('*'); - - App::shouldReceive('environment')->andReturn('*'); - $this->assertTrue($this->commandService->runnableInEnvironment($scheduledCommand)); - } - - public function testRunnableInOneEnvironment() - { - $scheduledCommand = $this->mockCommand('local'); - - App::shouldReceive('environment')->andReturn('local'); - $this->assertTrue($this->commandService->runnableInEnvironment($scheduledCommand)); - } - - public function testRunnableInMultipleEnvironments() - { - $scheduledCommand = $this->mockCommand(array('local', 'development')); - - App::shouldReceive('environment')->andReturn('local'); - $this->assertTrue($this->commandService->runnableInEnvironment($scheduledCommand)); - } - - public function testGetRunCommand() - { - $commandName = 'test:command'; - $scheduledCommand = $this->mockCommand(); - $scheduledCommand->shouldReceive('getName')->andReturn($commandName); - $scheduledCommand->shouldReceive('user')->andReturn(false); - $this->assertEquals($this->commandService->getRunCommand($scheduledCommand), implode(' ', array( - 'php', - base_path().'/artisan', - $commandName, - '&', - '> /dev/null 2>&1' - ))); - } - public function testGetRunCommandAsUser() - { - $user = 'myUser'; - $commandName = 'test:command'; - $scheduledCommand = $this->mockCommand(); - $scheduledCommand->shouldReceive('getName')->andReturn($commandName); - $scheduledCommand->shouldReceive('user')->andReturn($user); - $this->assertEquals($this->commandService->getRunCommand($scheduledCommand), implode(' ', array( - 'sudo -u '.$user, - 'php', - base_path().'/artisan', - $commandName, - '&', - '> /dev/null 2>&1' - ))); - } - - private function mockCommand ($environment = '*') - { - return $class = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($environment) { - $m->shouldReceive('environment')->andReturn($environment); - }); - } - -} \ No newline at end of file diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index 4606fe6..8601101 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -39,15 +39,24 @@ public function testRunDue() $scheduledCommand->shouldReceive('getName')->once()->andReturn('test:command'); $scheduledCommand->shouldReceive('user')->once()->andReturn(false); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable'); + $scheduler->shouldReceive('getArguments')->once()->andReturn(array()); + $queue = m::mock('Indatus\Dispatcher\Queue', + function ($m) use ($scheduledCommand, $scheduler) { + $item = m::mock('Indatus\Dispatcher\QueueItem'); + $item->shouldReceive('getCommand')->once()->andReturn($scheduledCommand); + $item->shouldReceive('getScheduler')->once()->andReturn($scheduler); + $m->shouldReceive('flush')->once()->andReturn(array($item)); + }); $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService'); - $scheduleService->shouldReceive('getDueCommands')->once()->andReturn(array($scheduledCommand)); + $scheduleService->shouldReceive('getQueue')->once()->andReturn($queue); $this->app->instance('Indatus\Dispatcher\Services\ScheduleService', $scheduleService); $commandService = m::mock('Indatus\Dispatcher\Services\CommandService[runnableInEnvironment,run]', array($scheduleService), - function ($m) { + function ($m) use ($scheduledCommand, $scheduler) { $m->shouldReceive('runnableInEnvironment')->andReturn(true); - $m->shouldReceive('run')->andReturnNull(); + $m->shouldReceive('run')->with($scheduledCommand, $scheduler)->andReturnNull(); }); $this->assertNull($commandService->runDue()); @@ -85,6 +94,59 @@ public function testNotRunnableInEnvironment() $this->assertFalse($this->commandService->runnableInEnvironment($scheduledCommand)); } + public function testPrepareArguments() + { + $arguments = array( + 'test' => 'argument' + ); + $commandService = $this->getMockForAbstractClass('Indatus\Dispatcher\Services\CommandService', + array( + m::mock('Indatus\Dispatcher\Services\ScheduleService') + )); + + $this->assertEquals( + '--test="argument"', + $commandService->prepareArguments($arguments) + ); + } + + public function testPrepareArgumentsKeyOnly() + { + $arguments = array( + 'test' => 'argument', + 'keyOnly' + ); + $commandService = $this->getMockForAbstractClass('Indatus\Dispatcher\Services\CommandService', + array( + m::mock('Indatus\Dispatcher\Services\ScheduleService') + )); + + $this->assertEquals( + '--test="argument" --keyOnly', + $commandService->prepareArguments($arguments) + ); + } + + public function testPrepareArgumentsArrayValue() + { + $arguments = array( + 'test' => 'argument', + 'option' => array( + 'value1', + 'value2' + ) + ); + $commandService = $this->getMockForAbstractClass('Indatus\Dispatcher\Services\CommandService', + array( + m::mock('Indatus\Dispatcher\Services\ScheduleService') + )); + + $this->assertEquals( + '--test="argument" --option="value1" --option="value2"', + $commandService->prepareArguments($arguments) + ); + } + public function testGetRunCommand() { $commandName = 'test:command'; @@ -99,6 +161,30 @@ public function testGetRunCommand() '> /dev/null 2>&1' ))); } + + public function testGetRunCommandWithArguments() + { + $commandName = 'test:command'; + $scheduledCommand = $this->mockCommand(); + $scheduledCommand->shouldReceive('getName')->andReturn($commandName); + $scheduledCommand->shouldReceive('user')->andReturn(false); + $this->assertEquals( + $this->commandService->getRunCommand( + $scheduledCommand, + array( + 'option' => 'value' + ) + ), + implode(' ', array( + 'php', + base_path().'/artisan', + $commandName, + '--option="value"', + '&', + '> /dev/null 2>&1' + ))); + } + public function testGetRunCommandAsUser() { $user = 'myUser'; diff --git a/tests/Services/TestScheduleService.php b/tests/Services/TestScheduleService.php index 2d583b5..61929f1 100644 --- a/tests/Services/TestScheduleService.php +++ b/tests/Services/TestScheduleService.php @@ -20,7 +20,7 @@ public function setUp() { parent::setUp(); - $this->scheduleService = new ScheduleService(new Table(), new Queue()); + $this->scheduleService = new ScheduleService(new Table()); } public function tearDown() @@ -40,19 +40,53 @@ public function testGetScheduledCommands() $this->assertSameSize($scheduledCommands, $this->scheduleService->getScheduledCommands()); } - public function testGetDueCommands() + public function testGetQueue() { $scheduleService = m::mock('Indatus\Dispatcher\Services\ScheduleService[getScheduledCommands,isDue]', array( - new Table(), - new Queue() + new Table() ), function ($m) { + $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable'); + $command->shouldReceive('schedule')->once() + ->andReturn($scheduler); + $m->shouldReceive('getScheduledCommands')->once() - ->andReturn(array(m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'))); - $m->shouldReceive('isDue')->once()->andReturn(true); + ->andReturn(array($command)); + $m->shouldReceive('isDue')->once()->with($scheduler) + ->andReturn(true); + + }); + + $queue = $scheduleService->getQueue(); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Queue', + $queue + ); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testGetQueueException() + { + $scheduleService = m::mock('Indatus\Dispatcher\Services\ScheduleService[getScheduledCommands,isDue]', array( + new Table() + ), function ($m) { + $command = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand'); + $command->shouldReceive('schedule')->once() + ->andReturn(array(1)); + $command->shouldReceive('getName')->once() + ->andReturn('asdf'); + $m->shouldReceive('getScheduledCommands')->once() + ->andReturn(array($command)); }); - $this->assertEquals(1, count($scheduleService->getDueCommands())); + $queue = $scheduleService->getQueue(); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Queue', + $queue + ); } } \ No newline at end of file From ff30b0e89f7929f9362a5e887aae57aa43bdba31 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Mon, 7 Apr 2014 23:27:04 -0400 Subject: [PATCH 19/25] Resolved dependency issue --- src/Indatus/Dispatcher/ConfigResolver.php | 42 +++++++++++++----- .../Dispatcher/Drivers/Cron/Scheduler.php | 3 +- .../Dispatcher/Scheduling/Schedulable.php | 24 ++++++++-- src/Indatus/Dispatcher/ServiceProvider.php | 6 +-- tests/Drivers/Cron/TestCronScheduler.php | 4 +- tests/Scheduling/TestSchedulable.php | 44 ------------------- tests/TestConfigResolver.php | 32 ++++++++------ 7 files changed, 76 insertions(+), 79 deletions(-) delete mode 100644 tests/Scheduling/TestSchedulable.php diff --git a/src/Indatus/Dispatcher/ConfigResolver.php b/src/Indatus/Dispatcher/ConfigResolver.php index 839ac47..4f98fd7 100644 --- a/src/Indatus/Dispatcher/ConfigResolver.php +++ b/src/Indatus/Dispatcher/ConfigResolver.php @@ -18,29 +18,47 @@ class ConfigResolver /** * Resolve a class based on the driver configuration * - * @param $className - * @param array $arguments - * - * @return mixed + * @return \Indatus\Dispatcher\Scheduling\Schedulable */ - public function resolveDriverClass($className, $arguments = array()) + public function resolveSchedulerClass() { try { return App::make( - Config::get('dispatcher::driver').'\\'.$className, array( - $this, - $arguments + Config::get('dispatcher::driver').'\\Scheduler', array( + $this ) ); } catch (\ReflectionException $e) { - $driver = ucwords(strtolower(Config::get('dispatcher::driver'))); return App::make( - 'Indatus\Dispatcher\Drivers\\'.$driver.'\\'.$className, array( - $this, - $arguments + 'Indatus\Dispatcher\Drivers\\'.$this->getDriver().'\\Scheduler', array( + $this ) ); } } + /** + * Resolve a class based on the driver configuration + * + * @return \Indatus\Dispatcher\Scheduling\ScheduleService + */ + public function resolveServiceClass() + { + try { + return App::make(Config::get('dispatcher::driver').'\\ScheduleService'); + } catch (\ReflectionException $e) { + return App::make('Indatus\Dispatcher\Drivers\\'.$this->getDriver().'\\ScheduleService'); + } + } + + /** + * Get the dispatcher driver class + * + * @return string + */ + public function getDriver() + { + return ucwords(strtolower(Config::get('dispatcher::driver'))); + } + } diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index 32ee4b1..66acff0 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -291,7 +291,8 @@ public function args(array $arguments) } /** - * @todo This is a terrible method name + * If an array of values is used, convert it + * to a comma separated value. */ private function parseTimeParameter($parameter) { diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index 4411827..363acd8 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -15,14 +15,15 @@ abstract class Schedulable { + /** @var \Indatus\Dispatcher\ConfigResolver $configResolver */ protected $configResolver; - protected $arguments; + /** @var array $arguments */ + protected $arguments = array(); - public function __construct(ConfigResolver $configResolver, $arguments = array()) + public function __construct(ConfigResolver $configResolver) { $this->configResolver = $configResolver; - $this->arguments = $arguments; } /** @@ -34,7 +35,10 @@ public function __construct(ConfigResolver $configResolver, $arguments = array() */ public function args(array $arguments) { - return $this->configResolver->resolveDriverClass('Scheduler', $arguments); + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ + $scheduler = $this->configResolver->resolveSchedulerClass(); + $scheduler->setArguments($arguments); + return $scheduler; } /** @@ -46,4 +50,16 @@ public function getArguments() { return $this->arguments; } + + /** + * Set the schedule's arguments + * + * This method is only to be used internally by Dispatcher. + * + * @param array $arguments + */ + public function setArguments($arguments) + { + $this->arguments = $arguments; + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/ServiceProvider.php b/src/Indatus/Dispatcher/ServiceProvider.php index af65395..4733077 100644 --- a/src/Indatus/Dispatcher/ServiceProvider.php +++ b/src/Indatus/Dispatcher/ServiceProvider.php @@ -44,12 +44,12 @@ public function register() //load the scheduler of the appropriate driver App::bind('Indatus\Dispatcher\Scheduling\Schedulable', function () use ($resolver) { - return $resolver->resolveDriverClass('Scheduler'); + return $resolver->resolveSchedulerClass(); }); - //load the scheduler of the appropriate driver + //load the schedule service of the appropriate driver App::bind('Indatus\Dispatcher\Services\ScheduleService', function () use ($resolver) { - return $resolver->resolveDriverClass('ScheduleService'); + return $resolver->resolveServiceClass(); }); $this->registerCommands(); diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index 4c2fb62..f2dfd9f 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -8,7 +8,7 @@ class TestCronScheduler extends TestCase { /** - * @var Indatus\Dispatcher\Scheduler + * @var Indatus\Dispatcher\Drivers\Cron\Scheduler */ private $scheduler; @@ -150,7 +150,7 @@ public function testArgs() { $args = array('testArgument'); - /** @var \Indatus\Dispatcher\Scheduleable $scheduler */ + /** @var \Indatus\Dispatcher\Drivers\Cron\Scheduler $scheduler */ $scheduler = $this->scheduler->args($args); $this->assertInstanceOf($this->schedularClass, $scheduler); $this->assertEquals($args, $scheduler->getArguments()); diff --git a/tests/Scheduling/TestSchedulable.php b/tests/Scheduling/TestSchedulable.php deleted file mode 100644 index cf8b506..0000000 --- a/tests/Scheduling/TestSchedulable.php +++ /dev/null @@ -1,44 +0,0 @@ - - */ - -use Mockery as m; -use Indatus\Dispatcher\BackgroundProcess; - -class TestSchedulable extends TestCase -{ - - public function tearDown() - { - parent::tearDown(); - m::close(); - } - - public function testArguments() - { - $args = ['type' => 'scheduled']; - /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduleable */ - $scheduleable = $this->getMockForAbstractClass( - 'Indatus\Dispatcher\Scheduling\Schedulable', array( - App::make('Indatus\Dispatcher\ConfigResolver') - )); - $newScheduleable = $scheduleable->args($args); - $this->assertEquals($args, $newScheduleable->getArguments()); - } - - public function testArgumentsConstructor() - { - $args = ['type' => 'scheduled']; - - /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduleable */ - $scheduleable = $this->getMockForAbstractClass( - 'Indatus\Dispatcher\Scheduling\Schedulable', array( - App::make('Indatus\Dispatcher\ConfigResolver'), - $args - ) - ); - - $this->assertEquals($args, $scheduleable->getArguments()); - } -} \ No newline at end of file diff --git a/tests/TestConfigResolver.php b/tests/TestConfigResolver.php index 50dd8c6..70a32d4 100644 --- a/tests/TestConfigResolver.php +++ b/tests/TestConfigResolver.php @@ -16,35 +16,41 @@ public function tearDown() m::close(); } - public function testLoadingPackagedDriver() + public function testLoadingSchedulerPackagedDriver() { $resolver = new ConfigResolver(); $this->assertInstanceOf( 'Indatus\Dispatcher\Drivers\Cron\Scheduler', - $resolver->resolveDriverClass('Scheduler') + $resolver->resolveSchedulerClass() ); } - public function testLoadingPackagedDriverWithArguments() + public function testLoadingServiceCustomDriver() { - $args = array('testArgument'); + Config::shouldReceive('get')->andReturn('cron'); $resolver = new ConfigResolver(); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Scheduling\Schedulable', + $resolver->resolveSchedulerClass() + ); + } - /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ - $scheduler = $resolver->resolveDriverClass('Scheduler', $args); - $this->assertEquals( - $args, - $scheduler->getArguments() + public function testLoadingServicePackagedDriver() + { + $resolver = new ConfigResolver(); + $this->assertInstanceOf( + 'Indatus\Dispatcher\Services\ScheduleService', + $resolver->resolveServiceClass() ); } - public function testLoadingCustomDriver() + public function testLoadingSchedulerCustomDriver() { - Config::shouldReceive('get')->andReturn('Indatus\Dispatcher\Drivers\Cron'); + Config::shouldReceive('get')->andReturn('cron'); $resolver = new ConfigResolver(); $this->assertInstanceOf( - 'Indatus\Dispatcher\Scheduling\Schedulable', - $resolver->resolveDriverClass('Scheduler') + 'Indatus\Dispatcher\Services\ScheduleService', + $resolver->resolveServiceClass() ); } From b350a553fc71396967077085b0ee4c20b9c1887b Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Tue, 8 Apr 2014 20:49:46 -0400 Subject: [PATCH 20/25] Commands can now be scheduled with arguments and options --- .../Dispatcher/BackgroundProcessRunner.php | 10 ++- .../Drivers/Cron/ScheduleService.php | 87 +++++++++++++++---- .../Dispatcher/Drivers/Cron/Scheduler.php | 9 ++ .../Dispatcher/Scheduling/Schedulable.php | 62 ++++++++++++- .../Scheduling/ScheduledCommandInterface.php | 1 - .../Dispatcher/Services/CommandService.php | 45 +++++++--- .../Dispatcher/Services/ScheduleService.php | 2 +- .../Drivers/Cron/TestCronScheduleService.php | 51 +++++++++-- tests/Drivers/Cron/TestCronScheduler.php | 17 ++++ tests/Services/TestCommandService.php | 40 +++++++-- 10 files changed, 271 insertions(+), 53 deletions(-) diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index a45f861..bdf3281 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -32,11 +32,15 @@ public function __construct(CommandService $commandService) * * @param ScheduledCommand $scheduledCommand * @param array $arguments + * @param array $options * @return bool */ - public function run(ScheduledCommand $scheduledCommand, array $arguments = array()) - { - exec($this->commandService->getRunCommand($scheduledCommand), $arguments); + public function run( + ScheduledCommand $scheduledCommand, + array $arguments = array(), + array $options = array() + ) { + exec($this->commandService->getRunCommand($scheduledCommand, $arguments, $options)); return true; } diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index 86e709e..9657637 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -12,20 +12,28 @@ use App; use Cron\CronExpression; use Indatus\Dispatcher\Scheduling\Schedulable; +use Indatus\Dispatcher\Scheduling\ScheduledCommandInterface; +use Log; class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { /** * Determine if a schedule is due to be run * - * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler + * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler * * @return bool */ public function isDue(Schedulable $scheduler) { - $cron = CronExpression::factory($scheduler->getSchedule()); - return $cron->isDue(); + try { + $cron = CronExpression::factory($scheduler->getSchedule()); + return $cron->isDue(); + } catch (\Exception $e) { + Log::error($e->getMessage()); + } + + return false; } /** @@ -33,27 +41,72 @@ public function isDue(Schedulable $scheduler) */ public function printSummary() { - $this->table->setHeaders(array('Environment(s)', 'Name', 'Minute', 'Hour', 'Day of Month', 'Month', 'Day of Week', 'Run as')); + $this->table->setHeaders(array('Environment(s)', 'Name', 'Args/Opts', 'Minute', 'Hour', 'Day of Month', 'Month', 'Day of Week', 'Run as')); /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ foreach ($this->getScheduledCommands() as $command) { /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Scheduling\Schedulable')); - $this->table->addRow(array( - is_array($command->environment()) ? implode(',', $command->environment()) : $command->environment(), - $command->getName(), - $scheduler->getScheduleMinute(), - $scheduler->getScheduleHour(), - $scheduler->getScheduleDayOfMonth(), - $scheduler->getScheduleMonth(), - $scheduler->getScheduleDayOfWeek(), - $command->user() - )); + //if there's only one schedule, print just the command + if (!is_array($scheduler)) { + $this->printCommand($command, $scheduler); + } else { + if ($this->printCommandLabel($command)) { + foreach ($scheduler as $schedule) { + $this->printSchedule($command, $schedule); + } + } + } } - //sort by first column - $this->table->sort(0); - $this->table->display(); } + + protected function printCommand(ScheduledCommandInterface $command, Schedulable $scheduler) + { + $this->table->addRow(array( + is_array($command->environment()) ? implode(',', $command->environment()) : $command->environment(), + $command->getName(), + '', + $scheduler->getScheduleMinute(), + $scheduler->getScheduleHour(), + $scheduler->getScheduleDayOfMonth(), + $scheduler->getScheduleMonth(), + $scheduler->getScheduleDayOfWeek(), + $command->user() + )); + } + + protected function printCommandLabel(ScheduledCommandInterface $command) + { + $this->table->addRow(array( + is_array($command->environment()) ? implode(',', $command->environment()) : $command->environment(), + $command->getName(), + '', + '', + '', + '', + '', + '', + $command->user() + )); + return true; + } + + protected function printSchedule(ScheduledCommandInterface $command, Schedulable $scheduler) + { + $commandService = App::make('Indatus\Dispatcher\Services\CommandService'); + + $this->table->addRow(array( + '', + '', + trim($commandService->prepareArguments($scheduler->getArguments()).' '.$commandService->prepareOptions($scheduler->getOptions())), + $scheduler->getScheduleMinute(), + $scheduler->getScheduleHour(), + $scheduler->getScheduleDayOfMonth(), + $scheduler->getScheduleMonth(), + $scheduler->getScheduleDayOfWeek(), + '' + )); + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index 66acff0..5fbcc0c 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -290,6 +290,15 @@ public function args(array $arguments) return parent::args($arguments); } + /** + * @inheritDoc + * @return $this + */ + public function opts(array $options) + { + return parent::opts($options); + } + /** * If an array of values is used, convert it * to a comma separated value. diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index 363acd8..0213c44 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -21,6 +21,12 @@ abstract class Schedulable /** @var array $arguments */ protected $arguments = array(); + /** @var array $options */ + protected $options = array(); + + /** @var bool Instantiate a new instance when using args() or opts() */ + protected $instantiateNew = true; + public function __construct(ConfigResolver $configResolver) { $this->configResolver = $configResolver; @@ -35,8 +41,7 @@ public function __construct(ConfigResolver $configResolver) */ public function args(array $arguments) { - /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ - $scheduler = $this->configResolver->resolveSchedulerClass(); + $scheduler = $this->getClass(); $scheduler->setArguments($arguments); return $scheduler; } @@ -62,4 +67,57 @@ public function setArguments($arguments) { $this->arguments = $arguments; } + + /** + * Define options for this command when it runs. + * + * @param array $options + * + * @return \Indatus\Dispatcher\Scheduling\Schedulable + */ + public function opts(array $options) + { + $scheduler = $this->getClass(); + $scheduler->setOptions($options); + return $scheduler; + } + + /** + * Get the options for this command. + * + * @return array + */ + public function getOptions() + { + return $this->options; + } + + /** + * Set the schedule's options + * + * This method is only to be used internally by Dispatcher. + * + * @param array $options + */ + public function setOptions($options) + { + $this->options = $options; + } + + /** + * Get a scheduler class + * + * @return $this|Schedulable + */ + public function getClass() + { + //use the existing one if we've already instantiated + if ($this->instantiateNew === false) { + return $this; + } + + $this->instantiateNew = false; + + return $this; + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php b/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php index 7af20da..279f952 100644 --- a/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php +++ b/src/Indatus/Dispatcher/Scheduling/ScheduledCommandInterface.php @@ -5,7 +5,6 @@ */ use Indatus\Dispatcher\Scheduler; -use Indatus\Dispatcher\Scheduling\Schedulable; interface ScheduledCommandInterface { diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 258df25..46f7686 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -10,7 +10,6 @@ */ use App; -use Indatus\Dispatcher\Scheduling\Schedulable; use Indatus\Dispatcher\Scheduling\ScheduledCommand; class CommandService @@ -77,30 +76,42 @@ public function runnableInEnvironment(ScheduledCommand $command) */ public function prepareArguments(array $arguments) { - $argumentPieces = array(); - foreach ($arguments as $arg => $value) { + return implode(' ', $arguments); + } + + /** + * Prepare a command's options for command line usage + * + * @param array $options + * + * @return string + */ + public function prepareOptions(array $options) + { + $optionPieces = array(); + foreach ($options as $opt => $value) { //if it's an array of options, throw them in there as well if (is_array($value)) { - foreach ($value as $argArrayValue) { - $argumentPieces[] = '--'.$arg.'="'.addslashes($argArrayValue).'"'; + foreach ($value as $optArrayValue) { + $optionPieces[] = '--'.$opt.'="'.addslashes($optArrayValue).'"'; } } else { - $argument = null; + $option = null; //option exists with no value - if (is_numeric($arg)) { - $argument = $value; + if (is_numeric($opt)) { + $option = $value; } elseif (!empty($value)) { - $argument = $arg.'="'.addslashes($value).'"'; + $option = $opt.'="'.addslashes($value).'"'; } - if (!is_null($argument)) { - $argumentPieces[] = '--'.$argument; + if (!is_null($option)) { + $optionPieces[] = '--'.$option; } } } - return implode(' ', $argumentPieces); + return implode(' ', $optionPieces); } /** @@ -108,10 +119,14 @@ public function prepareArguments(array $arguments) * * @param \Indatus\Dispatcher\Scheduling\ScheduledCommand $scheduledCommand * @param array $arguments + * @param array $options * * @return string */ - public function getRunCommand(ScheduledCommand $scheduledCommand, array $arguments = array()) + public function getRunCommand( + ScheduledCommand $scheduledCommand, + array $arguments = array(), + array $options = array()) { $commandPieces = array( 'php', @@ -123,6 +138,10 @@ public function getRunCommand(ScheduledCommand $scheduledCommand, array $argumen $commandPieces[] = $this->prepareArguments($arguments); } + if (count($options) > 0) { + $commandPieces[] = $this->prepareOptions($options); + } + $commandPieces[] = '&'; //run in background $commandPieces[] = '> /dev/null 2>&1'; //don't show output, errors can be viewed in the Laravel log diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index bc1144a..21d128f 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -20,7 +20,7 @@ abstract class ScheduleService { - /** @var \Indatus\Dispatcher\Table */ + /** @var \Indatus\Dispatcher\Table */ protected $table; public function __construct(Table $table) diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index e0c94e4..db430b9 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -37,6 +37,15 @@ public function testIsNotDue() $this->assertFalse($this->scheduleService->isDue($scheduler)); } + public function testIsDueException() + { + Log::shouldReceive('error')->once(); + $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { + $m->shouldReceive('getSchedule')->once()->andReturn('asdf'); + }); + $this->assertFalse($this->scheduleService->isDue($scheduler)); + } + public function testIsDue() { $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable', function ($m) { @@ -53,7 +62,6 @@ public function testPrintSummary() { $table = m::mock('Indatus\Dispatcher\Table', function ($m) { $m->shouldReceive('setHeaders')->once(); - $m->shouldReceive('sort')->once(); $m->shouldReceive('display')->once(); }); $queue = m::mock('Indatus\Dispatcher\Queue', function ($m) { @@ -61,25 +69,50 @@ public function testPrintSummary() $m->shouldReceive('sort')->once(); $m->shouldReceive('display')->once();*/ }); + + $scheduledCommandWithMultipleSchedulers = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { + $table->shouldReceive('addRow')->times(3); + + $scheduler = m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { + $m->shouldReceive('getScheduleMinute'); + $m->shouldReceive('getScheduleHour'); + $m->shouldReceive('getScheduleDayOfMonth'); + $m->shouldReceive('getScheduleMonth'); + $m->shouldReceive('getScheduleDayOfWeek'); + $m->shouldReceive('getArguments')->twice()->andReturn(array()); + $m->shouldReceive('getOptions')->twice()->andReturn(array()); + }); + + $m->shouldReceive('getName')->once(); + $m->shouldReceive('user')->once(); + $m->shouldReceive('environment')->twice(); + $m->shouldReceive('schedule')->once()->andReturn([ + $scheduler, + $scheduler + ]); + }); $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { $table->shouldReceive('addRow')->once(); + $scheduler = m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { + $m->shouldReceive('getScheduleMinute'); + $m->shouldReceive('getScheduleHour'); + $m->shouldReceive('getScheduleDayOfMonth'); + $m->shouldReceive('getScheduleMonth'); + $m->shouldReceive('getScheduleDayOfWeek'); + }); + $m->shouldReceive('getName')->once(); $m->shouldReceive('user')->once(); $m->shouldReceive('environment')->twice(); - $m->shouldReceive('schedule')->once()->andReturn(m::mock('Indatus\Dispatcher\Drivers\Cron\Scheduler', function ($m) { - $m->shouldReceive('getScheduleMinute'); - $m->shouldReceive('getScheduleHour'); - $m->shouldReceive('getScheduleDayOfMonth'); - $m->shouldReceive('getScheduleMonth'); - $m->shouldReceive('getScheduleDayOfWeek'); - })); + $m->shouldReceive('schedule')->once()->andReturn($scheduler); }); $scheduleService = m::mock('Indatus\Dispatcher\Drivers\Cron\ScheduleService[getScheduledCommands]', array( $table, $queue - ), function ($m) use ($scheduledCommand) { + ), function ($m) use ($scheduledCommand, $scheduledCommandWithMultipleSchedulers) { $m->shouldReceive('getScheduledCommands')->once()->andReturn(array( + $scheduledCommandWithMultipleSchedulers, $scheduledCommand )); }); diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index f2dfd9f..133bc17 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -156,4 +156,21 @@ public function testArgs() $this->assertEquals($args, $scheduler->getArguments()); } + public function testOpts() + { + $opts = array( + 'testOpt', + 'option' => 'value' + ); + $args = array( + 'testArgument' + ); + + /** @var \Indatus\Dispatcher\Drivers\Cron\Scheduler $scheduler */ + $scheduler = $this->scheduler->args($args)->opts($opts); + $this->assertInstanceOf($this->schedularClass, $scheduler); + $this->assertEquals($args, $scheduler->getArguments()); + $this->assertEquals($opts, $scheduler->getOptions()); + } + } \ No newline at end of file diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index 8601101..f314f4f 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -97,7 +97,7 @@ public function testNotRunnableInEnvironment() public function testPrepareArguments() { $arguments = array( - 'test' => 'argument' + 'argument' ); $commandService = $this->getMockForAbstractClass('Indatus\Dispatcher\Services\CommandService', array( @@ -105,12 +105,12 @@ public function testPrepareArguments() )); $this->assertEquals( - '--test="argument"', + 'argument', $commandService->prepareArguments($arguments) ); } - public function testPrepareArgumentsKeyOnly() + public function testPrepareOptions() { $arguments = array( 'test' => 'argument', @@ -123,11 +123,11 @@ public function testPrepareArgumentsKeyOnly() $this->assertEquals( '--test="argument" --keyOnly', - $commandService->prepareArguments($arguments) + $commandService->prepareOptions($arguments) ); } - public function testPrepareArgumentsArrayValue() + public function testPrepareOptionsArrayValue() { $arguments = array( 'test' => 'argument', @@ -143,7 +143,7 @@ public function testPrepareArgumentsArrayValue() $this->assertEquals( '--test="argument" --option="value1" --option="value2"', - $commandService->prepareArguments($arguments) + $commandService->prepareOptions($arguments) ); } @@ -172,7 +172,32 @@ public function testGetRunCommandWithArguments() $this->commandService->getRunCommand( $scheduledCommand, array( - 'option' => 'value' + 'option' + ) + ), + implode(' ', array( + 'php', + base_path().'/artisan', + $commandName, + 'option', + '&', + '> /dev/null 2>&1' + ))); + } + + public function testGetRunCommandWithOptions() + { + $commandName = 'test:command'; + $scheduledCommand = $this->mockCommand(); + $scheduledCommand->shouldReceive('getName')->andReturn($commandName); + $scheduledCommand->shouldReceive('user')->andReturn(false); + $this->assertEquals( + $this->commandService->getRunCommand( + $scheduledCommand, + array(), + array( + 'option' => 'value', + 'anotherOption' ) ), implode(' ', array( @@ -180,6 +205,7 @@ public function testGetRunCommandWithArguments() base_path().'/artisan', $commandName, '--option="value"', + '--anotherOption', '&', '> /dev/null 2>&1' ))); From 571c4c81857278d412e3d219c3c36591fbcc4705 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Tue, 8 Apr 2014 21:59:30 -0400 Subject: [PATCH 21/25] Options are now properly passed to the command --- .../Dispatcher/BackgroundProcessRunner.php | 1 + src/Indatus/Dispatcher/Commands/Run.php | 1 + .../Dispatcher/Scheduling/Schedulable.php | 34 +++++++++++-------- .../Dispatcher/Services/CommandService.php | 8 +++-- .../Dispatcher/Services/ScheduleService.php | 2 +- tests/Drivers/Cron/TestCronScheduler.php | 6 ++++ 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index bdf3281..f4a77ba 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -40,6 +40,7 @@ public function run( array $arguments = array(), array $options = array() ) { + \Log::debug($scheduledCommand->getName(), [$this->commandService->getRunCommand($scheduledCommand, $arguments, $options)]); exec($this->commandService->getRunCommand($scheduledCommand, $arguments, $options)); return true; diff --git a/src/Indatus/Dispatcher/Commands/Run.php b/src/Indatus/Dispatcher/Commands/Run.php index 800a1b9..d6c67ec 100644 --- a/src/Indatus/Dispatcher/Commands/Run.php +++ b/src/Indatus/Dispatcher/Commands/Run.php @@ -50,6 +50,7 @@ public function __construct(CommandService $commandService) */ public function fire() { + $this->commandService->runDue(); } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index 0213c44..206e6c5 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -41,9 +41,14 @@ public function __construct(ConfigResolver $configResolver) */ public function args(array $arguments) { - $scheduler = $this->getClass(); - $scheduler->setArguments($arguments); - return $scheduler; + if (count($this->getOptions()) == 0) { + $scheduler = $this->getNewSchedulerClass(); + $scheduler->setArguments($arguments); + return $scheduler; + } + + $this->setArguments($arguments); + return $this; } /** @@ -77,9 +82,14 @@ public function setArguments($arguments) */ public function opts(array $options) { - $scheduler = $this->getClass(); - $scheduler->setOptions($options); - return $scheduler; + if (count($this->getArguments()) == 0) { + $scheduler = $this->getNewSchedulerClass(); + $scheduler->setOptions($options); + return $scheduler; + } + + $this->setOptions($options); + return $this; } /** @@ -109,15 +119,11 @@ public function setOptions($options) * * @return $this|Schedulable */ - public function getClass() + public function getNewSchedulerClass() { - //use the existing one if we've already instantiated - if ($this->instantiateNew === false) { - return $this; - } + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $scheduler */ + $scheduler = $this->configResolver->resolveSchedulerClass(); - $this->instantiateNew = false; - - return $this; + return $scheduler; } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 46f7686..82e9725 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -35,11 +35,15 @@ public function runDue() /** @var \Indatus\Dispatcher\Queue $queue */ $queue = $this->scheduleService->getQueue(); + \Log::debug('runCommand', [$queue->size()]); foreach ($queue->flush() as $queueItem) { $command = $queueItem->getCommand(); - $scheduler = $queueItem->getScheduler(); + if ($command->isEnabled() && $this->runnableInEnvironment($command)) { - $backgroundProcessRunner->run($command, $scheduler->getArguments()); + $scheduler = $queueItem->getScheduler(); + + \Log::debug('runCommand', [$command->getName(), $scheduler->getArguments(), $scheduler->getOptions()]); + $backgroundProcessRunner->run($command, $scheduler->getArguments(), $scheduler->getOptions()); } } } diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 21d128f..0dc8e18 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -86,7 +86,7 @@ public function getQueue() $queueItem = App::make('Indatus\Dispatcher\QueueItem'); $queueItem->setCommand($command); - $queueItem->setScheduler($scheduler); + $queueItem->setScheduler($schedule); $queue->add($queueItem); } diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index 133bc17..216933c 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -171,6 +171,12 @@ public function testOpts() $this->assertInstanceOf($this->schedularClass, $scheduler); $this->assertEquals($args, $scheduler->getArguments()); $this->assertEquals($opts, $scheduler->getOptions()); + + /** @var \Indatus\Dispatcher\Drivers\Cron\Scheduler $scheduler */ + $scheduler = $this->scheduler->opts($opts)->args($args); + $this->assertInstanceOf($this->schedularClass, $scheduler); + $this->assertEquals($args, $scheduler->getArguments()); + $this->assertEquals($opts, $scheduler->getOptions()); } } \ No newline at end of file From 3a65f98869a1037fcb963d92dbbe7eecf69083c0 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Wed, 9 Apr 2014 09:32:47 -0400 Subject: [PATCH 22/25] all variations of arguments and options are now fully accepted --- README.md | 53 ++++++++++++++++++- .../Dispatcher/BackgroundProcessRunner.php | 3 +- .../Drivers/Cron/ScheduleService.php | 2 +- .../Dispatcher/Drivers/Cron/Scheduler.php | 8 +++ .../Dispatcher/Services/CommandService.php | 2 - .../Dispatcher/Services/ScheduleService.php | 1 - tests/Commands/TestMake.php | 2 +- tests/Commands/TestRun.php | 2 +- tests/Commands/TestScheduleSummary.php | 2 +- .../Drivers/Cron/TestCronScheduleService.php | 2 +- tests/Drivers/Cron/TestCronScheduler.php | 3 +- tests/Scheduling/TestScheduledCommand.php | 2 +- tests/Services/TestCommandService.php | 9 ++-- tests/Services/TestScheduleService.php | 3 +- tests/TestBackgroundProcessRunner.php | 2 +- tests/TestConfig.php | 2 +- tests/TestConfigResolver.php | 4 +- tests/TestQueue.php | 1 - tests/TestQueueItem.php | 2 +- tests/TestServiceProvider.php | 4 +- 20 files changed, 82 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index ceaf908..63e75c5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ class MyCommand extends ScheduledCommand { * [Generating New Scheduled Commands](#new-commands) * [Scheduling Existing Commands](#scheduling-commands) * [Running Commands As Users](#commands-as-users) - * [Environment-specific commands](#environment-commands) + * [Environment-Specific Commands](#environment-commands) + * [Advanced Scheduling](#advanced-scheduling) * [Drivers](#drivers) * [Cron](#Cron) * [Custom Drivers](#custom-drivers) @@ -126,7 +127,7 @@ You may override `user()` to run a given artisan command as a specific user. En > This feature may not be supported by all drivers. -### Environment-specific commands +### Environment-Specific Commands You may override `environment()` to ensure your command is only scheduled in specific environments. It should provide a single environment or an array of environments. @@ -137,7 +138,55 @@ You may override `environment()` to ensure your command is only scheduled in spe } ``` + +### Advanced scheduling +You may schedule a given command to to run at multiple times by `schedule()` returning multiple `Schedulable` instances. + +```php + public function schedule(Schedulable $scheduler) + { + return [ + // 5am Mon-Fri + $scheduler->everyWeekday()->hours(5), + + // 2am every Saturday + App::make(get_class($scheduler)) + ->daysOfTheWeek(Scheduler::SATURDAY) + ->hours(2) + ]; + } +``` + +You may also schedule a command to run with arguments and options. + +```php + + public function schedule(Schedulable $scheduler) + { + return [ + // equivalent to: php /path/to/artisan command:name /path/to/file + $scheduler->args(['/path/to/file']) + ->everyWeekday() + ->hours(5), + + // equivalent to: php /path/to/artisan command:name /path/to/file --force --toDelete="expired" --exclude="admins" --exclude="developers" + $scheduler->args(['/path/to/file']) + ->opts([ + 'force', + 'toDelete' => 'expired', + 'exclude' => [ + 'admins', + 'developers' + ] + ]) + ->daysOfTheMonth([1, 15]) + ->hours(2) + ]; + } +``` + +> Both `args()` and `opts()`, whichever is called first, will internally create a new `Schedulable` instance for you, so be sure you call those prior to any scheduling methods. ## Drivers diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index f4a77ba..1c6f104 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -40,7 +40,8 @@ public function run( array $arguments = array(), array $options = array() ) { - \Log::debug($scheduledCommand->getName(), [$this->commandService->getRunCommand($scheduledCommand, $arguments, $options)]); + + \Log::debug('runCommand', [$this->commandService->getRunCommand($scheduledCommand, $arguments, $options)]); exec($this->commandService->getRunCommand($scheduledCommand, $arguments, $options)); return true; diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index 9657637..83fb8ac 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -18,7 +18,7 @@ class ScheduleService extends \Indatus\Dispatcher\Services\ScheduleService { /** - * Determine if a schedule is due to be run + * Determine if a schedule is due to be run. * * @param \Indatus\Dispatcher\Scheduling\Schedulable $scheduler * diff --git a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php index 5fbcc0c..49c531c 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/Scheduler.php @@ -391,4 +391,12 @@ public function getScheduleMonth() { return $this->scheduleMonth; } + + /** + * @return string + */ + public function __toString() + { + return $this->getSchedule(); + } } \ No newline at end of file diff --git a/src/Indatus/Dispatcher/Services/CommandService.php b/src/Indatus/Dispatcher/Services/CommandService.php index 82e9725..c6507cf 100644 --- a/src/Indatus/Dispatcher/Services/CommandService.php +++ b/src/Indatus/Dispatcher/Services/CommandService.php @@ -35,14 +35,12 @@ public function runDue() /** @var \Indatus\Dispatcher\Queue $queue */ $queue = $this->scheduleService->getQueue(); - \Log::debug('runCommand', [$queue->size()]); foreach ($queue->flush() as $queueItem) { $command = $queueItem->getCommand(); if ($command->isEnabled() && $this->runnableInEnvironment($command)) { $scheduler = $queueItem->getScheduler(); - \Log::debug('runCommand', [$command->getName(), $scheduler->getArguments(), $scheduler->getOptions()]); $backgroundProcessRunner->run($command, $scheduler->getArguments(), $scheduler->getOptions()); } } diff --git a/src/Indatus/Dispatcher/Services/ScheduleService.php b/src/Indatus/Dispatcher/Services/ScheduleService.php index 0dc8e18..372cc21 100644 --- a/src/Indatus/Dispatcher/Services/ScheduleService.php +++ b/src/Indatus/Dispatcher/Services/ScheduleService.php @@ -81,7 +81,6 @@ public function getQueue() } if ($this->isDue($schedule)) { - /** @var \Indatus\Dispatcher\QueueItem $queueItem */ $queueItem = App::make('Indatus\Dispatcher\QueueItem'); diff --git a/tests/Commands/TestMake.php b/tests/Commands/TestMake.php index aecbf10..40f8405 100644 --- a/tests/Commands/TestMake.php +++ b/tests/Commands/TestMake.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Commands\Make; +use Mockery as m; class TestMake extends TestCase { diff --git a/tests/Commands/TestRun.php b/tests/Commands/TestRun.php index c991684..016e9f8 100644 --- a/tests/Commands/TestRun.php +++ b/tests/Commands/TestRun.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Commands\Run; +use Mockery as m; class TestRun extends TestCase { diff --git a/tests/Commands/TestScheduleSummary.php b/tests/Commands/TestScheduleSummary.php index 2264ffa..9e1517d 100644 --- a/tests/Commands/TestScheduleSummary.php +++ b/tests/Commands/TestScheduleSummary.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Commands\ScheduleSummary; +use Mockery as m; class TestScheduleSummary extends TestCase { diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index db430b9..43d61ad 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -3,7 +3,7 @@ * @author Ben Kuhl */ -use \Indatus\Dispatcher\Drivers\Cron\ScheduleService; +use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Mockery as m; class TestCronScheduleService extends TestCase diff --git a/tests/Drivers/Cron/TestCronScheduler.php b/tests/Drivers/Cron/TestCronScheduler.php index 216933c..ef3eec8 100644 --- a/tests/Drivers/Cron/TestCronScheduler.php +++ b/tests/Drivers/Cron/TestCronScheduler.php @@ -3,7 +3,7 @@ * @author Ben Kuhl */ -use \Indatus\Dispatcher\Drivers\Cron\Scheduler; +use Indatus\Dispatcher\Drivers\Cron\Scheduler; class TestCronScheduler extends TestCase { @@ -26,6 +26,7 @@ public function setUp() public function testBuildingSchedule() { $this->assertEquals($this->scheduler->getSchedule(), '* * * * *'); + $this->assertEquals($this->scheduler.'', '* * * * *'); } public function testSetSchedule() diff --git a/tests/Scheduling/TestScheduledCommand.php b/tests/Scheduling/TestScheduledCommand.php index 2d8c5fe..b605d9d 100644 --- a/tests/Scheduling/TestScheduledCommand.php +++ b/tests/Scheduling/TestScheduledCommand.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Drivers\Cron\Scheduler; +use Mockery as m; class TestScheduledCommand extends TestCase { diff --git a/tests/Services/TestCommandService.php b/tests/Services/TestCommandService.php index f314f4f..5c17015 100644 --- a/tests/Services/TestCommandService.php +++ b/tests/Services/TestCommandService.php @@ -3,12 +3,12 @@ * @author Ben Kuhl */ -use Mockery as m; -use Indatus\Dispatcher\Services\CommandService; use Indatus\Dispatcher\Drivers\Cron\ScheduleService; -use Indatus\Dispatcher\Table; -use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\Queue; +use Indatus\Dispatcher\Scheduler; +use Indatus\Dispatcher\Services\CommandService; +use Indatus\Dispatcher\Table; +use Mockery as m; class TestCommandService extends TestCase { @@ -41,6 +41,7 @@ public function testRunDue() $scheduler = m::mock('Indatus\Dispatcher\Scheduling\Schedulable'); $scheduler->shouldReceive('getArguments')->once()->andReturn(array()); + $scheduler->shouldReceive('getOptions')->once()->andReturn(array()); $queue = m::mock('Indatus\Dispatcher\Queue', function ($m) use ($scheduledCommand, $scheduler) { $item = m::mock('Indatus\Dispatcher\QueueItem'); diff --git a/tests/Services/TestScheduleService.php b/tests/Services/TestScheduleService.php index 61929f1..f07f2fc 100644 --- a/tests/Services/TestScheduleService.php +++ b/tests/Services/TestScheduleService.php @@ -3,11 +3,10 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Drivers\Cron\ScheduleService; use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\Table; -use Indatus\Dispatcher\Queue; +use Mockery as m; class TestScheduleService extends TestCase { diff --git a/tests/TestBackgroundProcessRunner.php b/tests/TestBackgroundProcessRunner.php index c8696f6..97c6036 100644 --- a/tests/TestBackgroundProcessRunner.php +++ b/tests/TestBackgroundProcessRunner.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ +use Indatus\Dispatcher\BackgroundProcessRunner; use Mockery as m; -use \Indatus\Dispatcher\BackgroundProcessRunner; class TestBackgroundProcessRunner extends TestCase { diff --git a/tests/TestConfig.php b/tests/TestConfig.php index c4955a3..782cb96 100644 --- a/tests/TestConfig.php +++ b/tests/TestConfig.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\Scheduler; +use Mockery as m; class TestConfig extends TestCase { diff --git a/tests/TestConfigResolver.php b/tests/TestConfigResolver.php index 70a32d4..f1e5ab9 100644 --- a/tests/TestConfigResolver.php +++ b/tests/TestConfigResolver.php @@ -3,9 +3,9 @@ * @author Ben Kuhl */ -use Mockery as m; -use Indatus\Dispatcher\Scheduler; use Indatus\Dispatcher\ConfigResolver; +use Indatus\Dispatcher\Scheduler; +use Mockery as m; class TestConfigResolver extends TestCase { diff --git a/tests/TestQueue.php b/tests/TestQueue.php index 7b1e814..d4f310a 100644 --- a/tests/TestQueue.php +++ b/tests/TestQueue.php @@ -4,7 +4,6 @@ */ use Mockery as m; -use Indatus\Dispatcher\Queue; class TestQueue extends TestCase { diff --git a/tests/TestQueueItem.php b/tests/TestQueueItem.php index 2782adc..32013b6 100644 --- a/tests/TestQueueItem.php +++ b/tests/TestQueueItem.php @@ -3,8 +3,8 @@ * @author Ben Kuhl */ -use Mockery as m; use Indatus\Dispatcher\QueueItem; +use Mockery as m; class TestQueueItem extends TestCase { diff --git a/tests/TestServiceProvider.php b/tests/TestServiceProvider.php index 74197e5..fd38037 100644 --- a/tests/TestServiceProvider.php +++ b/tests/TestServiceProvider.php @@ -3,9 +3,9 @@ * @author Ben Kuhl */ -use Mockery as m; -use Indatus\Dispatcher\ServiceProvider; use Indatus\Dispatcher\BackgroundProcess; +use Indatus\Dispatcher\ServiceProvider; +use Mockery as m; class TestServiceProvider extends TestCase { From ddd9d3759530b61fdbba15947afce62ff60e0cd8 Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Wed, 9 Apr 2014 10:33:07 -0400 Subject: [PATCH 23/25] readme tweaks, php 5.3 compatibility --- README.md | 4 +++- src/Indatus/Dispatcher/BackgroundProcessRunner.php | 2 +- .../Dispatcher/Drivers/Cron/ScheduleService.php | 5 +++-- src/Indatus/Dispatcher/Scheduling/Schedulable.php | 12 ++++++------ tests/Drivers/Cron/TestCronScheduleService.php | 10 +++------- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 63e75c5..956877e 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,8 @@ You may override `environment()` to ensure your command is only scheduled in spe ### Advanced scheduling +> These examples utilize the [cron](#Cron) driver. + You may schedule a given command to to run at multiple times by `schedule()` returning multiple `Schedulable` instances. ```php @@ -186,7 +188,7 @@ You may also schedule a command to run with arguments and options. } ``` -> Both `args()` and `opts()`, whichever is called first, will internally create a new `Schedulable` instance for you, so be sure you call those prior to any scheduling methods. +> Both `args()` and `opts()`, whichever is called first, will internally create a new `Schedulable` instance for you so you don't need to `App::make()`. ## Drivers diff --git a/src/Indatus/Dispatcher/BackgroundProcessRunner.php b/src/Indatus/Dispatcher/BackgroundProcessRunner.php index 1c6f104..93d9bea 100644 --- a/src/Indatus/Dispatcher/BackgroundProcessRunner.php +++ b/src/Indatus/Dispatcher/BackgroundProcessRunner.php @@ -41,7 +41,7 @@ public function run( array $options = array() ) { - \Log::debug('runCommand', [$this->commandService->getRunCommand($scheduledCommand, $arguments, $options)]); + //\Log::debug('runCommand', [$this->commandService->getRunCommand($scheduledCommand, $arguments, $options)]); exec($this->commandService->getRunCommand($scheduledCommand, $arguments, $options)); return true; diff --git a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php index 83fb8ac..e72d154 100644 --- a/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php +++ b/src/Indatus/Dispatcher/Drivers/Cron/ScheduleService.php @@ -30,7 +30,7 @@ public function isDue(Schedulable $scheduler) $cron = CronExpression::factory($scheduler->getSchedule()); return $cron->isDue(); } catch (\Exception $e) { - Log::error($e->getMessage()); + \Log::error($e->getMessage()); } return false; @@ -46,12 +46,13 @@ public function printSummary() foreach ($this->getScheduledCommands() as $command) { /** @var $command \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface */ $scheduler = $command->schedule(App::make('Indatus\Dispatcher\Scheduling\Schedulable')); - //if there's only one schedule, print just the command if (!is_array($scheduler)) { $this->printCommand($command, $scheduler); } else { + if ($this->printCommandLabel($command)) { + /** @var \Indatus\Dispatcher\Scheduling\Schedulable $schedule */ foreach ($scheduler as $schedule) { $this->printSchedule($command, $schedule); } diff --git a/src/Indatus/Dispatcher/Scheduling/Schedulable.php b/src/Indatus/Dispatcher/Scheduling/Schedulable.php index 206e6c5..2e48bfe 100644 --- a/src/Indatus/Dispatcher/Scheduling/Schedulable.php +++ b/src/Indatus/Dispatcher/Scheduling/Schedulable.php @@ -33,7 +33,7 @@ public function __construct(ConfigResolver $configResolver) } /** - * Define arguments for this command when it runs. + * Define arguments for this schedule when it runs. * * @param array $arguments * @@ -41,7 +41,7 @@ public function __construct(ConfigResolver $configResolver) */ public function args(array $arguments) { - if (count($this->getOptions()) == 0) { + if (count($this->options) == 0) { $scheduler = $this->getNewSchedulerClass(); $scheduler->setArguments($arguments); return $scheduler; @@ -52,7 +52,7 @@ public function args(array $arguments) } /** - * Get the arguments for this command. + * Get the arguments for this schedule. * * @return array */ @@ -74,7 +74,7 @@ public function setArguments($arguments) } /** - * Define options for this command when it runs. + * Define options for this schedule when it runs. * * @param array $options * @@ -82,7 +82,7 @@ public function setArguments($arguments) */ public function opts(array $options) { - if (count($this->getArguments()) == 0) { + if (count($this->arguments) == 0) { $scheduler = $this->getNewSchedulerClass(); $scheduler->setOptions($options); return $scheduler; @@ -93,7 +93,7 @@ public function opts(array $options) } /** - * Get the options for this command. + * Get the options for this schedule. * * @return array */ diff --git a/tests/Drivers/Cron/TestCronScheduleService.php b/tests/Drivers/Cron/TestCronScheduleService.php index 43d61ad..f616585 100644 --- a/tests/Drivers/Cron/TestCronScheduleService.php +++ b/tests/Drivers/Cron/TestCronScheduleService.php @@ -64,11 +64,7 @@ public function testPrintSummary() $m->shouldReceive('setHeaders')->once(); $m->shouldReceive('display')->once(); }); - $queue = m::mock('Indatus\Dispatcher\Queue', function ($m) { - /*$m->shouldReceive('setHeaders')->once(); - $m->shouldReceive('sort')->once(); - $m->shouldReceive('display')->once();*/ - }); + $queue = m::mock('Indatus\Dispatcher\Queue'); $scheduledCommandWithMultipleSchedulers = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { $table->shouldReceive('addRow')->times(3); @@ -86,10 +82,10 @@ public function testPrintSummary() $m->shouldReceive('getName')->once(); $m->shouldReceive('user')->once(); $m->shouldReceive('environment')->twice(); - $m->shouldReceive('schedule')->once()->andReturn([ + $m->shouldReceive('schedule')->once()->andReturn(array( $scheduler, $scheduler - ]); + )); }); $scheduledCommand = m::mock('Indatus\Dispatcher\Scheduling\ScheduledCommand', function ($m) use ($table) { $table->shouldReceive('addRow')->once(); From 19469ccc22fa112a109b124424f89ddddc6820cd Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Wed, 9 Apr 2014 10:42:48 -0400 Subject: [PATCH 24/25] Updated custom driver docs to use correct publish command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 956877e..cee256a 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ You can build your own drivers or extend a driver that's included. Create a pac * `Scheduler` that `implements Indatus\Dispatcher\Scheduling\Schedulable`. This class should provide a useful interface for programmers to schedule their commands. * `ScheduleService` that `extends \Indatus\Dispatcher\Services\ScheduleService`. This class contains logic on how to determine if a command is due to run. -Publish the configs using `php artisan view:publish indatus/dispatcher`. Then update your driver configuration to reference the package in which these 2 classes are included (do not include a trailing slash): +Publish the configs using `php artisan config:publish indatus/dispatcher`. Then update your driver configuration to reference the package in which these 2 classes are included (do not include a trailing slash): ```php 'driver' => '\MyApp\ScheduleDriver' From 9b785c643370e855ef6e2d6420a4dae1d1bcd4cf Mon Sep 17 00:00:00 2001 From: Ben Kuhl Date: Wed, 9 Apr 2014 10:48:08 -0400 Subject: [PATCH 25/25] Updated rcron instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cee256a..431bc76 100644 --- a/README.md +++ b/README.md @@ -257,7 +257,7 @@ Publish the configs using `php artisan config:publish indatus/dispatcher`. Then **I need to deploy to multiple servers representing a single environment. How can I be sure my command is only run by a single server and not run on each server?** -Schedule `scheduled:run` to use [rcron](https://code.google.com/p/rcron/): +Schedule `scheduled:run` to run every minute with [rcron](https://code.google.com/p/rcron/): ```php * * * * * /usr/bin/rcron php /path/to/artisan scheduled:run 1>> /dev/null 2>&1