From 5c356c3f6dd287946eb0463506663d9506bd24fb Mon Sep 17 00:00:00 2001 From: Kuzia Date: Wed, 11 Jan 2023 11:04:49 +0300 Subject: [PATCH] add task callbacks --- src/Dplr/Dplr.php | 41 +++++++++++++++++++++++++++++------ src/Dplr/Task.php | 25 +++++++++++++++++++-- tests/Dplr/Tests/DplrTest.php | 37 +++++++++++++++++++++++++++++++ tests/Dplr/Tests/TaskTest.php | 30 +++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 9 deletions(-) diff --git a/src/Dplr/Dplr.php b/src/Dplr/Dplr.php index b085450..3af217e 100644 --- a/src/Dplr/Dplr.php +++ b/src/Dplr/Dplr.php @@ -23,6 +23,7 @@ class Dplr protected $servers = []; + /** @var array */ protected $tasks = []; protected $multipleThread = -1; @@ -227,8 +228,13 @@ private function addTask(Task $task): self /* * Adding command task. */ - public function command(string $command, string $serverGroup = null, int $timeout = null): self - { + public function command( + string $command, + string $serverGroup = null, + int $timeout = null, + callable $onSuccess = null, + callable $onFailure = null + ): self { $servers = null; if (null !== $serverGroup) { $servers = $this->getServersByGroup($serverGroup); @@ -246,7 +252,11 @@ public function command(string $command, string $serverGroup = null, int $timeou 'Timeout' => ($timeout > 0 ? $timeout : $this->defaultTimeout) * 1000, ]; - $this->addTask(new Task($data)); + $this->addTask(new Task( + $data, + $onSuccess, + $onFailure, + )); return $this; } @@ -254,8 +264,14 @@ public function command(string $command, string $serverGroup = null, int $timeou /* * Adding uploading task. */ - public function upload(string $localFile, string $remoteFile, string $serverGroup = null, int $timeout = null): self - { + public function upload( + string $localFile, + string $remoteFile, + string $serverGroup = null, + int $timeout = null, + callable $onSuccess = null, + callable $onFailure = null + ): self { $servers = null; if (null !== $serverGroup) { $servers = $this->getServersByGroup($serverGroup); @@ -274,7 +290,11 @@ public function upload(string $localFile, string $remoteFile, string $serverGrou 'Timeout' => ($timeout > 0 ? $timeout : $this->defaultTimeout) * 1000, ]; - $this->addTask(new Task($data)); + $this->addTask(new Task( + $data, + $onSuccess, + $onFailure, + )); return $this; } @@ -457,16 +477,22 @@ protected function runTasks(callable $callback = null): void if ('Reply' === $data['Type']) { $report = new TaskReport($data, $task); $this->reports[] = $report; - if ($callback) { $callback($report->isSuccessful() ? '.' : 'E'); } + + if ($report->isSuccessful()) { + $task->callOnSuccess(); + } else { + $task->callOnFailure(); + } } elseif ('UserError' === $data['Type']) { $this->reports[] = new TaskReport($data, $task); if ($callback) { $callback('J'); } + $task->callOnFailure(); } elseif ('FinalReply' === $data['Type']) { $hosts = $data['TimedOutHosts']; if (count($hosts)) { @@ -482,6 +508,7 @@ protected function runTasks(callable $callback = null): void if ($callback) { $callback('T'); } + $task->callOnFailure(); } } } diff --git a/src/Dplr/Task.php b/src/Dplr/Task.php index 420721d..532bb1a 100644 --- a/src/Dplr/Task.php +++ b/src/Dplr/Task.php @@ -11,9 +11,14 @@ class Task implements \JsonSerializable public const ACTIONS = [self::ACTION_SSH, self::ACTION_SCP]; protected $parameters = []; + protected $onSuccess; + protected $onFailure; - public function __construct(array $parameters) - { + public function __construct( + array $parameters, + callable $onSuccess = null, + callable $onFailure = null + ) { if (!isset($parameters['Action'])) { throw new \InvalidArgumentException('Not found `Action` parameter.'); } @@ -26,6 +31,8 @@ public function __construct(array $parameters) } $this->parameters = $parameters; + $this->onSuccess = $onSuccess; + $this->onFailure = $onFailure; } public function __toString() @@ -50,4 +57,18 @@ public function jsonSerialize(): array { return $this->parameters; } + + public function callOnSuccess(): void + { + if (null !== $this->onSuccess) { + call_user_func($this->onSuccess); + } + } + + public function callOnFailure(): void + { + if (null !== $this->onFailure) { + call_user_func($this->onFailure); + } + } } diff --git a/tests/Dplr/Tests/DplrTest.php b/tests/Dplr/Tests/DplrTest.php index cf59ffe..87c0eb7 100644 --- a/tests/Dplr/Tests/DplrTest.php +++ b/tests/Dplr/Tests/DplrTest.php @@ -47,6 +47,43 @@ public function testSuccessful(): void $this->assertEquals(".\n..\n.ssh\n", $d->getSingleReportOutput()); } + public function testTaskCallbacks(): void + { + $successes = 0; + $failures = 0; + $success = function () use (&$successes) { + ++$successes; + }; + $failure = function () use (&$failures) { + ++$failures; + }; + + $d = self::getDplr(); + $d->command('id', 'app', null, $success, $failure); + $d->command('cat doesnotexist.log', 'app', null, $success, $failure); + + $this->assertTrue($d->hasTasks()); + $d->run(); + + $this->assertFalse($d->isSuccessful()); + $this->assertFalse($d->hasTasks()); + $this->assertEquals(2, $successes); + $this->assertEquals(2, $failures); + + $report = $d->getReport(); + $this->assertEquals(4, $report['total']); + $this->assertEquals(2, $report['successful']); + $this->assertEquals(2, $report['failed']); + + $this->assertCount(2, $d->getFailed()); + foreach ($d->getFailed() as $report) { + $this->assertEquals( + 'CMD cat doesnotexist.log', + (string) $report->getTask() + ); + } + } + public function testExceptionOnSingleReportOutputWithSeveralTasks(): void { $this->expectException(OutOfRangeException::class); diff --git a/tests/Dplr/Tests/TaskTest.php b/tests/Dplr/Tests/TaskTest.php index 59213e5..4c009dd 100644 --- a/tests/Dplr/Tests/TaskTest.php +++ b/tests/Dplr/Tests/TaskTest.php @@ -49,4 +49,34 @@ public function testScpTask(): void json_encode($task) ); } + + public function testCallbacks(): void + { + $success = false; + $failure = false; + + $task = new Task( + [ + 'Action' => 'scp', + 'Source' => '/home/user1/1.txt', + 'Target' => '/home/user2/2.txt', + ], + function () use (&$success) { + $success = true; + }, + function () use (&$failure) { + $failure = true; + } + ); + + $this->assertEquals('CPY /home/user1/1.txt -> /home/user2/2.txt', (string) $task); + $this->assertJsonStringEqualsJsonString( + '{"Action":"scp","Source":"/home/user1/1.txt","Target":"/home/user2/2.txt"}', + json_encode($task) + ); + $task->callOnSuccess(); + $this->assertTrue($success); + $task->callOnFailure(); + $this->assertTrue($failure); + } }