Skip to content
This repository has been archived by the owner on Aug 17, 2022. It is now read-only.

Commit

Permalink
Merge pull request #62 from loveOSS/added-failed-event
Browse files Browse the repository at this point in the history
[FEAT] Be able to get information about the exception thrown in case of failure
  • Loading branch information
mickaelandrieu authored Jan 24, 2022
2 parents caeb7e4 + 1bea62b commit 8fbf09e
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Resiliency, an implementation for resilient and modern PHP applications

[![codecov](https://codecov.io/gh/loveOSS/resiliency/branch/master/graph/badge.svg)](https://codecov.io/gh/loveOSS/resiliency) [![PHPStan](https://img.shields.io/badge/PHPStan-Level%207-brightgreen.svg?style=flat&logo=php)](https://shields.io/#/) [![Psalm](https://img.shields.io/badge/Psalm-Level%20Max-brightgreen.svg?style=flat&logo=php)](https://shields.io/#/) [![Build Status](https://travis-ci.com/loveOSS/resiliency.svg?branch=master)](https://travis-ci.com/loveOSS/resiliency)
[![codecov](https://codecov.io/gh/loveOSS/resiliency/branch/master/graph/badge.svg)](https://codecov.io/gh/loveOSS/resiliency) [![PHPStan](https://img.shields.io/badge/PHPStan-Level%20max-brightgreen.svg?style=flat&logo=php)](https://shields.io/#/) [![Psalm](https://img.shields.io/badge/Psalm-Level%20Max-brightgreen.svg?style=flat&logo=php)](https://shields.io/#/) [![Build Status](https://travis-ci.com/loveOSS/resiliency.svg?branch=master)](https://travis-ci.com/loveOSS/resiliency)

## Main principles

Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^8.0",
"symfony/cache": "~4.4|~5.3",
"symfony/http-client": "^4.4|~5.3",
"symfony/cache": "~4.4|~5.4|~6.0",
"symfony/http-client": "^4.4|~5.4|~6.0",
"vimeo/psalm": "^4.3"
},
"suggest": {
Expand All @@ -49,7 +49,7 @@
},
"scripts": {
"cs-fix": "@php ./vendor/bin/php-cs-fixer fix",
"phpqa": "@php ./vendor/bin/phpqa --report --tools phpcs:0,phpmd:0,phpmetrics,phploc,pdepend,security-checker:0,parallel-lint:0 --ignoredDirs tests,vendor",
"phpqa": "@php ./vendor/bin/phpqa --report --tools phpcs:0,phpmetrics,phploc,pdepend,security-checker:0,parallel-lint:0 --ignoredDirs tests,vendor",
"phpstan": "@php ./vendor/bin/phpstan analyse src --level max -c extension.neon",
"psalm": "@php ./vendor/bin/psalm --threads=8 --diff",
"test": "@php ./vendor/bin/phpunit"
Expand Down
1 change: 0 additions & 1 deletion psalm.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
name="Psalm configuration for the Resiliency library"
totallyTyped="true"
strictBinaryOperands="true"
allowPhpStormGenerics="true"
allowStringToStandInForClass="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
Expand Down
14 changes: 14 additions & 0 deletions src/Contracts/ThrowableEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Resiliency\Contracts;

/**
* Specific event in case of failure.
*/
interface ThrowableEvent extends Event
{
/**
* @return Exception the Exception
*/
public function getException(): Exception;
}
34 changes: 34 additions & 0 deletions src/Events/Failed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Resiliency\Events;

use Resiliency\Contracts\CircuitBreaker;
use Resiliency\Contracts\Exception;
use Resiliency\Contracts\Service;
use Resiliency\Contracts\ThrowableEvent;

final class Failed extends TransitionEvent implements ThrowableEvent
{
/**
* We need to understand why a call have failed.
*
* @var Exception the exception
*/
private $exception;

/**
* @param CircuitBreaker $circuitBreaker the circuit breaker
* @param Service $service the Service
*/
public function __construct(CircuitBreaker $circuitBreaker, Service $service, Exception $exception)
{
$this->exception = $exception;

parent::__construct($circuitBreaker, $service);
}

public function getException(): Exception
{
return $this->exception;
}
}
2 changes: 2 additions & 0 deletions src/Places/Closed.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Resiliency\Contracts\Client;
use Resiliency\Contracts\Transaction;
use Resiliency\Events\Failed;
use Resiliency\Events\Tried;
use Resiliency\Exceptions\UnavailableService;
use Resiliency\States;
Expand Down Expand Up @@ -55,6 +56,7 @@ public function call(Transaction $transaction, callable $fallback): string

return $response;
} catch (UnavailableService $exception) {
$this->dispatch(new Failed($this->circuitBreaker, $service, $exception));
$transaction->incrementFailures();
$storage->saveTransaction($service->getUri(), $transaction);

Expand Down
2 changes: 1 addition & 1 deletion src/Systems/MainSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private static function validateTimeout(int $timeout): bool
{
// @doc https://www.php.net/manual/info.configuration.php the timeout is in seconds
$maxExecutionTime = ini_get('max_execution_time');

$timeoutInSeconds = (int) ($timeout / 1000);

return (0 === (int) $maxExecutionTime) || ($maxExecutionTime >= $timeoutInSeconds);
Expand Down
17 changes: 10 additions & 7 deletions tests/SymfonyCircuitBreakerEventsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use ReflectionClass;
use ReflectionException;
use Resiliency\Contracts\CircuitBreaker;
use Resiliency\Events\Failed;
use Resiliency\Events\Initiated;
use Resiliency\Events\Isolated;
use Resiliency\Events\Opened;
Expand Down Expand Up @@ -54,12 +55,14 @@ public function testCircuitBreakerEventsOnFirstFailedCall(): void
* then the conditions are met to open the circuit breaker
*/
$invocations = self::invocations($this->spy);
self::assertCount(4, $invocations);
self::assertCount(6, $invocations);

self::assertInstanceOf(Initiated::class, $invocations[0]->getParameters()[0]);
self::assertInstanceOf(Tried::class, $invocations[1]->getParameters()[0]);
self::assertInstanceOf(Tried::class, $invocations[2]->getParameters()[0]);
self::assertInstanceOf(Opened::class, $invocations[3]->getParameters()[0]);
self::assertInstanceOf(Failed::class, $invocations[2]->getParameters()[0]);
self::assertInstanceOf(Tried::class, $invocations[3]->getParameters()[0]);
self::assertInstanceOf(Failed::class, $invocations[4]->getParameters()[0]);
self::assertInstanceOf(Opened::class, $invocations[5]->getParameters()[0]);
}

public function testCircuitBreakerEventsOnIsolationAndResetActions(): void
Expand All @@ -79,17 +82,17 @@ public function testCircuitBreakerEventsOnIsolationAndResetActions(): void
* the related event has been dispatched
*/
$invocations = self::invocations($this->spy);
self::assertCount(5, $invocations);
self::assertInstanceOf(Isolated::class, $invocations[4]->getParameters()[0]);
self::assertCount(7, $invocations);
self::assertInstanceOf(Isolated::class, $invocations[6]->getParameters()[0]);

/*
* And now we reset the circuit breaker!
* The related event must be dispatched
*/
$circuitBreaker->reset($service);
$invocations = self::invocations($this->spy);
self::assertCount(6, $invocations);
self::assertInstanceOf(Reseted::class, $invocations[5]->getParameters()[0]);
self::assertCount(8, $invocations);
self::assertInstanceOf(Reseted::class, $invocations[7]->getParameters()[0]);
}

private function createCircuitBreaker(): CircuitBreaker
Expand Down

0 comments on commit 8fbf09e

Please sign in to comment.