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:
2026-04-05 09:49:30 -07:00
commit 373ebc8c93
1284 changed files with 409372 additions and 0 deletions

View 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());
}
}
}