151 lines
4.6 KiB
PHP
151 lines
4.6 KiB
PHP
|
<?php
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace Enqueue\Stomp;
|
||
|
|
||
|
use Enqueue\Dsn\Dsn;
|
||
|
use Interop\Queue\ConnectionFactory;
|
||
|
use Interop\Queue\Context;
|
||
|
use Stomp\Network\Connection;
|
||
|
|
||
|
class StompConnectionFactory implements ConnectionFactory
|
||
|
{
|
||
|
const SCHEME_EXT_ACTIVEMQ = 'activemq';
|
||
|
const SCHEME_EXT_RABBITMQ = 'rabbitmq';
|
||
|
|
||
|
/**
|
||
|
* @var array
|
||
|
*/
|
||
|
private $config;
|
||
|
|
||
|
/**
|
||
|
* @var BufferedStompClient
|
||
|
*/
|
||
|
private $stomp;
|
||
|
|
||
|
/**
|
||
|
* $config = [
|
||
|
* 'host' => null,
|
||
|
* 'port' => null,
|
||
|
* 'login' => null,
|
||
|
* 'password' => null,
|
||
|
* 'vhost' => null,
|
||
|
* 'buffer_size' => 1000,
|
||
|
* 'connection_timeout' => 1,
|
||
|
* 'sync' => false,
|
||
|
* 'lazy' => true,
|
||
|
* 'ssl_on' => false,
|
||
|
* ].
|
||
|
*
|
||
|
* or
|
||
|
*
|
||
|
* stomp:
|
||
|
* stomp:?buffer_size=100
|
||
|
*
|
||
|
* @param array|string|null $config
|
||
|
*/
|
||
|
public function __construct($config = 'stomp:')
|
||
|
{
|
||
|
if (empty($config) || 'stomp:' === $config) {
|
||
|
$config = [];
|
||
|
} elseif (is_string($config)) {
|
||
|
$config = $this->parseDsn($config);
|
||
|
} elseif (is_array($config)) {
|
||
|
if (array_key_exists('dsn', $config)) {
|
||
|
$config = array_replace($config, $this->parseDsn($config['dsn']));
|
||
|
|
||
|
unset($config['dsn']);
|
||
|
}
|
||
|
} else {
|
||
|
throw new \LogicException('The config must be either an array of options, a DSN string or null');
|
||
|
}
|
||
|
|
||
|
$this->config = array_replace($this->defaultConfig(), $config);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return StompContext
|
||
|
*/
|
||
|
public function createContext(): Context
|
||
|
{
|
||
|
$useExchangePrefix = self::SCHEME_EXT_RABBITMQ === $this->config['target'] ? true : false;
|
||
|
|
||
|
if ($this->config['lazy']) {
|
||
|
return new StompContext(function () {
|
||
|
return $this->establishConnection();
|
||
|
}, $useExchangePrefix);
|
||
|
}
|
||
|
|
||
|
return new StompContext($this->establishConnection(), $useExchangePrefix);
|
||
|
}
|
||
|
|
||
|
private function establishConnection(): BufferedStompClient
|
||
|
{
|
||
|
if (false == $this->stomp) {
|
||
|
$config = $this->config;
|
||
|
|
||
|
$scheme = (true === $config['ssl_on']) ? 'ssl' : 'tcp';
|
||
|
$uri = $scheme.'://'.$config['host'].':'.$config['port'];
|
||
|
$connection = new Connection($uri, $config['connection_timeout']);
|
||
|
|
||
|
$this->stomp = new BufferedStompClient($connection, $config['buffer_size']);
|
||
|
$this->stomp->setLogin($config['login'], $config['password']);
|
||
|
$this->stomp->setVhostname($config['vhost']);
|
||
|
$this->stomp->setSync($config['sync']);
|
||
|
|
||
|
$this->stomp->connect();
|
||
|
}
|
||
|
|
||
|
return $this->stomp;
|
||
|
}
|
||
|
|
||
|
private function parseDsn(string $dsn): array
|
||
|
{
|
||
|
$dsn = Dsn::parseFirst($dsn);
|
||
|
|
||
|
if ('stomp' !== $dsn->getSchemeProtocol()) {
|
||
|
throw new \LogicException(sprintf('The given DSN is not supported. Must start with "stomp:".'));
|
||
|
}
|
||
|
|
||
|
$schemeExtension = current($dsn->getSchemeExtensions());
|
||
|
if (false === $schemeExtension) {
|
||
|
$schemeExtension = self::SCHEME_EXT_RABBITMQ;
|
||
|
}
|
||
|
if (self::SCHEME_EXT_ACTIVEMQ !== $schemeExtension && self::SCHEME_EXT_RABBITMQ !== $schemeExtension) {
|
||
|
throw new \LogicException(sprintf('The given DSN is not supported. The scheme extension "%s" provided is invalid. It must be one of "%s" or "%s".', $schemeExtension, self::SCHEME_EXT_ACTIVEMQ, self::SCHEME_EXT_RABBITMQ));
|
||
|
}
|
||
|
|
||
|
return array_filter(array_replace($dsn->getQuery(), [
|
||
|
'target' => $schemeExtension,
|
||
|
'host' => $dsn->getHost(),
|
||
|
'port' => $dsn->getPort(),
|
||
|
'login' => $dsn->getUser(),
|
||
|
'password' => $dsn->getPassword(),
|
||
|
'vhost' => null !== $dsn->getPath() ? ltrim($dsn->getPath(), '/') : null,
|
||
|
'buffer_size' => $dsn->getDecimal('buffer_size'),
|
||
|
'connection_timeout' => $dsn->getDecimal('connection_timeout'),
|
||
|
'sync' => $dsn->getBool('sync'),
|
||
|
'lazy' => $dsn->getBool('lazy'),
|
||
|
'ssl_on' => $dsn->getBool('ssl_on'),
|
||
|
]), function ($value) { return null !== $value; });
|
||
|
}
|
||
|
|
||
|
private function defaultConfig(): array
|
||
|
{
|
||
|
return [
|
||
|
'target' => self::SCHEME_EXT_RABBITMQ,
|
||
|
'host' => 'localhost',
|
||
|
'port' => 61613,
|
||
|
'login' => 'guest',
|
||
|
'password' => 'guest',
|
||
|
'vhost' => '/',
|
||
|
'buffer_size' => 1000,
|
||
|
'connection_timeout' => 1,
|
||
|
'sync' => false,
|
||
|
'lazy' => true,
|
||
|
'ssl_on' => false,
|
||
|
];
|
||
|
}
|
||
|
}
|