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

Commit

Permalink
fixed #12 - added information to fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
mickaelandrieu committed Jul 30, 2019
1 parent 2007df1 commit 4dd5226
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 14 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ $circuitBreaker = new MainCircuitBreaker(
$dispatcher
);

$fallbackResponse = function () {
/**
* @var Service $service
*/
$fallbackResponse = function ($service) {
return '{}';
};

Expand Down
23 changes: 23 additions & 0 deletions src/Places/AbstractPlace.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Resiliency\Contracts\Event;
use Resiliency\Exceptions\InvalidPlace;
use Resiliency\Utils\Assert;
use DateTime;

abstract class AbstractPlace implements Place
{
Expand Down Expand Up @@ -104,6 +105,16 @@ public function isAllowedToRetry(Transaction $transaction): bool
return $transaction->getFailures() < $this->failures;
}

/**
* @param Transaction $transaction the Transaction
*
* @return bool
*/
public function haveWaitedLongEnough(Transaction $transaction): bool
{
return $transaction->getThresholdDateTime() < new DateTime();
}

/**
* Helper to dispatch transition events.
*
Expand All @@ -117,6 +128,18 @@ protected function dispatch(Event $event): void
;
}

/**
* Helper to return the fallback Response.
*
* @return string the configurated fallback
*/
protected function useFallback(Transaction $transaction, callable $fallback): string
{
$service = $transaction->getService();

return (string) $fallback($service);
}

/**
* Ensure the place is valid
*
Expand Down
2 changes: 1 addition & 1 deletion src/Places/Isolated.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ public function getState(): string
*/
public function call(Transaction $transaction, callable $fallback): string
{
return (string) $fallback();
return $this->useFallback($transaction, $fallback);
}
}
5 changes: 2 additions & 3 deletions src/Places/Opened.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Resiliency\Contracts\Transaction;
use Resiliency\Events\Opened as OpenedEvent;
use Resiliency\States;
use DateTime;

/**
* While the circuit is in an open state: every call to the service
Expand Down Expand Up @@ -37,8 +36,8 @@ public function call(Transaction $transaction, callable $fallback): string
$service = $transaction->getService();
$this->dispatch(new OpenedEvent($this->circuitBreaker, $service));

if (!($transaction->getThresholdDateTime() < new DateTime())) {
return (string) $fallback();
if (!$this->haveWaitedLongEnough($transaction)) {
return $this->useFallback($transaction, $fallback);
}

$this->circuitBreaker->moveStateTo(States::HALF_OPEN_STATE, $service);
Expand Down
18 changes: 9 additions & 9 deletions tests/CircuitBreakerWorkflowTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function testCircuitBreakerIsInClosedStateAtStart(): void
$this->assertInstanceOf(Closed::class, $this->circuitBreaker->getState());

$this->assertSame(
'{}',
'{"uri": https://httpbin.org/get/foo"}',
$this->circuitBreaker->call(
'https://httpbin.org/get/foo',
$this->createFallbackResponse()
Expand All @@ -54,12 +54,12 @@ public function testCircuitBreakerWillBeOpenInCaseOfFailures(): void
// CLOSED
$this->assertInstanceOf(Closed::class, $this->circuitBreaker->getState());
$response = $this->circuitBreaker->call('https://httpbin.org/get/foo', $this->createFallbackResponse());
$this->assertSame('{}', $response);
$this->assertSame('{"uri": https://httpbin.org/get/foo"}', $response);

//After two failed calls switch to OPEN state
$this->assertInstanceOf(Opened::class, $this->circuitBreaker->getState());
$this->assertSame(
'{}',
'{"uri": https://httpbin.org/get/foo"}',
$this->circuitBreaker->call(
'https://httpbin.org/get/foo',
$this->createFallbackResponse()
Expand All @@ -81,12 +81,12 @@ public function testOnceInHalfOpenModeServiceIsFinallyReachable(): void
// CLOSED - first call fails (twice)
$this->assertInstanceOf(Closed::class, $this->circuitBreaker->getState());
$response = $this->circuitBreaker->call('https://httpbin.org/get/foo', $this->createFallbackResponse());
$this->assertSame('{}', $response);
$this->assertSame('{"uri": https://httpbin.org/get/foo"}', $response);
$this->assertInstanceOf(Opened::class, $this->circuitBreaker->getState());

// OPEN - no call to client
$response = $this->circuitBreaker->call('https://httpbin.org/get/foo', $this->createFallbackResponse());
$this->assertSame('{}', $response);
$this->assertSame('{"uri": https://httpbin.org/get/foo"}', $response);
$this->assertInstanceOf(Opened::class, $this->circuitBreaker->getState());
$this->waitFor(2 * self::OPEN_THRESHOLD);

Expand Down Expand Up @@ -114,14 +114,14 @@ public function testOnceCircuitBreakerIsIsolatedNoTrialsAreDone(): void
$this->circuitBreaker->isolate($uri);

$response = $this->circuitBreaker->call($uri, $this->createFallbackResponse());
$this->assertSame('{}', $response);
$this->assertSame('{"uri": https://httpbin.org/get/foo"}', $response);
$this->assertInstanceOf(Isolated::class, $this->circuitBreaker->getState());

// Let's do 5 calls!

for ($i = 0; $i < 5; ++$i) {
$this->circuitBreaker->call($uri, $this->createFallbackResponse());
$this->assertSame('{}', $response);
$this->assertSame('{"uri": https://httpbin.org/get/foo"}', $response);
$this->assertInstanceOf(Isolated::class, $this->circuitBreaker->getState());
}

Expand Down Expand Up @@ -163,8 +163,8 @@ private function createCircuitBreaker(): MainCircuitBreaker
*/
private function createFallbackResponse(): callable
{
return function () {
return '{}';
return function ($service) {
return '{"uri": ' . $service->getUri() . '"}';
};
}
}

0 comments on commit 4dd5226

Please sign in to comment.