-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from tompedals/feature/poller
Add non-blocking poller
- Loading branch information
Showing
16 changed files
with
785 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
namespace Radish\Broker; | ||
|
||
class QueueLoader | ||
{ | ||
/** | ||
* @var QueueRegistry | ||
*/ | ||
private $queueRegistry; | ||
|
||
/** | ||
* @param QueueRegistry $queueRegistry | ||
*/ | ||
public function __construct(QueueRegistry $queueRegistry) | ||
{ | ||
$this->queueRegistry = $queueRegistry; | ||
} | ||
/** | ||
* @param array $queueNames | ||
* @return QueueCollection | ||
*/ | ||
public function load(array $queueNames) | ||
{ | ||
$queues = new QueueCollection(); | ||
|
||
foreach ($queueNames as $queueName) { | ||
$queues->add($this->queueRegistry->get($queueName)); | ||
} | ||
|
||
return $queues; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
<?php | ||
|
||
namespace Radish\Consumer; | ||
|
||
use Psr\Log\LoggerInterface; | ||
use Radish\Broker\QueueCollection; | ||
use Radish\Middleware\InitializableInterface; | ||
use Radish\Middleware\MiddlewareInterface; | ||
use Radish\Middleware\Next; | ||
use Radish\Middleware\SleepyMiddlewareInterface; | ||
use RuntimeException; | ||
|
||
class Poller implements ConsumerInterface | ||
{ | ||
protected $queues; | ||
protected $middlewares; | ||
protected $workers; | ||
protected $logger; | ||
protected $interval; | ||
protected $waiting = false; | ||
|
||
/** | ||
* @param QueueCollection $queues | ||
* @param MiddlewareInterface[] $middlewares | ||
* @param array $workers | ||
* @param int $interval | ||
* @param LoggerInterface|null $logger | ||
*/ | ||
public function __construct(QueueCollection $queues, array $middlewares, array $workers, $interval = 10, LoggerInterface $logger = null) | ||
{ | ||
$this->queues = $queues; | ||
$this->middlewares = $middlewares; | ||
$this->workers = $workers; | ||
$this->interval = $interval; | ||
$this->logger = $logger; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function consume() | ||
{ | ||
if ($this->logger) { | ||
$this->logger->debug('Starting poller'); | ||
} | ||
|
||
foreach ($this->middlewares as $middleware) { | ||
if ($middleware instanceof InitializableInterface) { | ||
$middleware->initialize(); | ||
} | ||
} | ||
|
||
while (true) { | ||
if ($this->process() === false) { | ||
break; | ||
} | ||
|
||
if ($this->sleep() === false) { | ||
break; | ||
} | ||
} | ||
|
||
if ($this->logger) { | ||
$this->logger->debug('Stopping poller'); | ||
} | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
private function process() | ||
{ | ||
while (($message = $this->queues->pop()) !== null) { | ||
|
||
$queue = $this->queues->get($message->getRoutingKey()); | ||
|
||
// Process the message using the worker and middleware | ||
$worker = $this->getWorker($queue->getName()); | ||
$next = new Next($this->middlewares, $worker); | ||
|
||
$result = $next($message, $queue); | ||
|
||
if ($result === false) { | ||
return false; | ||
} | ||
} | ||
|
||
$this->waiting = !isset($message); | ||
return true; | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
private function sleep() | ||
{ | ||
foreach ($this->middlewares as $middleware) { | ||
if ($middleware instanceof SleepyMiddlewareInterface && $middleware->sleep() === false) { | ||
return false; | ||
} | ||
} | ||
|
||
if ($this->waiting) { | ||
// Sleep between queue polls when the queue is empty | ||
usleep($this->interval * 1000000); | ||
} | ||
return true; | ||
} | ||
|
||
/** | ||
* @param string $name | ||
* @return callable | ||
*/ | ||
private function getWorker($name) | ||
{ | ||
if (!isset($this->workers[$name])) { | ||
throw new RuntimeException(sprintf('Worker not defined for queue "%s"', $name)); | ||
} | ||
|
||
return $this->workers[$name]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
namespace Radish\Consumer; | ||
|
||
use Psr\Log\LoggerInterface; | ||
use Radish\Broker\QueueLoader; | ||
use Radish\Middleware\MiddlewareLoader; | ||
|
||
class PollerFactory | ||
{ | ||
/** | ||
* @var QueueLoader | ||
*/ | ||
protected $queueLoader; | ||
/** | ||
* @var MiddlewareLoader | ||
*/ | ||
private $middlewareLoader; | ||
/** | ||
* @var LoggerInterface|null | ||
*/ | ||
protected $logger; | ||
|
||
/** | ||
* @param QueueLoader $queueLoader | ||
* @param MiddlewareLoader $middlewareLoader | ||
* @param LoggerInterface|null $logger | ||
*/ | ||
public function __construct(QueueLoader $queueLoader, MiddlewareLoader $middlewareLoader, LoggerInterface $logger = null) | ||
{ | ||
$this->queueLoader = $queueLoader; | ||
$this->middlewareLoader = $middlewareLoader; | ||
$this->logger = $logger; | ||
} | ||
|
||
/** | ||
* @param array $queueNames | ||
* @param array $middlewareOptions | ||
* @param array $workers | ||
* @param int $interval | ||
* @return Poller | ||
*/ | ||
public function create(array $queueNames, array $middlewareOptions, array $workers, $interval) | ||
{ | ||
return new Poller( | ||
$this->queueLoader->load($queueNames), | ||
$this->middlewareLoader->load($middlewareOptions), | ||
$workers, | ||
$interval, | ||
$this->logger | ||
); | ||
} | ||
} |
Oops, something went wrong.