Skip to content

Instantly share code, notes, and snippets.

@alsma
Last active January 6, 2016 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alsma/7eb31dc027fc0a295927 to your computer and use it in GitHub Desktop.
Save alsma/7eb31dc027fc0a295927 to your computer and use it in GitHub Desktop.
Chain of responsibility
<?php
namespace models\Instant\Action;
interface ActionInterface
{
/**
* Executes action
*
* @param array $args
*
* @return mixed
*/
public function execute(array $args = []);
}
<?php
namespace models\Instant\Action;
class CacheAction extends ChainedAction
{
/** @var \Redis */
private $redis;
/** @var string */
private $key;
/** @var int */
private $ttl;
/**
* @param \Redis $redis
* @param string $key
* @param int $ttl
*/
public function __construct(\Redis $redis, $key, $ttl)
{
$this->redis = $redis;
$this->key = $key;
$this->ttl = $ttl;
}
/**
* @param mixed $value
*/
public function save($value)
{
$this->redis->set($this->key, json_encode($value), $this->ttl);
}
/**
* {@inheritdoc}
*/
protected function doExecute(array $args)
{
if (!$this->redis->exists($this->key)) {
throw new \RuntimeException("No cache data in {$this->key}");
}
return json_decode($this->redis->get($this->key), true);
}
}
<?php
namespace models\Instant\Action;
class CallableAction extends ChainedAction
{
/** @var callable */
private $callable;
/**
* @param callable $callable
*/
public function __construct(callable $callable)
{
$this->callable = $callable;
}
/**
* {@inheritdoc}
*/
public function doExecute(array $args)
{
return call_user_func_array($this->callable, $args);
}
}
<?php
namespace models\Instant\Action;
abstract class ChainedAction implements ActionInterface
{
/** @var ActionInterface */
private $next;
/** @var ActionInterface */
private $successor;
/**
* @param ActionInterface $next
*/
public function setNext(ActionInterface $next)
{
$this->next = $next;
}
/**
* @param ActionInterface $successor
*/
public function setSuccessor(ActionInterface $successor)
{
$this->successor = $successor;
}
/**
* {@inheritdoc}
*/
public function execute(array $args = [])
{
try {
$result = $this->doExecute($args);
$result = $this->trySuccess($result, $args);
} catch (\Exception $e) {
if (!$this->next) {
throw $e;
}
$result = $this->next->execute($args);
}
return $result;
}
/**
* @param array $args
*
* @return mixed
*/
abstract protected function doExecute(array $args);
/**
* @param mixed $result
* @param array $args
*
* @return mixed
*/
private function trySuccess($result, array $args)
{
if (!$this->successor) {
return $result;
}
array_unshift($args, $result);
return $this->successor->execute($args);
}
}
<?php
$c1 = new CacheAction(\Red::getInstance(), "c1:depth:{$pair}", 10);
$c2 = new CacheAction(\Red::getInstance(), "c2:depth:{$pair}", 3600);
$loader = new CallableAction(function ($pair) {
return uniqid($pair, true);
});
$cacheUpdater = new CallableAction(function ($result) use ($c1, $c2) {
$c1->save($result);
$c2->save($result);
return $result;
});
$c1->setNext($loader);
$loader->setNext($c2);
$loader->setSuccessor($cacheUpdater);
var_dump($c1->execute(['btc_usd']));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment