From f69204148828b5b1ef40e63566a3e87c353171c4 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Jan 2018 10:51:11 +0100 Subject: [PATCH 1/8] Add debugger --- src/Pool.php | 13 ++++++++++++- src/PoolDebugger.php | 44 ++++++++++++++++++++++++++++++++++++++++++++ tests/PoolTest.php | 14 +++++++------- 3 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 src/PoolDebugger.php diff --git a/src/Pool.php b/src/Pool.php index b822b9bd..6db005ba 100644 --- a/src/Pool.php +++ b/src/Pool.php @@ -24,6 +24,9 @@ class Pool implements ArrayAccess /** @var \Spatie\Async\ParallelProcess[] */ protected $failed = []; + /** @var \Spatie\Async\ParallelProcess[] */ + protected $timeouts = []; + protected $results = []; public function __construct() @@ -157,7 +160,7 @@ public function markAsTimedOut(ParallelProcess $process) unset($this->inProgress[$process->getPid()]); - $this->failed[$process->getPid()] = $process; + $this->timeouts[$process->getPid()] = $process; $this->notify(); } @@ -211,6 +214,14 @@ public function getFailed(): array return $this->failed; } + /** + * @return \Spatie\Async\ParallelProcess[] + */ + public function getTimeouts(): array + { + return $this->timeouts; + } + protected function registerListener() { pcntl_async_signals(true); diff --git a/src/PoolDebugger.php b/src/PoolDebugger.php new file mode 100644 index 00000000..f0ec13e7 --- /dev/null +++ b/src/PoolDebugger.php @@ -0,0 +1,44 @@ +getFinished(); + $failed = $pool->getFailed(); + $timeouts = $pool->getTimeouts(); + + return 'finished: ' . count($finished) + . ' - failed: ' . count($failed) + . ' - timeouts: ' . count($timeouts); + } + + public static function statusForFailed(Pool $pool): string + { + $failed = $pool->getFailed(); + + $status = "\nFailed status:\n\n"; + + foreach ($failed as $process) { + $output = $process->getErrorOutput(); + + if ($output instanceof SerializableException) { + $output = get_class($output->asThrowable()) . ' ' . $output->asThrowable()->getMessage(); + } + + $status .= "{$process->getId()} failed with {$output}\n\n"; + } + + return $status; + } +} diff --git a/tests/PoolTest.php b/tests/PoolTest.php index fca97d99..54518a63 100644 --- a/tests/PoolTest.php +++ b/tests/PoolTest.php @@ -39,7 +39,7 @@ public function it_can_run_processes_in_parallel() $executionTime = $endTime - $startTime; - $this->assertLessThan(0.2, $executionTime, "Execution time was {$executionTime}, expected less than 0.2."); + $this->assertLessThan(0.2, $executionTime, "Execution time was {$executionTime}, expected less than 0.2.\n" . PoolDebugger::statusForPool($pool)); } /** @test */ @@ -59,7 +59,7 @@ public function it_can_handle_success() $pool->wait(); - $this->assertEquals(10, $counter); + $this->assertEquals(10, $counter, PoolDebugger::statusForPool($pool)); } /** @test */ @@ -80,7 +80,7 @@ public function it_can_handle_timeout() $pool->wait(); - $this->assertEquals(5, $counter); + $this->assertEquals(5, $counter, PoolDebugger::statusForPool($pool)); } /** @test */ @@ -98,7 +98,7 @@ public function it_can_handle_exceptions() $pool->wait(); - $this->assertCount(5, $pool->getFailed()); + $this->assertCount(5, $pool->getFailed(), PoolDebugger::statusForPool($pool)); } /** @test */ @@ -121,8 +121,8 @@ public function it_can_handle_a_maximum_of_concurrent_processes() $executionTime = $endTime - $startTime; - $this->assertGreaterThanOrEqual(2, $executionTime, "Execution time was {$executionTime}, expected more than 2."); - $this->assertCount(3, $pool->getFinished()); + $this->assertGreaterThanOrEqual(2, $executionTime, "Execution time was {$executionTime}, expected more than 2.\n" . PoolDebugger::statusForPool($pool)); + $this->assertCount(3, $pool->getFinished(), PoolDebugger::statusForPool($pool)); } /** @test */ @@ -144,7 +144,7 @@ public function it_works_with_helper_functions() await($pool); - $this->assertEquals(10, $counter); + $this->assertEquals(10, $counter, PoolDebugger::statusForPool($pool)); } /** @test */ From e005ca793143b195e2c31b1e1d6907ae7b3edff1 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Jan 2018 13:44:02 +0100 Subject: [PATCH 2/8] Add PoolStatus --- src/Pool.php | 9 ++++++ src/{PoolDebugger.php => PoolStatus.php} | 35 +++++++++++++++++------- tests/PoolTest.php | 28 ++++++++++++++----- 3 files changed, 55 insertions(+), 17 deletions(-) rename src/{PoolDebugger.php => PoolStatus.php} (50%) diff --git a/src/Pool.php b/src/Pool.php index 6db005ba..d648110f 100644 --- a/src/Pool.php +++ b/src/Pool.php @@ -29,9 +29,13 @@ class Pool implements ArrayAccess protected $results = []; + protected $status; + public function __construct() { $this->registerListener(); + + $this->status = new PoolStatus($this); } /** @@ -222,6 +226,11 @@ public function getTimeouts(): array return $this->timeouts; } + public function status(): PoolStatus + { + return $this->status; + } + protected function registerListener() { pcntl_async_signals(true); diff --git a/src/PoolDebugger.php b/src/PoolStatus.php similarity index 50% rename from src/PoolDebugger.php rename to src/PoolStatus.php index f0ec13e7..21ee53d4 100644 --- a/src/PoolDebugger.php +++ b/src/PoolStatus.php @@ -4,28 +4,43 @@ use Spatie\Async\Output\SerializableException; -class PoolDebugger +class PoolStatus { - public static function statusForPool(Pool $pool): string + protected $pool; + + public function __construct(Pool $pool) + { + $this->pool = $pool; + } + + public function __toString(): string { - return self::summaryForPool($pool) . "\n" - . self::statusForFailed($pool); + return $this->lines( + $this->summaryToString(), + $this->failedToString() + ); } - public static function summaryForPool(Pool $pool): string + protected function lines(string ...$lines): string { - $finished = $pool->getFinished(); - $failed = $pool->getFailed(); - $timeouts = $pool->getTimeouts(); + return implode("\n", $lines); + } + + protected function summaryToString(): string + { + $finished = $this->pool->getFinished(); + $failed = $this->pool->getFailed(); + $timeouts = $this->pool->getTimeouts(); return 'finished: ' . count($finished) . ' - failed: ' . count($failed) . ' - timeouts: ' . count($timeouts); } - public static function statusForFailed(Pool $pool): string + protected function failedToString(): string { - $failed = $pool->getFailed(); + + $failed = $this->pool->getFailed(); $status = "\nFailed status:\n\n"; diff --git a/tests/PoolTest.php b/tests/PoolTest.php index 54518a63..5c3bcf23 100644 --- a/tests/PoolTest.php +++ b/tests/PoolTest.php @@ -39,7 +39,7 @@ public function it_can_run_processes_in_parallel() $executionTime = $endTime - $startTime; - $this->assertLessThan(0.2, $executionTime, "Execution time was {$executionTime}, expected less than 0.2.\n" . PoolDebugger::statusForPool($pool)); + $this->assertLessThan(0.2, $executionTime, "Execution time was {$executionTime}, expected less than 0.2.\n" . (string) $pool->status()); } /** @test */ @@ -59,7 +59,7 @@ public function it_can_handle_success() $pool->wait(); - $this->assertEquals(10, $counter, PoolDebugger::statusForPool($pool)); + $this->assertEquals(10, $counter, (string) $pool->status()); } /** @test */ @@ -80,7 +80,7 @@ public function it_can_handle_timeout() $pool->wait(); - $this->assertEquals(5, $counter, PoolDebugger::statusForPool($pool)); + $this->assertEquals(5, $counter, (string) $pool->status()); } /** @test */ @@ -98,7 +98,7 @@ public function it_can_handle_exceptions() $pool->wait(); - $this->assertCount(5, $pool->getFailed(), PoolDebugger::statusForPool($pool)); + $this->assertCount(5, $pool->getFailed(), (string) $pool->status()); } /** @test */ @@ -121,8 +121,8 @@ public function it_can_handle_a_maximum_of_concurrent_processes() $executionTime = $endTime - $startTime; - $this->assertGreaterThanOrEqual(2, $executionTime, "Execution time was {$executionTime}, expected more than 2.\n" . PoolDebugger::statusForPool($pool)); - $this->assertCount(3, $pool->getFinished(), PoolDebugger::statusForPool($pool)); + $this->assertGreaterThanOrEqual(2, $executionTime, "Execution time was {$executionTime}, expected more than 2.\n" . (string) $pool->status()); + $this->assertCount(3, $pool->getFinished(), (string) $pool->status()); } /** @test */ @@ -144,7 +144,7 @@ public function it_works_with_helper_functions() await($pool); - $this->assertEquals(10, $counter, PoolDebugger::statusForPool($pool)); + $this->assertEquals(10, $counter, (string) $pool->status()); } /** @test */ @@ -220,4 +220,18 @@ public function it_can_check_for_asynchronous_support() { $this->assertTrue(Pool::isSupported()); } + + /** @test */ + public function it_can_show_a_textual_status() + { + $pool = Pool::create(); + + $pool->add(new MyTask()); + + $this->assertContains('finished: 0', (string) $pool->status()); + + await($pool); + + $this->assertContains('finished: 1', (string) $pool->status()); + } } From 390d4f805a9bd0d6592047545dbf3f26c8c855f2 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Jan 2018 12:48:09 +0000 Subject: [PATCH 3/8] Apply fixes from StyleCI --- src/Pool.php | 2 +- src/PoolStatus.php | 9 ++++----- tests/PoolTest.php | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Pool.php b/src/Pool.php index d648110f..a750a200 100644 --- a/src/Pool.php +++ b/src/Pool.php @@ -24,7 +24,7 @@ class Pool implements ArrayAccess /** @var \Spatie\Async\ParallelProcess[] */ protected $failed = []; - /** @var \Spatie\Async\ParallelProcess[] */ + /** @var \Spatie\Async\ParallelProcess[] */ protected $timeouts = []; protected $results = []; diff --git a/src/PoolStatus.php b/src/PoolStatus.php index 21ee53d4..038747cf 100644 --- a/src/PoolStatus.php +++ b/src/PoolStatus.php @@ -32,14 +32,13 @@ protected function summaryToString(): string $failed = $this->pool->getFailed(); $timeouts = $this->pool->getTimeouts(); - return 'finished: ' . count($finished) - . ' - failed: ' . count($failed) - . ' - timeouts: ' . count($timeouts); + return 'finished: '.count($finished) + .' - failed: '.count($failed) + .' - timeouts: '.count($timeouts); } protected function failedToString(): string { - $failed = $this->pool->getFailed(); $status = "\nFailed status:\n\n"; @@ -48,7 +47,7 @@ protected function failedToString(): string $output = $process->getErrorOutput(); if ($output instanceof SerializableException) { - $output = get_class($output->asThrowable()) . ' ' . $output->asThrowable()->getMessage(); + $output = get_class($output->asThrowable()).' '.$output->asThrowable()->getMessage(); } $status .= "{$process->getId()} failed with {$output}\n\n"; diff --git a/tests/PoolTest.php b/tests/PoolTest.php index 5c3bcf23..ffc88ae9 100644 --- a/tests/PoolTest.php +++ b/tests/PoolTest.php @@ -39,7 +39,7 @@ public function it_can_run_processes_in_parallel() $executionTime = $endTime - $startTime; - $this->assertLessThan(0.2, $executionTime, "Execution time was {$executionTime}, expected less than 0.2.\n" . (string) $pool->status()); + $this->assertLessThan(0.2, $executionTime, "Execution time was {$executionTime}, expected less than 0.2.\n".(string) $pool->status()); } /** @test */ @@ -121,7 +121,7 @@ public function it_can_handle_a_maximum_of_concurrent_processes() $executionTime = $endTime - $startTime; - $this->assertGreaterThanOrEqual(2, $executionTime, "Execution time was {$executionTime}, expected more than 2.\n" . (string) $pool->status()); + $this->assertGreaterThanOrEqual(2, $executionTime, "Execution time was {$executionTime}, expected more than 2.\n".(string) $pool->status()); $this->assertCount(3, $pool->getFinished(), (string) $pool->status()); } From 040e8b48443fe175e618145fa266e2676b7b24ce Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Jan 2018 13:57:25 +0100 Subject: [PATCH 4/8] Add failed test --- src/PoolStatus.php | 7 +++---- tests/PoolTest.php | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/PoolStatus.php b/src/PoolStatus.php index 21ee53d4..0cda3574 100644 --- a/src/PoolStatus.php +++ b/src/PoolStatus.php @@ -39,19 +39,18 @@ protected function summaryToString(): string protected function failedToString(): string { - $failed = $this->pool->getFailed(); - $status = "\nFailed status:\n\n"; + $status = ''; foreach ($failed as $process) { $output = $process->getErrorOutput(); if ($output instanceof SerializableException) { - $output = get_class($output->asThrowable()) . ' ' . $output->asThrowable()->getMessage(); + $output = get_class($output->asThrowable()) . ': ' . $output->asThrowable()->getMessage(); } - $status .= "{$process->getId()} failed with {$output}\n\n"; + $status = $this->lines($status, "{$process->getPid()} failed with {$output}"); } return $status; diff --git a/tests/PoolTest.php b/tests/PoolTest.php index 5c3bcf23..97eb04d2 100644 --- a/tests/PoolTest.php +++ b/tests/PoolTest.php @@ -234,4 +234,24 @@ public function it_can_show_a_textual_status() $this->assertContains('finished: 1', (string) $pool->status()); } + + /** @test */ + public function it_can_show_a_textual_failed_status() + { + $pool = Pool::create(); + + foreach (range(1, 5) as $i) { + $pool->add(function () { + throw new Exception('Test'); + })->catch(function () { + // Do nothing + }); + } + + $pool->wait(); + + $this->assertContains('finished: 0', (string) $pool->status()); + $this->assertContains('failed: 5', (string) $pool->status()); + $this->assertContains('failed with Exception: Test', (string) $pool->status()); + } } From 529e4bc8e85163466e206297dd659e0bd5c26e41 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Jan 2018 14:00:53 +0100 Subject: [PATCH 5/8] Refactor to PoolStatusTest --- src/PoolStatus.php | 2 +- tests/PoolStatusTest.php | 62 ++++++++++++++++++++++++++++++++++++++++ tests/PoolTest.php | 34 ---------------------- 3 files changed, 63 insertions(+), 35 deletions(-) create mode 100644 tests/PoolStatusTest.php diff --git a/src/PoolStatus.php b/src/PoolStatus.php index 8ecc7249..729fe25f 100644 --- a/src/PoolStatus.php +++ b/src/PoolStatus.php @@ -34,7 +34,7 @@ protected function summaryToString(): string return 'finished: '.count($finished) .' - failed: '.count($failed) - .' - timeouts: '.count($timeouts); + .' - timeout: '.count($timeouts); } protected function failedToString(): string diff --git a/tests/PoolStatusTest.php b/tests/PoolStatusTest.php new file mode 100644 index 00000000..2ed21cc0 --- /dev/null +++ b/tests/PoolStatusTest.php @@ -0,0 +1,62 @@ +add(new MyTask()); + + $this->assertContains('finished: 0', (string) $pool->status()); + + await($pool); + + $this->assertContains('finished: 1', (string) $pool->status()); + } + + /** @test */ + public function it_can_show_a_textual_failed_status() + { + $pool = Pool::create(); + + foreach (range(1, 5) as $i) { + $pool->add(function () { + throw new Exception('Test'); + })->catch(function () { + // Do nothing + }); + } + + $pool->wait(); + + $this->assertContains('finished: 0', (string) $pool->status()); + $this->assertContains('failed: 5', (string) $pool->status()); + $this->assertContains('failed with Exception: Test', (string) $pool->status()); + } + + /** @test */ + public function it_can_show_timeout_status() + { + $pool = Pool::create()->timeout(0); + + foreach (range(1, 5) as $i) { + $pool->add(function () { + sleep(1000); + })->catch(function () { + // Do nothing + }); + } + + $pool->wait(); + + $this->assertContains('timeout: 5', (string) $pool->status()); + } +} diff --git a/tests/PoolTest.php b/tests/PoolTest.php index f20b2be3..04de1957 100644 --- a/tests/PoolTest.php +++ b/tests/PoolTest.php @@ -220,38 +220,4 @@ public function it_can_check_for_asynchronous_support() { $this->assertTrue(Pool::isSupported()); } - - /** @test */ - public function it_can_show_a_textual_status() - { - $pool = Pool::create(); - - $pool->add(new MyTask()); - - $this->assertContains('finished: 0', (string) $pool->status()); - - await($pool); - - $this->assertContains('finished: 1', (string) $pool->status()); - } - - /** @test */ - public function it_can_show_a_textual_failed_status() - { - $pool = Pool::create(); - - foreach (range(1, 5) as $i) { - $pool->add(function () { - throw new Exception('Test'); - })->catch(function () { - // Do nothing - }); - } - - $pool->wait(); - - $this->assertContains('finished: 0', (string) $pool->status()); - $this->assertContains('failed: 5', (string) $pool->status()); - $this->assertContains('failed with Exception: Test', (string) $pool->status()); - } } From edb12f63f292ae38822b43e276d0d7311309a2d8 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Jan 2018 13:05:26 +0000 Subject: [PATCH 6/8] Apply fixes from StyleCI --- tests/PoolStatusTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PoolStatusTest.php b/tests/PoolStatusTest.php index 2ed21cc0..7de85b00 100644 --- a/tests/PoolStatusTest.php +++ b/tests/PoolStatusTest.php @@ -3,8 +3,8 @@ namespace Spatie\Async; use Exception; -use PHPUnit\Framework\TestCase; use Spatie\Async\Tests\MyTask; +use PHPUnit\Framework\TestCase; class PoolStatusTest extends TestCase { From f6bbb1ac5eab9d8a4c87c1fc586969db1ef07fe2 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Jan 2018 14:03:23 +0100 Subject: [PATCH 7/8] Code cleanup --- tests/PoolStatusTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/PoolStatusTest.php b/tests/PoolStatusTest.php index 7de85b00..ed0b5b2c 100644 --- a/tests/PoolStatusTest.php +++ b/tests/PoolStatusTest.php @@ -50,8 +50,6 @@ public function it_can_show_timeout_status() foreach (range(1, 5) as $i) { $pool->add(function () { sleep(1000); - })->catch(function () { - // Do nothing }); } From caac1e3c9b4b8f72883e5df05549cfb1a2604a86 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Tue, 2 Jan 2018 14:43:52 +0100 Subject: [PATCH 8/8] Code cleanup --- src/PoolStatus.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/PoolStatus.php b/src/PoolStatus.php index 729fe25f..c4c22f14 100644 --- a/src/PoolStatus.php +++ b/src/PoolStatus.php @@ -23,7 +23,7 @@ public function __toString(): string protected function lines(string ...$lines): string { - return implode("\n", $lines); + return implode(PHP_EOL, $lines); } protected function summaryToString(): string @@ -39,20 +39,14 @@ protected function summaryToString(): string protected function failedToString(): string { - $failed = $this->pool->getFailed(); - - $status = ''; - - foreach ($failed as $process) { + return (string) array_reduce($this->pool->getFailed(), function ($currentStatus, ParallelProcess $process) { $output = $process->getErrorOutput(); if ($output instanceof SerializableException) { $output = get_class($output->asThrowable()).': '.$output->asThrowable()->getMessage(); } - $status = $this->lines($status, "{$process->getPid()} failed with {$output}"); - } - - return $status; + return $this->lines((string) $currentStatus, "{$process->getPid()} failed with {$output}"); + }); } }