Skip to content
This repository was archived by the owner on Feb 6, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@
build/
composer.lock
nbproject
tmp/
tmp/
vendor/
.phpunit.result.cache
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Notice, the extra parameters you pass to the factory’s getCommand method are f
The factory is instantiated as follows:

```php
use Zend\Config\Config;
use Laminas\Config\Config;
use Odesk\Phystrix\ApcStateStorage;
use Odesk\Phystrix\CircuitBreakerFactory;
use Odesk\Phystrix\CommandMetricsFactory;
Expand All @@ -87,12 +87,12 @@ $circuitBreakerFactory = new CircuitBreakerFactory($stateStorage);
$commandMetricsFactory = new CommandMetricsFactory($stateStorage);

$phystrix = new CommandFactory(
$config, new \Zend\Di\ServiceLocator(), $circuitBreakerFactory, $commandMetricsFactory,
$config, new \Laminas\Di\ServiceLocator(), $circuitBreakerFactory, $commandMetricsFactory,
new \Odesk\Phystrix\RequestCache(), new \Odesk\Phystrix\RequestLog()
);
```

The way you store the configuration files is up to you. Phystrix relies on [Zend\Config](https://github.com/zendframework/Component_ZendConfig) to manage configurations. In this case, __phystrix-config.php__ is a PHP array:
The way you store the configuration files is up to you. Phystrix relies on [Laminas\Config](https://github.com/zendframework/Component_ZendConfig) to manage configurations. In this case, __phystrix-config.php__ is a PHP array:

```php
return array(
Expand Down Expand Up @@ -160,7 +160,7 @@ Phystrix only works with the command keys. If you have two different commands wi
Sometimes, you may need to change a parameter when a command is used in a particular context:

```php
use Zend\Config\Config;
use Laminas\Config\Config;
$myCommand = $phystrix->getCommand('MyCommand', 'Alex');
$myCommand->setConfig(new Config(array('requestCache' => array('enabled' => false))));
$result = $myCommand->execute();
Expand Down Expand Up @@ -258,7 +258,7 @@ where “timeout” is a custom parameter which Phystrix does not make any use o
}
```

where the client might be a 3rd library you downloaded, or an instance of http client from a framework such as Zend Framework or Symfony or something you wrote yourself.
where the client might be a 3rd library you downloaded, or an instance of http client from a framework such as Laminas Framework or Symfony or something you wrote yourself.

Of course, having to add this into each command would be suboptimal. Normally, you will have a set of abstract commands, specific to your use cases. E.g. you might have __GenericCurlCommand__ or __GenericGoogleApiCommand__ and __MyCommand__ would extend one of those.

Expand All @@ -270,10 +270,10 @@ One way would be to extend the __Odesk\Phystrix\CommandFactory__, create your ow

Alternatively, configure the locator instance that __Odesk\Phystrix\CommandFactory__ accepts in the constructor.

The service locator can be anything, implementing the very basic [Zend\Di\LocatorInterface](https://github.com/zendframework/zf2/blob/master/library/Zend/Di/LocatorInterface.php). You can inject an IoC container that will lazily instantiate instance as they are needed, or you can use a simpler, preconfigured, instance of __Zend\Di\ServiceLocator__:
The service locator can be anything, implementing the very basic [Laminas\Di\LocatorInterface](https://github.com/zendframework/zf2/blob/master/library/Zend/Di/LocatorInterface.php). You can inject an IoC container that will lazily instantiate instance as they are needed, or you can use a simpler, preconfigured, instance of __Laminas\Di\ServiceLocator__:

```php
$serviceLocator = \Zend\Di\ServiceLocator();
$serviceLocator = \Laminas\Di\ServiceLocator();
$googleApiRemoteService = new GoogleApi(...);
$serviceLocator->set('googleApi', $googleApiRemoteService);

Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
}
},
"require": {
"php": ">=5.3.3",
"zendframework/zend-config": "~2.2",
"zendframework/zend-di": "~2.2"
"php": ">=7.4",
"laminas/laminas-config": "~2.2",
"laminas/laminas-di": "~2.2"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
"roave/security-advisories": "dev-latest",
"phpunit/phpunit": "^9.5"
},
"extra": {
"branch-alias": {
Expand Down
33 changes: 18 additions & 15 deletions library/Odesk/Phystrix/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
use Odesk\Phystrix\Exception\BadRequestException;
use Odesk\Phystrix\Exception\FallbackNotAvailableException;
use Odesk\Phystrix\Exception\RuntimeException;
use Zend\Di\LocatorInterface;
use Zend\Config\Config;
use Laminas\Di\LocatorInterface;
use Laminas\Config\Config;
use Exception;

/**
Expand Down Expand Up @@ -95,7 +95,7 @@ abstract class AbstractCommand
/**
* Exception thrown if there was one
*
* @var \Exception
* @var Exception
*/
private $executionException;

Expand All @@ -108,17 +108,15 @@ abstract class AbstractCommand

/**
* Determines and returns command key, used for circuit breaker grouping and metrics tracking
*
* @return string
*/
public function getCommandKey()
public function getCommandKey(): string
{
if ($this->commandKey) {
return $this->commandKey;
} else {
// If the command key hasn't been defined in the class we use the current class name
return get_class($this);
}

// If the command key hasn't been defined in the class we use the current class name
return get_class($this);
}

/**
Expand Down Expand Up @@ -168,13 +166,13 @@ public function setRequestLog(RequestLog $requestLog)
*/
public function initializeConfig(Config $phystrixConfig)
{
$commandKey = $this->getCommandKey();
$config = new Config($phystrixConfig->get('default')->toArray(), true);
if ($phystrixConfig->__isset($commandKey)) {
$commandConfig = $phystrixConfig->get($commandKey);
$config->merge($commandConfig);
$key = $this->getCommandKey();
$configuration = new Config($phystrixConfig->get('default')->toArray(), true);
if ($phystrixConfig->__isset($key)) {
$commandConfig = $phystrixConfig->get($key);
$configuration->merge($commandConfig);
}
$this->config = $config;
$this->config = $configuration;
}

/**
Expand All @@ -192,6 +190,11 @@ public function setConfig(Config $config, $merge = true)
}
}

public function getConfig(): Config
{
return $this->config;
}

/**
* Determines whether request caching is enabled for this command
*
Expand Down
2 changes: 1 addition & 1 deletion library/Odesk/Phystrix/ApcStateStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public function allowSingleTest($commandKey, $sleepingWindowInMilliseconds)
// using 'add' enforces thread safety.
$sleepingWindowInSeconds = ceil($sleepingWindowInMilliseconds / 1000);
// another APC limitation is that within the current request variables will never expire.
return (boolean) apc_add($singleTestFlagKey, true, $sleepingWindowInSeconds);
return apc_add($singleTestFlagKey, true, $sleepingWindowInSeconds);
}

/**
Expand Down
4 changes: 1 addition & 3 deletions library/Odesk/Phystrix/ArrayStateStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ class ArrayStateStorage implements StateStorageInterface
*/
public function getBucket($commandKey, $type, $index)
{
return isset($this->buckets[$commandKey][$type][$index])
? $this->buckets[$commandKey][$type][$index]
: null;
return $this->buckets[$commandKey][$type][$index] ?? null;
}

/**
Expand Down
65 changes: 24 additions & 41 deletions library/Odesk/Phystrix/CircuitBreaker.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
namespace Odesk\Phystrix;

use Zend\Config\Config;
use Laminas\Config\Config;

/**
* Circuit-breaker logic that is hooked into AbstractCommand execution and will stop allowing executions
Expand All @@ -29,40 +29,17 @@
*/
class CircuitBreaker implements CircuitBreakerInterface
{
/**
* @var CommandMetrics
*/
private $metrics;

/**
* Phystrix config
*
* @var Config
*/
private $config;

/**
* @var StateStorageInterface
*/
private $stateStorage;
private CommandMetrics $metrics;
private Config $config;
private StateStorageInterface $stateStorage;

/**
* String identifier of the group of commands this circuit breaker is responsible for
*
* @var string
*/
private $commandKey;
private string $commandKey;

/**
* Constructor
*
* @param string $commandKey
* @param CommandMetrics $metrics
* @param Config $commandConfig
* @param StateStorageInterface $stateStorage
*/
public function __construct(
$commandKey,
string $commandKey,
CommandMetrics $metrics,
Config $commandConfig,
StateStorageInterface $stateStorage
Expand All @@ -73,6 +50,16 @@ public function __construct(
$this->stateStorage = $stateStorage;
}

public function getConfig(): Config
{
return $this->config;
}

public function getCommandKey(): string
{
return $this->commandKey;
}

/**
* Whether the circuit is open
*
Expand All @@ -96,21 +83,19 @@ public function isOpen()
$allowedErrorPercentage = $this->config->get('circuitBreaker')->get('errorThresholdPercentage');
if ($healthCounts->getErrorPercentage() < $allowedErrorPercentage) {
return false;
} else {
$this->stateStorage->openCircuit(
$this->commandKey,
$this->config->get('circuitBreaker')->get('sleepWindowInMilliseconds')
);
return true;
}

$this->stateStorage->openCircuit(
$this->commandKey,
$this->config->get('circuitBreaker')->get('sleepWindowInMilliseconds')
);
return true;
}

/**
* Whether a single test is allowed now
*
* @return boolean
*/
public function allowSingleTest()
public function allowSingleTest(): bool
{
return $this->stateStorage->allowSingleTest(
$this->commandKey,
Expand All @@ -120,10 +105,8 @@ public function allowSingleTest()

/**
* Whether the request is allowed
*
* @return boolean
*/
public function allowRequest()
public function allowRequest(): bool
{
if ($this->config->get('circuitBreaker')->get('forceOpen')) {
return false;
Expand Down
18 changes: 3 additions & 15 deletions library/Odesk/Phystrix/CircuitBreakerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,16 @@
*/
namespace Odesk\Phystrix;

use Zend\Config\Config;
use Laminas\Config\Config;

/**
* Factory to keep track of and instantiate new circuit breakers when needed
*/
class CircuitBreakerFactory
{
/**
* @var array
*/
protected $circuitBreakersByCommand = array();

/**
* @var StateStorageInterface
*/
protected $stateStorage;
protected array $circuitBreakersByCommand = [];
protected StateStorageInterface $stateStorage;

/**
* Constructor
*
* @param StateStorageInterface $stateStorage
*/
public function __construct(StateStorageInterface $stateStorage)
{
$this->stateStorage = $stateStorage;
Expand Down
4 changes: 2 additions & 2 deletions library/Odesk/Phystrix/CommandFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
namespace Odesk\Phystrix;

use ReflectionClass;
use Zend\Config\Config;
use Zend\Di\LocatorInterface;
use Laminas\Config\Config;
use Laminas\Di\LocatorInterface;

/**
* All commands must be created through this factory.
Expand Down
Loading