1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Basebuilder\Scheduling\Command; |
4
|
|
|
|
5
|
|
|
use Basebuilder\Scheduling\Event; |
6
|
|
|
use Basebuilder\Scheduling\Event\Process; |
7
|
|
|
use Basebuilder\Scheduling\Schedule; |
8
|
|
|
use Symfony\Component\Console\Command\Command; |
9
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
10
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
11
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* This command runs all scheduled tasks that are due for execution, replacing the need for multiple CRON jobs |
15
|
|
|
*/ |
16
|
|
|
class Run extends Command |
17
|
|
|
{ |
18
|
|
|
/** |
19
|
|
|
* @var Schedule |
20
|
|
|
*/ |
21
|
|
|
protected $schedule; |
22
|
|
|
|
23
|
|
|
protected $minimumVerbosity = OutputInterface::VERBOSITY_VERBOSE; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @param Schedule $schedule |
27
|
|
|
* @param string|null $name |
28
|
|
|
*/ |
29
|
|
|
public function __construct(Schedule $schedule, $name = null) |
30
|
|
|
{ |
31
|
|
|
$this->schedule = $schedule; |
32
|
|
|
parent::__construct($name); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @inheritdoc |
37
|
|
|
*/ |
38
|
|
|
protected function configure() |
39
|
|
|
{ |
40
|
|
|
$this |
41
|
|
|
->setName('scheduler:run') |
42
|
|
|
->addArgument('force', InputArgument::OPTIONAL, 'Force a event to run'); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @inheritdoc |
47
|
|
|
*/ |
48
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
49
|
|
|
{ |
50
|
|
|
$schedule = $this->schedule; |
51
|
|
|
|
52
|
|
|
$forcedEventName = $input->getArgument('force'); |
53
|
|
|
|
54
|
|
|
if ($forcedEventName) { |
55
|
|
|
$events = array_filter($schedule->allEvents(), function (Event $event) use ($forcedEventName) { |
56
|
|
|
return $event->getName() === $forcedEventName; |
57
|
|
|
}); |
58
|
|
|
|
59
|
|
|
if (count($events) < 1) { |
60
|
|
|
throw new \RuntimeException('No events with that name'); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
$this->runEvent(array_shift($events), $output); |
64
|
|
|
exit; |
|
|
|
|
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
$events = $schedule->dueEvents(); |
68
|
|
|
|
69
|
|
|
if ($output->getVerbosity() >= $this->minimumVerbosity) { |
70
|
|
|
$output->writeln( |
71
|
|
|
'======================================================' . PHP_EOL . |
72
|
|
|
'# Running schedule for <info>' . $schedule->getName() . '</info>' . PHP_EOL . |
73
|
|
|
'======================================================' |
74
|
|
|
); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
foreach ($events as $event) { |
78
|
|
|
$this->runEvent($event, $output); |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
protected function runEvent(Event $event, OutputInterface $output) |
83
|
|
|
{ |
84
|
|
|
if ($output->getVerbosity() >= $this->minimumVerbosity) { |
85
|
|
|
$output->writeln('Running event <info>"' . (string) $event . '"</info>'); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
$result = $event->run(); |
89
|
|
|
if ($event instanceof Process) { |
90
|
|
|
$this->handleProcessOutput($result, $output); |
91
|
|
|
} |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
protected function handleProcessOutput(\Symfony\Component\Process\Process $process, OutputInterface $output) |
95
|
|
|
{ |
96
|
|
|
if ($process->isTerminated() && $output->getVerbosity() >= $this->minimumVerbosity) { |
97
|
|
|
$tag = $process->isSuccessful() ? 'info' : 'error'; |
98
|
|
|
$output->writeln('Exit code: <' . $tag . '>' . $process->getExitCode() . '</' . $tag . '>'); |
99
|
|
|
} |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.