Archive: Namaste PHP AMQP framework v1.0 (2017-2020)
952 days continuous production uptime, 40k+ tp/s single node. Original corpo Bitbucket history not included — clean archive commit.
This commit is contained in:
253
classes/gacBrokerClient.class.inc
Normal file
253
classes/gacBrokerClient.class.inc
Normal file
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
/**
|
||||
* gacBrokerClient -- class definition
|
||||
*
|
||||
* this is the class for declaring a brokerClient for use in testing, or within the framework when we need to publish
|
||||
* an event to another queue (that's not a logging event).
|
||||
*
|
||||
* This class simply abstracts the RabbitMQ processes so that you don't have to re-write all the RMQ code every
|
||||
* time you want to publish a message to the queues.
|
||||
*
|
||||
* IMPORTANT NOTE:
|
||||
* ---------------
|
||||
* Whenever you add a new queue to the pantheon, you'll need to update the constructor class, adding the queue name
|
||||
* to the $validQueues member, and to the switch-case statement that assigns the correct environment.
|
||||
*
|
||||
*
|
||||
* @author mike@givingassistant.org
|
||||
* @version 1.0
|
||||
*
|
||||
* HISTORY:
|
||||
* ========
|
||||
* 06-15-17 mks original coding
|
||||
* 02-08-17 mks _INF-139: updated for migrations broker, PHPDoc variable casting for AMQP members
|
||||
* 07-31-18 mks CORE-774: PHP7.2 exception handling
|
||||
* 09-18-19 mks DB-136: improved error messaging and exception handling
|
||||
*
|
||||
*/
|
||||
|
||||
//use PhpAmqpLib\Connection\AMQPStreamConnection;
|
||||
use PhpAmqpLib\Channel\AMQPChannel;
|
||||
use PhpAmqpLib\Exception\AMQPRuntimeException;
|
||||
use PhpAmqpLib\Exception\AMQPTimeoutException;
|
||||
use PhpAmqpLib\Message\AMQPMessage;
|
||||
|
||||
|
||||
class gacBrokerClient {
|
||||
private ?object $rabbitConnection = null;
|
||||
private ?AMQPChannel $rabbitChannel = null;
|
||||
private string $rabbitCallbackQueue;
|
||||
private ?string $rabbitResponse;
|
||||
private string $rabbitCorrelationID;
|
||||
private string $queueName;
|
||||
private array $validQueues;
|
||||
private gacErrorLogger $logger;
|
||||
private string $res = 'CLBR: ';
|
||||
public bool $status;
|
||||
|
||||
/**
|
||||
* __construct() -- public method
|
||||
*
|
||||
* the constructor instantiates the class and establishes a connection to the RMQ broker.
|
||||
*
|
||||
* the constructor takes one input parameter:
|
||||
*
|
||||
* - queueName -- which queue does this instantiation wish to connect to
|
||||
*
|
||||
* as of this writing, there are two queuing services supported: namaste and admin. If more are added, then
|
||||
* they'll need to be defined (as constants) and the resource evaluation code updated.
|
||||
*
|
||||
* method returns a boolean indicating whether or not the resource management was successful and attempts to
|
||||
* provide diagnostics via logging, cli output, or via the status member variable.
|
||||
*
|
||||
* queue_declare arguments:
|
||||
* ------------------------
|
||||
* Queue Name: this is an arbitrary name, will be used to identify the queue
|
||||
* Passive: if set to true, the server will only check if the queue can be created, false will actually attempt to create the queue.
|
||||
* Durable: Typically, if the server stops or crashes, all queues and messages are lost... unless we declare the queue durable, in which case the queue will persist if the server is restarted.
|
||||
* Exclusive: If true, the queue can only be used by the connection that created it.
|
||||
* Autodelete: if true, the queue will be deleted once it has no messages and there are no subscribers connected
|
||||
*
|
||||
*
|
||||
* @author mike@givingassistant.org
|
||||
* @version 1.0
|
||||
*
|
||||
* @param $_queueName
|
||||
* @param $_tag
|
||||
*
|
||||
* HISTORY:
|
||||
* ========
|
||||
* 06-15-17 mks initial coding
|
||||
* 02-08-18 mks _INF-139: support for the migration broker, fixed return statements, console log
|
||||
* 04-11-18 mks _INF-188: warehousing broker support
|
||||
* 01-29-20 mks DB-144: tercero support
|
||||
* 12-10-20 mks DB-180: segundo cons broker support
|
||||
*
|
||||
*/
|
||||
public function __construct(string $_queueName, $_tag = 'default')
|
||||
{
|
||||
register_shutdown_function(array($this, '__destruct'));
|
||||
$this->status = false;
|
||||
try {
|
||||
$this->logger = new gacErrorLogger();
|
||||
} catch (TypeError $t) {
|
||||
consoleLog($this->res, CON_ERROR, ERROR_TYPE_EXCEPTION . $t->getMessage());
|
||||
}
|
||||
$this->queueName = $_queueName;
|
||||
$this->validQueues = [
|
||||
BROKER_QUEUE_R,
|
||||
BROKER_QUEUE_W,
|
||||
BROKER_QUEUE_AI,
|
||||
BROKER_QUEUE_AO,
|
||||
BROKER_QUEUE_M,
|
||||
BROKER_QUEUE_WH,
|
||||
BROKER_QUEUE_U,
|
||||
BROKER_QUEUE_S,
|
||||
BROKER_QUEUE_C
|
||||
];
|
||||
if (!in_array($this->queueName, $this->validQueues)) {
|
||||
$this->logger->warn(ERROR_INVALID_QUEUE_NAME . $this->queueName);
|
||||
} else {
|
||||
switch ($this->queueName) {
|
||||
case BROKER_QUEUE_R :
|
||||
case BROKER_QUEUE_W :
|
||||
case BROKER_QUEUE_M :
|
||||
$resource = RESOURCE_BROKER;
|
||||
break;
|
||||
|
||||
case BROKER_QUEUE_AI :
|
||||
case BROKER_QUEUE_AO :
|
||||
$resource = RESOURCE_ADMIN;
|
||||
break;
|
||||
|
||||
case BROKER_QUEUE_WH :
|
||||
case BROKER_QUEUE_C :
|
||||
$resource = RESOURCE_SEGUNDO;
|
||||
break;
|
||||
|
||||
case BROKER_QUEUE_U :
|
||||
case BROKER_QUEUE_S :
|
||||
$resource = RESOURCE_TERCERO;
|
||||
break;
|
||||
|
||||
default :
|
||||
$msg = ERROR_RESOURCE_404 . $_queueName;
|
||||
$this->logger->info($msg);
|
||||
consoleLog($this->res, CON_SYSTEM, $msg);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
$this->rabbitConnection = gasResourceManager::fetchResource($resource);
|
||||
if (is_null($this->rabbitConnection)) return;
|
||||
$this->rabbitChannel = $this->rabbitConnection->channel();
|
||||
$label = uniqid('gacBrokerClient<' . $_tag . '>:');
|
||||
list($this->rabbitCallbackQueue, ,) = $this->rabbitChannel->queue_declare($label, false, false, false, true); // was: f, f, f, t
|
||||
$this->rabbitChannel->basic_consume($this->rabbitCallbackQueue, '', false, false, false, false, array($this, BROKER_CLIENT_RESPONSE));
|
||||
$this->status = true;
|
||||
} catch (AMQPRuntimeException | AMQPTimeoutException | Throwable $t) {
|
||||
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
|
||||
consoleLog($this->res, CON_ERROR, $hdr . ERROR_THROWABLE_EXCEPTION);
|
||||
consoleLog($this->res, CON_ERROR, $hdr . $t->getMessage());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @noinspection PhpUnused
|
||||
* client_response -- public method
|
||||
*
|
||||
* this method checks to see if the current response, based on the correlation (request) ID, is the one it's
|
||||
* waiting for from the remote (vault) service.
|
||||
*
|
||||
* When it receives the awaited response, it stores the response into a member variable and exits.
|
||||
*
|
||||
*
|
||||
* @author mikegivingassistant.org
|
||||
* @version 1.0
|
||||
* @param $_response - the class object created in the constructor
|
||||
*
|
||||
*
|
||||
* HISTORY:
|
||||
* ========
|
||||
* 06-15-17 mks original coding
|
||||
* 09-18-19 mks DB-136: exception wrapped this code
|
||||
*
|
||||
*/
|
||||
public function client_response(AMQPMessage $_response)
|
||||
{
|
||||
try {
|
||||
if ($_response->get(BROKER_CORRELATION_ID) == $this->rabbitCorrelationID) {
|
||||
$this->rabbitResponse = $_response->body;
|
||||
}
|
||||
} catch (AMQPTimeoutException | AMQPRuntimeException | Throwable $t) {
|
||||
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
|
||||
consoleLog($this->res, CON_ERROR, $hdr . ERROR_EXCEPTION);
|
||||
consoleLog($this->res, CON_ERROR, $hdr . $t->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* call() -- public method
|
||||
*
|
||||
* This method is invoked outside of the class and is the entry point for publishing a message request to the
|
||||
* broker. It creates a new AMQP message and publishes it to the queue (defined in the constructor), and then
|
||||
* blocks-and-waits for a response from the remote (vault) service.
|
||||
*
|
||||
* Publishing a message is exception trapped and will generate a log message at the warn level if tripped.
|
||||
*
|
||||
* The "raw" response is returned directly to the calling client and will be processed at that level.
|
||||
*
|
||||
* @author mike@givingassistant.org
|
||||
* @version 1.0
|
||||
*
|
||||
* @param $_data
|
||||
* @return null
|
||||
*
|
||||
* HISTORY:
|
||||
* ========
|
||||
* 06-15-17 mks original coding
|
||||
* 05-31-18 mks CORE-1011: update for new XML broker services configuration
|
||||
*
|
||||
*/
|
||||
public function call($_data)
|
||||
{
|
||||
$this->rabbitResponse = null;
|
||||
$this->rabbitCorrelationID = uniqid();
|
||||
|
||||
$rabbitMessage = new AMQPMessage((string)$_data, [BROKER_CORRELATION_ID => $this->rabbitCorrelationID, BROKER_REPLY_TO => $this->rabbitCallbackQueue]);
|
||||
try {
|
||||
$this->rabbitChannel->basic_publish($rabbitMessage, '', (gasConfig::$settings[CONFIG_BROKER_SERVICES][CONFIG_BROKER_QUEUE_TAG] . $this->queueName));
|
||||
while (!$this->rabbitResponse) {
|
||||
$this->rabbitChannel->wait();
|
||||
}
|
||||
} catch (AMQPTimeoutException | AMQPRuntimeException | Throwable $e) {
|
||||
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
|
||||
$this->logger->fatal($hdr . ERROR_BROKER_EXCEPTION_TIMEOUT);
|
||||
$this->logger->fatal($hdr . $e->getMessage());
|
||||
consoleLog('_BTC: ', CON_ERROR, $hdr . $e->getMessage());
|
||||
}
|
||||
return ($this->rabbitResponse);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
// As of PHP 5.3.10 destructors are not run on shutdown caused by fatal errors.
|
||||
//
|
||||
// destructor is registered shut-down function in constructor -- so any recovery
|
||||
// efforts should go in this method.
|
||||
try {
|
||||
if (!is_null($this->rabbitChannel))
|
||||
$this->rabbitChannel->close();
|
||||
if (!is_null($this->rabbitConnection))
|
||||
$this->rabbitConnection->close();
|
||||
} catch (Throwable $t) {
|
||||
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
|
||||
consoleLog($this->res, CON_ERROR, $hdr . ERROR_THROWABLE_EXCEPTION);
|
||||
consoleLog($this->res, CON_ERROR, $hdr. $t->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user