952 days continuous production uptime, 40k+ tp/s single node. Original corpo Bitbucket history not included — clean archive commit.
173 lines
7.4 KiB
PHP
173 lines
7.4 KiB
PHP
<?php
|
|
/**
|
|
* gacLogClient -- class definition
|
|
*
|
|
* this is the class for declaring a logClient for use in testing, or within the framework when we need to publish
|
|
* a log event to another queue.
|
|
*
|
|
* 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 log exchange.
|
|
*
|
|
* IMPORTANT NOTE:
|
|
* ---------------
|
|
* Whenever you add a qualifying 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:
|
|
* ========
|
|
* 09-18-19 mks DB-136: original coding
|
|
* 12-04-19 mks DB-140: PHP 7.4 compliance
|
|
* 01-07-20 mks DB-150: PHP 7.4 member variable casting
|
|
*
|
|
*/
|
|
|
|
use PhpAmqpLib\Channel\AMQPChannel;
|
|
use PhpAmqpLib\Exception\AMQPRuntimeException;
|
|
use PhpAmqpLib\Exception\AMQPTimeoutException;
|
|
use PhpAmqpLib\Message\AMQPMessage;
|
|
|
|
|
|
class gacLogClient {
|
|
private ?object $rabbitConnection;
|
|
private AMQPChannel $rabbitChannel;
|
|
private string $res = 'BRCL: ';
|
|
// if you add to the log-exchange bindings, for either service or source, remember to update these arrays as needed
|
|
private array $validTypes = [ EXCHANGE_SOURCE_LOGS, EXCHANGE_SOURCE_METRICS, STAR ];
|
|
public string $status;
|
|
|
|
/**
|
|
* __construct() -- public method
|
|
*
|
|
* the constructor instantiates the class and establishes a connection to the RMQ Log Exchange.
|
|
*
|
|
* other client classes, such as BrokerClient, require a queue name to be passed to the constructor because these
|
|
* clients are connecting directly to the queues to publish an event. This client, instead, connects to the
|
|
* log exchange (instead of a queue) and publishes to the exchange.
|
|
*
|
|
* Within the bindings for the exchange which are coded in the brokers for each of the exchange queues, are the
|
|
* configuration directives for how messages are routed by the exchange to the destination queues. Messages
|
|
* published to the exchange can be routed to one, several, or all of the queues bound to the exchange.
|
|
*
|
|
* That is why there isn't a string parameter passed to this class' constructor - because this client connects
|
|
* to the exchange and not to a broker specified by the input parameter.
|
|
*
|
|
* method returns an implicit boolean via a class member (status) indicating whether or not the resource management
|
|
* was successful and attempts to provide diagnostics via logging, cli output, or via the status member variable.
|
|
*
|
|
*
|
|
* @author mike@givingassistant.org
|
|
* @version 1.0
|
|
*
|
|
*
|
|
* HISTORY:
|
|
* ========
|
|
* 09-18-19 mks DB-136: original coding
|
|
*
|
|
*/
|
|
public function __construct()
|
|
{
|
|
register_shutdown_function(array($this, '__destruct'));
|
|
$this->status = false;
|
|
try {
|
|
// fetch the AMQPStreamConnection to the Admin service
|
|
$this->rabbitConnection = gasResourceManager::fetchResource(RESOURCE_ADMIN);
|
|
if (is_null($this->rabbitConnection)) {
|
|
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
|
|
consoleLog($this->res, CON_ERROR, $hdr . ERROR_RESOURCE_404 . RESOURCE_ADMIN);
|
|
return;
|
|
}
|
|
$this->rabbitChannel = $this->rabbitConnection->channel();
|
|
// connect the channel to the logging exchange
|
|
$this->rabbitChannel->exchange_declare(EXCHANGE_NAME_TOPIC_LOGS, EXCHANGE_TYPE_TOPIC, false, false, false);
|
|
$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;
|
|
}
|
|
|
|
|
|
/**
|
|
* call() -- public method
|
|
*
|
|
* This method is invoked outside of the class and is the entry point for publishing a message request to the
|
|
* logging exchange. It creates a new AMQP message and publishes it to the exchange, defined in the constructor),
|
|
* and then blocks-and-waits for a response from the remote (vault) service.
|
|
*
|
|
* There are two input parameters to this method:
|
|
*
|
|
* $_data -- this is the payload data that, untouched, is converted into an AMQPMessage class object
|
|
* $_route -- this defines how the exchange will handle the incoming message (<service>.<source> format)
|
|
*
|
|
* For exchange routing, the $_route is required and critical for delivering a successful message request to
|
|
* the logging exchange. The following values are valid routes with the default route set to STAR:
|
|
*
|
|
* EXCHANGE_SOURCE_METRICS, EXCHANGE_SOURCE_LOGS, STAR
|
|
*
|
|
* Publishing a message is exception trapped and will generate a log message at the warn level if tripped.
|
|
*
|
|
* The method returns a boolean to the calling client if the message was successfully published to the exchange.
|
|
* Since logging is fire-n-forget, we can't know if the message was accepted... if a false value is returned,
|
|
* then the client should check the console log as their request failed routing validation.
|
|
*
|
|
*
|
|
* @author mike@givingassistant.org
|
|
* @version 1.0
|
|
*
|
|
* @param $_data -- the payload to be converted to an AMQPMessage class object
|
|
* @param $_route -- The declared route for the message request ( defaults to: * )
|
|
*
|
|
* @return bool -- indicates if the message was successfully published or not
|
|
*
|
|
*
|
|
* HISTORY:
|
|
* ========
|
|
* 09-18-19 mks DB-136: original coding
|
|
*
|
|
*/
|
|
public function call(string $_data, string $_route = STAR): bool
|
|
{
|
|
// validate the routing string for the exchange...
|
|
if (!in_array($_route, $this->validTypes)) {
|
|
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
|
|
$msg = sprintf(ERROR_SERVICE_SOURCE_UNK, $_route);
|
|
consoleLog($this->res, CON_ERROR, $hdr . $msg);
|
|
return false;
|
|
}
|
|
|
|
// create and publish the message to the logging exchange
|
|
try {
|
|
$rabbitMessage = new AMQPMessage((string)$_data);
|
|
$this->rabbitChannel->basic_publish($rabbitMessage, EXCHANGE_NAME_TOPIC_LOGS, $_route);
|
|
consoleLog($this->res, CON_SUCCESS, SUCCESS_PUBLISHED . $_route);
|
|
} catch (AMQPTimeoutException | AMQPRuntimeException | Throwable $e) {
|
|
$hdr = basename(__METHOD__) . AT . __LINE__ . COLON;
|
|
consoleLog($this->res, CON_ERROR, $hdr . $e->getMessage());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
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 {
|
|
$this->rabbitChannel->close();
|
|
$this->rabbitConnection->close();
|
|
} catch (AMQPTimeoutException | AMQPRuntimeException | 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());
|
|
}
|
|
}
|
|
}
|