44
55namespace Wrep \Daemonizable \Command ;
66
7+ use Exception ;
8+ use InvalidArgumentException ;
79use Symfony \Component \Console \Exception \LogicException ;
10+ use Throwable ;
811use Wrep \Daemonizable \Exception \ShutdownEndlessCommandException ;
912use Symfony \Component \Console \Command \Command ;
1013use Symfony \Component \Console \Output \OutputInterface ;
11- use Symfony \Component \Console \Output \NullOutput ;
1214use Symfony \Component \Console \Input \InputInterface ;
1315use Symfony \Component \Console \Input \InputOption ;
1416use function pcntl_async_signals ;
@@ -18,12 +20,12 @@ abstract class EndlessCommand extends Command
1820{
1921 public const DEFAULT_TIMEOUT = 5 ;
2022
21- private $ code ;
22- private $ timeout ;
23- private $ returnCode ;
24- private $ shutdownRequested ;
25- private $ lastUsage ;
26- private $ lastPeakUsage ;
23+ /** @var int<0,max> $timeout */
24+ private int $ timeout ;
25+ private int $ returnCode ;
26+ private bool $ shutdownRequested ;
27+ private int $ lastUsage ;
28+ private int $ lastPeakUsage ;
2729
2830 /**
2931 * @see Command::__construct()
@@ -59,7 +61,7 @@ public function run(InputInterface $input, OutputInterface $output): int
5961 // Enable async signals for fast signal processing
6062 try {
6163 pcntl_async_signals (true );
62- } catch (\ Throwable $ e ) {
64+ } catch (Throwable $ e ) {
6365 declare (ticks=1 );
6466 }
6567
@@ -93,16 +95,16 @@ public function handleSignal(int $signal): void
9395 * @param InputInterface $input An InputInterface instance
9496 * @param OutputInterface $output An OutputInterface instance
9597 *
96- * @return integer The command exit code
98+ * @return int The command exit code
9799 *
98- * @throws \ Exception
100+ * @throws Exception
99101 */
100- protected function runloop (InputInterface $ input , OutputInterface $ output )
102+ protected function runloop (InputInterface $ input , OutputInterface $ output ): int
101103 {
102104 try {
103105 $ this ->starting ($ input , $ output );
104106
105- do {
107+ while (! $ this -> shutdownRequested ) {
106108 // Start iteration
107109 $ this ->startIteration ($ input , $ output );
108110
@@ -113,12 +115,12 @@ protected function runloop(InputInterface $input, OutputInterface $output)
113115 $ this ->finishIteration ($ input , $ output );
114116
115117 // Request shutdown if we only should run once
116- if (( bool ) $ input ->getOption ('run-once ' )) {
118+ if ($ input ->getOption ('run-once ' )) {
117119 $ this ->shutdown ();
118120 }
119121
120122 // Print memory report if requested
121- if (( bool ) $ input ->getOption ('detect-leaks ' )) {
123+ if ($ input ->getOption ('detect-leaks ' )) {
122124 // Gather memory info
123125 $ peak = $ this ->getMemoryInfo (true );
124126 $ curr = $ this ->getMemoryInfo (false );
@@ -139,8 +141,9 @@ protected function runloop(InputInterface $input, OutputInterface $output)
139141 if (! $ this ->shutdownRequested ) {
140142 usleep ($ this ->timeout );
141143 }
142- } while (! $ this -> shutdownRequested );
144+ }
143145 } catch (ShutdownEndlessCommandException $ ignore ) {
146+ // this exception is just caught to break out of the loop and signal we are done and finalize
144147 }
145148
146149 // Prepare for shutdown
@@ -179,13 +182,14 @@ protected function finishIteration(InputInterface $input, OutputInterface $outpu
179182 /**
180183 * Get information about the current memory usage
181184 *
182- * @param bool True for peak usage, false for current usage
185+ * @param bool $peak True for peak usage, false for current usage
183186 *
184- * @return array
187+ * @return array{amount: int, diff: int, diffPercentage: int|float, statusDescription: 'decreasing'|'increasing'|'stable', statusType: 'comment'|'error'|'info'}
185188 */
186189 private function getMemoryInfo (bool $ peak = false ): array
187190 {
188191 $ lastUsage = ($ peak ) ? $ this ->lastPeakUsage : $ this ->lastUsage ;
192+ $ info = [];
189193 $ info ['amount ' ] = ($ peak ) ? memory_get_peak_usage () : memory_get_usage ();
190194 $ info ['diff ' ] = $ info ['amount ' ] - $ lastUsage ;
191195 $ info ['diffPercentage ' ] = ($ lastUsage == 0 ) ? 0 : $ info ['diff ' ] / ($ lastUsage / 100 );
@@ -212,22 +216,6 @@ private function getMemoryInfo(bool $peak = false): array
212216 return $ info ;
213217 }
214218
215- /**
216- * @see Command::setCode()
217- */
218- public function setCode (callable $ code ): static
219- {
220- // Exact copy of our parent
221- // Makes sure we can access to call it every iteration
222- if (! is_callable ($ code )) {
223- throw new \InvalidArgumentException ('Invalid callable provided to Command::setCode. ' );
224- }
225-
226- $ this ->code = $ code ;
227-
228- return $ this ;
229- }
230-
231219 /**
232220 * Execution logic.
233221 *
@@ -252,19 +240,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int
252240 /**
253241 * Set the timeout of this command.
254242 *
255- * @param int|float $timeout Timeout between two iterations in seconds
256- *
257- * @return Command The current instance
243+ * @param float $timeout Timeout between two iterations in seconds
258244 *
259- * @throws \ InvalidArgumentException
245+ * @throws InvalidArgumentException
260246 */
261- public function setTimeout (float $ timeout )
247+ public function setTimeout (float $ timeout ): self
262248 {
263249 if ($ timeout < 0 ) {
264- throw new \ InvalidArgumentException ('Invalid timeout provided to Command::setTimeout. ' );
250+ throw new InvalidArgumentException ('Invalid timeout provided to Command::setTimeout. ' );
265251 }
266252
267- $ this ->timeout = (int ) (1000000 * $ timeout );
253+ /** @var int<0,max> $timeout */
254+ $ timeout = (int )(1000000 * $ timeout );
255+
256+ $ this ->timeout = $ timeout ;
268257
269258 return $ this ;
270259 }
@@ -282,16 +271,14 @@ public function getTimeout(): float
282271 /**
283272 * Set the return code of this command.
284273 *
285- * @param int 0 if everything went fine, or an error code
286- *
287- * @return Command The current instance
274+ * @param int $returnCode 0 if everything went fine, or an error code
288275 *
289- * @throws \ InvalidArgumentException
276+ * @throws InvalidArgumentException
290277 */
291- public function setReturnCode (int $ returnCode )
278+ public function setReturnCode (int $ returnCode ): self
292279 {
293280 if ($ returnCode < 0 ) {
294- throw new \ InvalidArgumentException ('Invalid returnCode provided to Command::setReturnCode. ' );
281+ throw new InvalidArgumentException ('Invalid returnCode provided to Command::setReturnCode. ' );
295282 }
296283
297284 $ this ->returnCode = $ returnCode ;
@@ -313,11 +300,10 @@ public function getReturnCode(): int
313300 * Instruct the command to end the endless loop gracefully.
314301 *
315302 * This will finish the current iteration and give the command a chance
316- * to cleanup .
303+ * to clean up .
317304 *
318- * @return Command The current instance
319305 */
320- public function shutdown ()
306+ public function shutdown (): self
321307 {
322308 $ this ->shutdownRequested = true ;
323309
@@ -331,19 +317,17 @@ public function shutdown()
331317 * execution code takes quite long to finish on a point where you still can exit
332318 * without corrupting any data.
333319 *
334- * @return Command The current instance
335- *
336320 * @throws ShutdownEndlessCommandException
337321 */
338- protected function throwExceptionOnShutdown ()
322+ protected function throwExceptionOnShutdown (): self
339323 {
340324 // Make sure all signals are handled
341325 if (function_exists ('pcntl_signal_dispatch ' )) {
342326 pcntl_signal_dispatch ();
343327 }
344328
345329 if ($ this ->shutdownRequested ) {
346- throw new ShutdownEndlessCommandException ('Volunteered to break out of the EndlessCommand runloop because a shutdown is requested. ' );
330+ throw new ShutdownEndlessCommandException ('Volunteered to break out of the EndlessCommand:: runloop because a shutdown is requested. ' );
347331 }
348332
349333 return $ this ;
@@ -362,4 +346,9 @@ protected function throwExceptionOnShutdown()
362346 protected function finalize (InputInterface $ input , OutputInterface $ output ): void
363347 {
364348 }
349+
350+ protected function isShutdownRequested (): bool
351+ {
352+ return $ this ->shutdownRequested ;
353+ }
365354}
0 commit comments