Skip to content

Commit

Permalink
🔨 [Healthcheck] Introduce a Destination value object
Browse files Browse the repository at this point in the history
Thus don't repeating ourself in destination validation
  • Loading branch information
shouze committed Dec 1, 2017
1 parent 80932b9 commit 680d0d6
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 56 deletions.
45 changes: 45 additions & 0 deletions Destination.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/*
* This file is part of the Ubirak package.
*
* (c) Ubirak team <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Ubirak\Component\Healthcheck;

final class Destination
{
private $uri;

/**
* Informs if a destination is reachable
*
* @param string $destination A destination to join for the health check
*
* @throws InvalidDestination when the destination is not supported.
*/
public function __construct(string $uri)
{
$this->uri = filter_var($uri, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);

if ($this->uri === false) {
throw InvalidDestination::forUri($uri);
}
}

public function parse(): array
{
return parse_url($this->uri);
}

public function __toString(): string
{
return $this->uri;
}
}
5 changes: 2 additions & 3 deletions Healthcheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ interface Healthcheck
/**
* Informs if a destination is reachable
*
* @param string $destination A destination to join for the health check
* @param Destination $destination A destination to join for the health check
*
* @throws InvalidDestination when the destination is not supported by health check implementation.
* @throws HealthcheckFailure when a non expected health check failure occurs.
*/
public function isReachable(string $destination): bool;
public function isReachable(Destination $destination): bool;
}
15 changes: 6 additions & 9 deletions HttpHealthcheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,22 @@ public function __construct(HttpClient $httpClient, LoggerInterface $logger = nu
$this->logger = $logger ?? new NullLogger();
}

public function isReachable(string $destination): bool
public function isReachable(Destination $destination): bool
{
if (false === filter_var($destination, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)) {
throw InvalidDestination::ofProtocol('http');
}

$this->logger->info('Start HTTP healthcheck', ['destination' => $destination]);
$url = (string) $destination;
$this->logger->info('Start HTTP healthcheck', ['destination' => $url]);

try {
$response = $this->httpClient->sendRequest(new Request('GET', $destination));
$response = $this->httpClient->sendRequest(new Request('GET', $url));
} catch (\Exception $e) {
$this->logger->info('[Fail] HTTP healthcheck', ['destination' => $destination]);
$this->logger->info('[Fail] HTTP healthcheck', ['destination' => $url]);
return false;
}

$result = 200 === $response->getStatusCode();
$resultAsString = $result ? 'OK' : 'Fail';

$this->logger->info("[${resultAsString}] HTTP healthcheck", ['destination' => $destination]);
$this->logger->info("[${resultAsString}] HTTP healthcheck", ['destination' => $url]);

return $result;
}
Expand Down
4 changes: 2 additions & 2 deletions InvalidDestination.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

final class InvalidDestination extends \InvalidArgumentException
{
public static function ofProtocol(string $protocol)
public static function forUri(string $uri)
{
return new static("Destination must be a valid ${protocol} uri.");
return new static("Invalid destination: $uri.");
}
}
11 changes: 4 additions & 7 deletions TcpHealthcheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,9 @@ public function __construct(float $initialExponent, float $step, float $maxExecu
$this->logger = $logger ?? new NullLogger();
}

public function isReachable(string $destination): bool
public function isReachable(Destination $destination): bool
{
if (false === filter_var($destination, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)) {
throw InvalidDestination::ofProtocol('tcp');
}
['host' => $host, 'port' => $port] = parse_url($destination);
['host' => $host, 'port' => $port] = $destination->parse();
$uri = "tcp://${host}:${port}";

$this->logger->info('Start TCP healthcheck', ['destination' => $uri]);
Expand All @@ -71,10 +68,10 @@ public function isReachable(string $destination): bool
@fclose($socket);
return true;
}));
$this->logger->info('[OK] TCP healthcheck', ['destination' => $destination]);
$this->logger->info('[OK] TCP healthcheck', ['destination' => $uri]);
return true;
} catch (\Exception $e) {
$this->logger->info('[Fail] TCP healthcheck', ['destination' => $destination]);
$this->logger->info('[Fail] TCP healthcheck', ['destination' => $uri]);
return false;
}
}
Expand Down
43 changes: 43 additions & 0 deletions tests/Units/Destination.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* This file is part of the Ubirak package.
*
* (c) Ubirak team <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Ubirak\Component\Healthcheck\Tests\Units;

use atoum;

class Destination extends atoum
{
/**
* @dataProvider invalidUri
*/
public function test it fails with invalid uri($uri)
{
$this
->exception(function () use ($uri) {
$this->newTestedInstance($uri);
})
->hasMessage("Invalid destination: $uri.");
;
}

protected function invalidUri(): array
{
return [
'whithout scheme' => ['localhost'],
'whithout host #1' => ['http://'],
'whithout host #2' => ['https://'],
'whithout host #3' => ['tcp://'],
'empty' => [''],
];
}
}
19 changes: 3 additions & 16 deletions tests/Units/HttpHealthcheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
namespace Ubirak\Component\Healthcheck\Tests\Units;

use atoum;
use Ubirak\Component\Healthcheck\Destination;

class HttpHealthcheck extends atoum
{
/**
* @dataProvider reachability
*/
public function test reachability(string $destination, int $statusCode, bool $expectedReachability)
public function test reachability(string $uri, int $statusCode, bool $expectedReachability)
{
$this
->given(
Expand All @@ -32,7 +33,7 @@ public function test reachability(string $destination, int $statusCode, bool $e
$this->calling($response)->getStatusCode = $statusCode
)
->when(
$reachable = $this->testedInstance->isReachable($destination)
$reachable = $this->testedInstance->isReachable(new Destination($uri))
)
->then
->boolean($reachable)->isIdenticalTo($expectedReachability)
Expand All @@ -42,20 +43,6 @@ public function test reachability(string $destination, int $statusCode, bool $e
;
}

public function test it requires complete uri()
{
$this
->given(
$httpClient = new \mock\Http\Client\HttpClient(),
$this->newTestedInstance($httpClient)
)
->exception(function () {
$this->testedInstance->isReachable('localhost');
})
->hasMessage('Destination must be a valid http uri.')
;
}

protected function reachability(): array
{
return [
Expand Down
29 changes: 10 additions & 19 deletions tests/Units/TcpHealthcheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Ubirak\Component\Healthcheck\Tests\Units;

use atoum;
use Ubirak\Component\Healthcheck\Destination;

class TcpHealthcheck extends atoum
{
Expand All @@ -22,10 +23,11 @@ public function test it tries multiple time to create socket()
$this
->given(
$this->function->stream_socket_client = false,
$this->newTestedInstance(0.5, 0.5, 3.0)
$this->newTestedInstance(0.5, 0.5, 3.0),
$destination = new Destination('tcp://localhost:1000')
)
->when(
$result = $this->testedInstance->isReachable('tcp://localhost:1000')
$result = $this->testedInstance->isReachable($destination)
)
->then
->boolean($result)
Expand All @@ -40,10 +42,11 @@ public function test first successful try is enough()
->given(
$this->function->stream_socket_client = true,
$this->function->fclose = true,
$this->newTestedInstance(0.5, 0.5, 3.0)
$this->newTestedInstance(0.5, 0.5, 3.0),
$destination = new Destination('http://localhost:1000')
)
->when(
$result = $this->testedInstance->isReachable('http://localhost:1000')
$result = $this->testedInstance->isReachable($destination)
)
->then
->boolean($result)
Expand All @@ -59,28 +62,16 @@ public function test next successful try is enough()
$this->function->stream_socket_client = false,
$this->function->stream_socket_client[2] = true,
$this->function->fclose = true,
$this->newTestedInstance(0.5, 0.5, 3.0)
$this->newTestedInstance(0.5, 0.5, 3.0),
$destination = new Destination('http://localhost:1000')
)
->when(
$result = $this->testedInstance->isReachable('http://localhost:1000')
$result = $this->testedInstance->isReachable($destination)
)
->then
->boolean($result)
->isTrue()
->function('stream_socket_client')->wasCalled()->twice()
;
}

public function test it requires complete uri()
{
$this
->given(
$this->newTestedInstance(0.5, 0.5, 3.0)
)
->exception(function () {
$this->testedInstance->isReachable('localhost');
})
->hasMessage('Destination must be a valid tcp uri.')
;
}
}

0 comments on commit 680d0d6

Please sign in to comment.