diff --git a/CHANGELOG.md b/CHANGELOG.md index 50d87c8a..ef138c61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Latest ## Changes * [#190](https://github.com/cleverage/process-bundle/issues/190) Update quality stack: use Rector `withComposerBased()` sets (removed `SYMFONY_64` / `PHPUNIT_100` sets), declare used Symfony packages and PHPUnit range in composer.json, apply quality tools fixes * [#145](https://github.com/cleverage/process-bundle/issues/145) Add missing documentations: reference pages for every Task & Transformer, ConditionTrait & GenericTransformer, complete guides and cookbooks. Harmonize and fix existing documentation. +* [#229](https://github.com/cleverage/process-bundle/issues/229) StatCounterTask and AdvancedStatCounterTask pass their input to their output on every execution (they used to output `null`, and AdvancedStatCounterTask was skipped when not logging), so they can be placed anywhere in a branch. Update documentation, add tests. ## Fixes * [#192](https://github.com/cleverage/process-bundle/issues/192) Fix CommandRunnerTask: only pass the `options` option to `Process::setOptions()`, support string `commandline` through `Process::fromShellCommandline()`, validate option types. Update documentation, add tests. diff --git a/docs/reference/tasks/advanced_stat_counter_task.md b/docs/reference/tasks/advanced_stat_counter_task.md index 8853593b..a30924da 100644 --- a/docs/reference/tasks/advanced_stat_counter_task.md +++ b/docs/reference/tasks/advanced_stat_counter_task.md @@ -2,7 +2,8 @@ AdvancedStatCounterTask ======================= Logs performance statistics (`info` level) every N executions: time since the last log, processing rate, number of -processed items and total elapsed time. +processed items and total elapsed time. The input is passed to the output, so the task can be placed anywhere in a +branch. Task reference -------------- @@ -12,13 +13,12 @@ Task reference Accepted inputs --------------- -Input is ignored, only the number of executions matters. +`any`: only the number of executions matters. Possible outputs ---------------- -`null` when statistics are logged (with `show_every: 1`, on every counted execution), otherwise the task is skipped (nothing is sent to the outputs). It is meant to be -used as the last task of a branch. +`any`: the input, unchanged, on every execution (whether statistics are logged or not). The logged message has the following format: diff --git a/docs/reference/tasks/stat_counter_task.md b/docs/reference/tasks/stat_counter_task.md index eed8a84f..712deff0 100644 --- a/docs/reference/tasks/stat_counter_task.md +++ b/docs/reference/tasks/stat_counter_task.md @@ -1,7 +1,8 @@ StatCounterTask =============== -Counts the number of times the task is executed and logs the total (`info` level) when the process ends. +Counts the number of times the task is executed and logs the total (`info` level) when the process ends. The input is +passed to the output, so the task can be placed anywhere in a branch. Task reference -------------- @@ -11,12 +12,12 @@ Task reference Accepted inputs --------------- -Input is ignored. +`any`: only the number of executions matters. Possible outputs ---------------- -`null`: the task does not set any output. It is meant to be used as the last task of a branch. +`any`: the input, unchanged. At finalization, the message `Processed item count: ` is logged. diff --git a/src/Task/Reporting/AdvancedStatCounterTask.php b/src/Task/Reporting/AdvancedStatCounterTask.php index e7aa97a4..ddaff0e3 100644 --- a/src/Task/Reporting/AdvancedStatCounterTask.php +++ b/src/Task/Reporting/AdvancedStatCounterTask.php @@ -19,7 +19,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; /** - * Count the time between 2 iterations. + * Count the time between 2 iterations, and log statistics every N executions. The input is passed to the output. */ class AdvancedStatCounterTask extends AbstractConfigurableTask { @@ -43,9 +43,10 @@ public function execute(ProcessState $state): void $this->startedAt = $now; $this->lastUpdate = $now; } + // The input is always passed to the output, the task only logs statistics + $state->setOutput($state->getInput()); if ($this->preInitCounter < $this->getOption($state, 'skip_first')) { ++$this->preInitCounter; - $state->setSkipped(true); return; } @@ -65,8 +66,6 @@ public function execute(ProcessState $state): void $this->lastUpdate = $now; $this->logger->info($fullText); - } else { - $state->setSkipped(true); } } diff --git a/src/Task/Reporting/StatCounterTask.php b/src/Task/Reporting/StatCounterTask.php index c12285c1..b394aa64 100644 --- a/src/Task/Reporting/StatCounterTask.php +++ b/src/Task/Reporting/StatCounterTask.php @@ -18,7 +18,7 @@ use Psr\Log\LoggerInterface; /** - * Count the number of times the task was executed. + * Count the number of times the task was executed, and log it when the process ends. The input is passed to the output. */ class StatCounterTask implements FinalizableTaskInterface { @@ -37,5 +37,6 @@ public function finalize(ProcessState $state): void public function execute(ProcessState $state): void { ++$this->counter; + $state->setOutput($state->getInput()); } } diff --git a/tests/Task/Reporting/AdvancedStatCounterTaskTest.php b/tests/Task/Reporting/AdvancedStatCounterTaskTest.php index 648963d2..c0a06176 100644 --- a/tests/Task/Reporting/AdvancedStatCounterTaskTest.php +++ b/tests/Task/Reporting/AdvancedStatCounterTaskTest.php @@ -34,9 +34,9 @@ class AdvancedStatCounterTaskTest extends TestCase { public function testEveryExecutionIsLoggedWithShowEveryOne(): void { - [$messages, $skipped] = $this->runTask(3, ['show_every' => 1]); + [$messages, $outputs] = $this->runTask(3, ['show_every' => 1]); - self::assertSame([false, false, false], $skipped); + self::assertSame([0, 1, 2], $outputs); self::assertCount(3, $messages); self::assertStringContainsString(' 1 items processed', $messages[0]); self::assertStringContainsString(' 2 items processed', $messages[1]); @@ -45,9 +45,9 @@ public function testEveryExecutionIsLoggedWithShowEveryOne(): void public function testEveryNthExecutionIsLogged(): void { - [$messages, $skipped] = $this->runTask(7, ['show_every' => 3, 'num_items' => 10]); + [$messages, $outputs] = $this->runTask(7, ['show_every' => 3, 'num_items' => 10]); - self::assertSame([true, true, false, true, true, false, true], $skipped); + self::assertSame([0, 1, 2, 3, 4, 5, 6], $outputs); self::assertCount(2, $messages); self::assertStringContainsString(' 30 items processed', $messages[0]); self::assertStringContainsString(' 60 items processed', $messages[1]); @@ -55,9 +55,9 @@ public function testEveryNthExecutionIsLogged(): void public function testSkipFirstExecutionsAreNotCounted(): void { - [$messages, $skipped] = $this->runTask(4, ['show_every' => 2, 'skip_first' => 1]); + [$messages, $outputs] = $this->runTask(4, ['show_every' => 2, 'skip_first' => 1]); - self::assertSame([true, true, false, true], $skipped); + self::assertSame([0, 1, 2, 3], $outputs); self::assertCount(1, $messages); self::assertStringContainsString(' 2 items processed', $messages[0]); } @@ -65,7 +65,9 @@ public function testSkipFirstExecutionsAreNotCounted(): void /** * @param array $options * - * @return array{list, list} + * Execute the task $executions times with the inputs 0, 1, 2... + * + * @return array{list, list} logged messages, and outputs (null when skipped) */ private function runTask(int $executions, array $options): array { @@ -83,14 +85,15 @@ public function log($level, string|\Stringable $message, array $context = []): v $task = new AdvancedStatCounterTask($logger); $task->initialize($state); - $skipped = []; + $outputs = []; for ($i = 0; $i < $executions; ++$i) { $state->reset(false); + $state->setInput($i); $task->execute($state); - $skipped[] = $state->isSkipped(); + $outputs[] = $state->isSkipped() ? null : $state->getOutput(); } - return [$logger->messages, $skipped]; + return [$logger->messages, $outputs]; } private function createState(string $class, array $options): ProcessState diff --git a/tests/Task/Reporting/StatCounterTaskTest.php b/tests/Task/Reporting/StatCounterTaskTest.php new file mode 100644 index 00000000..e83278aa --- /dev/null +++ b/tests/Task/Reporting/StatCounterTaskTest.php @@ -0,0 +1,56 @@ + */ + public array $messages = []; + + public function log($level, string|\Stringable $message, array $context = []): void + { + $this->messages[] = (string) $message; + } + }; + $processConfiguration = new ProcessConfiguration('test', []); + $state = new ProcessState($processConfiguration, new ProcessHistory($processConfiguration)); + $task = new StatCounterTask($logger); + + $outputs = []; + foreach (['a', ['b'], null] as $input) { + $state->reset(false); + $state->setInput($input); + $task->execute($state); + $outputs[] = $state->isSkipped() ? 'skipped' : $state->getOutput(); + } + $task->finalize($state); + + self::assertSame(['a', ['b'], null], $outputs); + self::assertSame(['Processed item count: 3'], $logger->messages); + } +}