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

583
brokers/adminBrokerOut.php Normal file
View File

@@ -0,0 +1,583 @@
<?php
/**
* adminBrokerOut.php
*
* This is the admin-out broker and is, currently, a placeholder for future work.
*
* This broker is intended to be used to fetch data/reports from the admin-side. As it stands today, only base
* events are supported.
*
* This broker is pretty old requires refactoring to bring up-to standards. As it is now, it is simply a placeholder
* service.
*
* @author mike@givingassistant.org
* @version 1.0.0
*
* HISTORY:
* ========
* 06-15-17 mks original coding
* 08-24-17 mks CORE-500: broker events
* 02-06-18 mks _INF-139: migration event coding, PHP 7.2 exception handling
* 05-31-18 mks CORE-1011: update for new XML broker services configuration
* 06-07-18 mks CORE-1013: remote fetch event added
* 07-09-18 mks CORE-1017: pedigree fetch event added
* 07-28-20 mks DB-156: broker self-registration installed
*
*/
use PhpAmqpLib\Connection\AMQPStreamConnection;
use /** @noinspection PhpUnusedAliasInspection */ PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Message\AMQPMessage;
use /** @noinspection PhpUnusedAliasInspection */ PhpAmqpLib\Exception\AMQPTimeoutException;
pcntl_async_signals(true); // enable asynchronous signal handling (PHP 7.1)
$myPid = getmypid();
$_REDIRECT = true;
$topDir = dirname(__DIR__);
$thisWatcher = basename(__FILE__);
$thisWatcher = rtrim($thisWatcher, ".php");
// load the framework
@require_once($topDir . '/config/sneakerstrap.inc'); // can't be constants b/c this loads the constants
$childrenPidList = null;
$pidDir = $topDir . DIR_PIDS;
$eos = (isset($_SERVER['HTTP_USER_AGENT'])) ? '<br />' : PHP_EOL;
$res = 'ADMO: ';
// event management for children
$adminServiceConfig = gasConfig::$settings[CONFIG_BROKER_SERVICES][CONFIG_ADMIN];
$numberChildren = $adminServiceConfig[CONFIG_BROKER_INSTANCES][CONFIG_ADMIN_BROKER_OUT];
$requestsPerInstance = (empty($adminServiceConfig[CONFIG_BROKER_REQUEST_LIMIT])) ? NUMBER_C : $adminServiceConfig[CONFIG_BROKER_REQUEST_LIMIT];
$numberChildren = ($numberChildren < 1) ? 1 : $numberChildren; // todo -- should this be = 2??
$runningBrokers = $numberChildren;
$requestCounter = 0;
$myRequestsPerInstance = 0;
$startingMemory = 0;
// create the root guid
$groot = rtrim($res, COLON) . UDASH . guid(); // root guid
consoleLog($res, CON_SUCCESS, sprintf(INFO_BROKER_STARTUP, substr(basename(__FILE__), 0, -4), $groot));
/** @var gacErrorLogger $parentLog */
$parentLog = new gacErrorLogger();
$errors = null;
$file = rtrim(basename(__FILE__), DOT . FILE_TYPE_PHP);
$service = ENV_ADMIN;
if (!validateService($service, $errors)) {
$hdr = sprintf(INFO_LOC, $file, __LINE__);
$msg = sprintf(ERROR_SERVICE_REG, $file, $service);
$parentLog->fatal($hdr . $msg);
$parentLog->__destruct();
unset($parentLog);
exit(1);
}
//////////////////////////////////////////////////////////////////////////////////
// set-up the replacement signal handler that will be called on a child's death //
//////////////////////////////////////////////////////////////////////////////////
//declare( ticks = 1);
function sigHandler($_sig) {
global $numberChildren;
switch ($_sig) {
case SIGCHLD :
$numberChildren--;
while (($pid = pcntl_wait($_sig, WNOHANG)) > 0) {
@pcntl_wexitstatus($_sig);
}
break;
}
}
pcntl_signal(SIGCLD, 'sigHandler');
/////////////////////////////////////////////////////////////////////////////////////////
// set-up the forking function so that it can be called initially or on a SIGCLD event //
/////////////////////////////////////////////////////////////////////////////////////////
function forkMe()
{
global $thisWatcher, $eos, $res, $parentLog, $requestsPerInstance, $myRequestsPerInstance, $groot;
// $startingMemory = memory_get_usage(true);
// todo -- when this broker becomes active, add the systemEvent for calculating memory consumption on SIGCLD
$myRequestsPerInstance = $requestsPerInstance + (mt_rand(0, 2) * 10) + mt_rand(1, 9);
$thisPid = pcntl_fork();
switch ($thisPid) {
case -1 : // error
$cmsg = ERROR_FORK_FAILED . $thisWatcher;
$parentLog->fatal($cmsg);
die(getDateTime() . CON_ERROR . $res . $cmsg . $eos);
break;
case 0 : // child (broker daemon)
try {
// replace the sigcld signal handler
pcntl_signal(SIGCLD, SIG_DFL);
$thisPid = getmypid();
// create the child logger object
/** @var gacErrorLogger $childLog */
$childLog = new gacErrorLogger();
// generate a child guid for the forked child...
$childGUID = rtrim($res, COLON) . UDASH . guid();
// toss the childGUID unto cache because it does not propagate down to the callback method
gasCache::sysAdd(($groot . UDASH . $thisPid), $childGUID);
$queueTag = gasConfig::$settings[CONFIG_BROKER_SERVICES][CONFIG_BROKER_QUEUE_TAG];
$queue = $queueTag . BROKER_QUEUE_AO;
/** @var AMQPStreamConnection $brokerConnection */
$brokerConnection = gasResourceManager::fetchResource(RESOURCE_ADMIN);
if (is_null($brokerConnection)) {
$parentLog->fatal(ERROR_RESOURCE_404 . RESOURCE_ADMIN);
consoleLog($res, CON_ERROR, ERROR_RESOURCE_404 . RESOURCE_ADMIN);
exit(1); // shell-script exit value for fail
}
$brokerChannel = $brokerConnection->channel();
// params: queue name, passive, durable, exclusive, auto-delete
$brokerChannel->queue_declare($queue, BROKER_QUEUE_DECLARE_PASSIVE, false, false, true);
} catch (PhpAmqpLib\Exception\AMQPRuntimeException | Throwable | TypeError $t) {
$hdr = basename(__FILE__) . AT . __LINE__ . COLON;
@handleExceptionMessaging($hdr, $t->getMessage(), $foo, true);
exit(1);
}
// register the child-spawn event
$data = [
SYSTEM_EVENT_NAME => SYSEV_NAME_CHILD_REG,
SYSTEM_EVENT_TYPE => SYSEV_TYPE_BROKER,
SYSTEM_EVENT_BROKER_ROOT_GUID => $groot,
SYSTEM_EVENT_BROKER_GUID => $childGUID,
SYSTEM_EVENT_KEY => SYSEV_CHILD_RPI,
SYSTEM_EVENT_VAL => $myRequestsPerInstance,
SYSTEM_EVENT_CODE_LOC => basename(__FILE__) . COLON . __LINE__
];
@postSystemEvent($data, $childGUID, $childLog);
register_shutdown_function(BROKER_SHUTDOWN_FUNCTION, $brokerChannel, $brokerConnection, $res);
$callback = function($_request)
{
$startTime = gasStatic::doingTime();
global $requestCounter, $res, $eos, $myRequestsPerInstance, $startingMemory, $groot, $service;
$errorList = array();
$requestCounter++;
$aryRetData = null;
$retData = null;
$request = null;
$eos = (isset($_SERVER['HTTP_USER_AGENT'])) ? '<br />' : PHP_EOL;
$eventSuccess = false;
$conMsg = '';
$eventGUID = guid();
$thisPid = getmypid();
$eventTimer = false; // certain events will toggle to true to log timer recording for the broker event
$childGUID = gasCache::sysGet(($groot . UDASH . getmypid()));
// set-up the call-back logger
/** @var gacErrorLogger $callBackLog */
$callBackLog = new gacErrorLogger($eventGUID);
if (!firstPassPayloadValidation($_request, $service, $msg, $request, $eventGUID)) {
$conMsg = $msg;
$callBackLog->info($msg);
$aryRetData = buildReturnPayload([false, STATE_FAIL, null, $msg, null]);
$event = BROKER_QUEUE_AO . '(' . ERROR_DATA_VALIDATION_FIRST_PASS . ')';
} elseif (!validateMetaData($request, $errorList)) {
for ($index = 0, $last = count($errorList); $index < $last; $index++) {
$conMsg .= $errorList[$index] . $eos;
$callBackLog->error($errorList[$index]);
}
$conMsg = rtrim($conMsg, $eos);
$aryRetData = buildReturnPayload([false, STATE_META_ERROR, $msg, null, null]);
$event = BROKER_QUEUE_AO . '(' . ERROR_META_VALIDATION_SECOND_PASS . ')';
} else {
$event = BROKER_QUEUE_AO . '(' . $request[BROKER_REQUEST] . ')';
if (is_null($request)) consoleLog($res, CON_ERROR, ERROR_BROKER_REQUEST_BAD . BROKER_REQUEST);
switch ($request[BROKER_REQUEST]) {
case BROKER_REQUEST_SHUTDOWN :
$_request->delivery_info[BROKER_CHANNEL]->basic_cancel($_request->delivery_info[BROKER_DELIVERY_TAG]);
$conMsg = SUCCESS_SHUTDOWN;
$aryRetData = buildReturnPayload([true, STATE_SUCCESS, null, BROKER_REQUEST_SHUTDOWN, null]);
$eventSuccess = true;
break;
// test broker responsiveness
case BROKER_REQUEST_PING :
$conMsg = SUCCESS_PING . BROKER_QUEUE_AO;
$aryRetData = buildReturnPayload([true, STATE_SUCCESS, null, (SUCCESS_PING . BROKER_QUEUE_AO), null]);
$eventSuccess = true;
break;
case BROKER_REQUEST_PEDIGREE :
$conMsg = SUCCESS_EVENT . BROKER_REQUEST_PEDIGREE;
$aryRetData = buildReturnPayload([true, STATE_SUCCESS, null, gasConfig::getPedigree()]);
$eventSuccess = true;
break;
case BROKER_REQUEST_ADMIN_MWH_EVENT_CREATE :
$eventTimer = true;
$errors = array();
if (!isset($request[BROKER_META_DATA][META_CLIENT])) {
$msg = ERROR_META_CLIENT_404;
$conMsg = $msg;
$callBackLog->data($msg);
} elseif ($request[BROKER_META_DATA][META_CLIENT] != CLIENT_SYSTEM) {
$msg = ERROR_BROKER_CLIENT_NOT_AUTH . COLON . $request[BROKER_META_DATA][META_CLIENT];
$conMsg = $msg;
$callBackLog->data($msg);
} elseif ($request[BROKER_META_DATA][META_TEMPLATE] != TEMPLATE_CLASS_MIGRATIONS
and $request[BROKER_META_DATA][META_TEMPLATE] != TEMPLATE_CLASS_WAREHOUSE) {
$msg = ERROR_TEMPLATE_WRONG;
$conMsg = $msg;
$callBackLog->error($msg);
} else {
/** @var gacMongoDB $widget */
if (is_null($widget = grabWidget($request[BROKER_META_DATA], '', $errorList))) {
foreach ($errorList as $error)
$callBackLog->error($error);
} else {
$widget->_createRecord($request[BROKER_DATA]);
if (!$widget->status) {
$msg = FAIL_EVENT . BROKER_REQUEST_ADMIN_MWH_EVENT_CREATE;
$conMsg = $msg;
$callBackLog->error($msg);
$aryRetData = buildReturnPayload([false, $widget->state, $widget->eventMessages, null]);
} else {
$eventSuccess = true;
$conMsg = SUCCESS_EVENT . BROKER_REQUEST_ADMIN_MWH_EVENT_CREATE;
$aryRetData = buildReturnPayload([true, $widget->state, $widget->eventMessages, $widget->getData()]);
}
if (is_object($widget)) $widget->__destruct();
unset($widget);
}
}
break;
case BROKER_REQUEST_ADMIN_MWH_EVENT_FETCH :
$eventTimer = true;
// try { // if debugging, turn on the exception trapper
$errors = [];
if (empty($request[BROKER_DATA]) or !is_array($request[BROKER_DATA])) {
$msg = ERROR_DATA_MISSING_ARRAY . BROKER_DATA;
$conMsg = $msg;
$aryRetData = buildReturnPayload([false, STATE_DATA_ERROR, $msg]);
} elseif (!array_key_exists(META_TEMPLATE, $request[BROKER_META_DATA])
or ($request[BROKER_META_DATA][META_TEMPLATE] != TEMPLATE_CLASS_MIGRATIONS
and $request[BROKER_META_DATA][META_TEMPLATE] != TEMPLATE_CLASS_WAREHOUSE)) {
$msg = sprintf(ERROR_TEMPLATE_BAD, TEMPLATE_CLASS_MIGRATIONS);
$conMsg = $msg;
$aryRetData = buildReturnPayload([false, STATE_META_ERROR, $msg, null]);
} else {
/** @var gacMongoDB $widget */
if (is_null($widget = grabWidget($request[BROKER_META_DATA], '', $errorList))) {
foreach ($errorList as $error)
$callBackLog->error($error);
} else {
$widget->_fetchRecords($request[BROKER_DATA]);
if (!$widget->status) {
// fetch failed
$conMsg = FAIL_EVENT . BROKER_REQUEST_ADMIN_MWH_EVENT_FETCH;
$aryRetData = buildReturnPayload([false, $widget->state, $widget->eventMessages, null]);
} else {
// update successful
$eventSuccess = true;
$conMsg = SUCCESS_EVENT . BROKER_REQUEST_ADMIN_MWH_EVENT_FETCH;
// ReturnPayload - a query that returns no data will show success - eval the return
// state and return either a "no data found" message or the query
// results to the calling client
$rp = ($widget->state == STATE_NOT_FOUND) ? $widget->eventMessages : $widget->queryResults;
$aryRetData = buildReturnPayload([true, $widget->state, $rp, $widget->getData()]);
}
if (is_object($widget)) $widget->__destruct();
unset($widget);
}
}
// } catch (Throwable | TypeError $t) {
// $eLine = $t->getLine();
// $eFile = $t->getFile();
// $eMsg = $t->getMessage();
// $msg = $eFile . COLON_NS . $eLine . COLON . $eMsg;
// consoleLog($res, CON_ERROR, $msg);
// $conMsg = $hdrConE . FAIL_EVENT . BROKER_REQUEST_ADMIN_MIGRATE_FETCH_EVENT;
// $aryRetData = buildReturnPayload([false, STATE_FAIL, $eMsg, null]);
// }
break;
case BROKER_REQUEST_REMOTE_FETCH :
$eventTimer = true;
$errors = array();
/** @var gacMongoDB $widget */
if (is_null($widget = grabWidget($request[BROKER_META_DATA], '', $errorList))) {
foreach ($errorList as $error)
$callBackLog->error($error);
} else {
$widget->_fetchRecords($request[BROKER_DATA]);
if ($widget->status) {
$eventSuccess = true;
$widget->eventMessages[] = STRING_REC_COUNT_RET . $widget->recordsReturned;
$conMsg = SUCCESS_EVENT . BROKER_REQUEST_FETCH;
$queryMeta = [
STRING_REC_COUNT_RET => $widget->recordsReturned,
STRING_REC_COUNT_TOT => $widget->recordsInCollection
];
// recordsInQuery is a PDO thing so let's see if it exists in the class object
if (isset($widget->recordsInQuery) and $widget->recordsInQuery) {
$queryMeta[STRING_REC_COUNT_QUERY] = $widget->recordsInQuery;
}
if (isset($request[BROKER_META_DATA][META_DONUT_FILTER]) and $request[BROKER_META_DATA][META_DONUT_FILTER] == 1) {
$queryResults = $widget->getData();
} elseif ($widget->useCache or (isset($request[BROKER_META_DATA][META_DO_CACHE]) and $request[BROKER_META_DATA][META_DO_CACHE])) {
$queryResults = $widget->getCK();
} else {
$queryResults = $widget->getData();
}
$retData = [STRING_QUERY_RESULTS => $queryResults, STRING_QUERY_DATA => $queryMeta];
$aryRetData = buildReturnPayload([true, STATE_SUCCESS, $widget->eventMessages, $retData]);
} else {
$conMsg = FAIL_EVENT . BROKER_REQUEST_FETCH;
$aryRetData = buildReturnPayload([false, $widget->state, $widget->eventMessages, null]);
}
if (is_object($widget)) $widget->__destruct();
unset($widget);
}
break;
case BROKER_REQUEST_AUDIT_RESTORE :
$eventTimer = true;
$errors = [];
if (!isset($request[BROKER_DATA]) or empty($request[BROKER_DATA])) {
$msg = ERROR_DATA_MISSING_ARRAY . STRING_DATA;
$conMsg = $msg;
$callBackLog->data($msg);
$errors[] = $msg;
} elseif (!is_array($request[BROKER_DATA])) {
$msg = ERROR_DATA_ARRAY_NOT_ARRAY . STRING_DATA;
$conMsg = $msg;
$callBackLog->data($msg);
$errors[] = $msg;
} elseif (!isset($request[BROKER_DATA][STRING_KEY])) {
$msg = ERROR_ARRAY_KEY_404 . BROKER_DATA . COLON . STRING_KEY;
$conMsg = $msg;
$callBackLog->data($msg);
$errors[] = $msg;
} else {
$key = $request[BROKER_DATA][STRING_KEY];
if (!validateGUID($key)) {
$msg = ERROR_INVALID_GUID . $key;
$conMsg = $msg;
$callBackLog->data($msg);
$errors[] = $msg;
} else {
// inject a key into the metaPayload to flag all requests as audit requests
$request[BROKER_META_DATA][META_AUDIT_EVENT] = 1;
/** @var gacMongoDB $widget */
if (is_null($widget = grabWidget($request[BROKER_META_DATA], $key, $errorList))) {
foreach ($errorList as $error)
$callBackLog->error($error);
} else {
try {
$data = []; // for the return payload containing original and changed records
$rc = $widget->restoreAuditRecord($data);
switch ($rc) {
case true :
$eventSuccess = true;
$aryRetData = buildReturnPayload([true, STATE_SUCCESS, $widget->eventMessages, SUCCESS_DB_RECORD_RESTORED]);
$conMsg = SUCCESS_EVENT . BROKER_REQUEST_AUDIT_RESTORE;
break;
case false :
default :
if (!empty($errors)) $widget->eventMessages = array_merge($widget->eventMessages, $errors);
$conMsg = FAIL_EVENT . BROKER_REQUEST_AUDIT_RESTORE;
$aryRetData = buildReturnPayload([false, STATE_FAIL, $widget->eventMessages, null]);
break;
}
} catch (TypeError | Throwable $t) {
$msg = ERROR_TYPE_EXCEPTION . $t->getMessage();
$conMsg = $msg;
$callBackLog->error($msg);
}
if (is_object($widget)) $widget->__destruct();
unset($widget);
}
}
}
break;
case BROKER_REQUEST_ADMIN_MWH_EVENT_UPDATE :
$eventTimer = true;
$errors = array();
if (!isset($request[BROKER_DATA]) or empty($request[BROKER_DATA])) {
$msg = ERROR_DATA_MISSING_ARRAY . STRING_DATA;
$conMsg = $msg;
$callBackLog->data($msg);
} elseif (!isset($request[BROKER_META_DATA][META_CLIENT])) {
$msg = ERROR_META_CLIENT_404;
$conMsg = $msg;
$callBackLog->data($msg);
} elseif ($request[BROKER_META_DATA][META_CLIENT] != CLIENT_SYSTEM) {
$msg = ERROR_BROKER_CLIENT_NOT_AUTH . COLON . $request[BROKER_META_DATA][META_CLIENT];
$conMsg = $msg;
$callBackLog->data($msg);
} elseif ($request[BROKER_META_DATA][META_TEMPLATE] != TEMPLATE_CLASS_MIGRATIONS
and $request[BROKER_META_DATA][META_TEMPLATE] != TEMPLATE_CLASS_WAREHOUSE) {
$msg = ERROR_TEMPLATE_WRONG;
$conMsg = $msg;
$callBackLog->error($msg);
} else {
/** @var gacMongoDB $widget */
if (is_null($widget = grabWidget($request[BROKER_META_DATA], '', $errorList))) {
foreach ($errorList as $error)
$callBackLog->error($error);
} else {
$widget->_updateRecord($request[BROKER_DATA]);
if (!$widget->status) {
$msg = FAIL_EVENT . BROKER_REQUEST_ADMIN_MWH_EVENT_UPDATE;
$conMsg = $msg;
$callBackLog->error($msg);
$aryRetData = buildReturnPayload([false, $widget->state, $widget->eventMessages, null]);
} else {
$eventSuccess = true;
$conMsg = SUCCESS_EVENT . BROKER_REQUEST_ADMIN_MWH_EVENT_UPDATE;
$aryRetData = buildReturnPayload([true, $widget->state, $widget->eventMessages, $widget->getData()]);
}
if (is_object($widget)) $widget->__destruct();
unset($widget);
}
}
break;
}
unset($aryRetData[PAYLOAD_CM]);
}
// ensure we have a return-payload and a console message
if (empty($aryRetData)) {
$msg = ERROR_NO_RET_DATA . '-' . __FILE__ . '-' . $request[BROKER_REQUEST];
$conMsg = BROKER_QUEUE_AO . ' - ' . $msg;
$errorList = (empty($errors)) ? null : $errors;
$aryRetData = buildReturnPayload([false, STATE_FRAMEWORK_FAIL, $msg, $errorList]);
} elseif ($eventSuccess and empty($conMsg)) {
$callBackLog->warn(ERROR_NO_CON_MSG);
$conMsg = $request[BROKER_REQUEST] . ' - ' . STATE_SUCCESS;
}
// prepare the return payload...
/** @noinspection PhpUndefinedMethodInspection */
$msg = new AMQPMessage(gzcompress(json_encode($aryRetData)), array(BROKER_CORRELATION_ID => $_request->get(BROKER_CORRELATION_ID)));
try {
/** @noinspection PhpUndefinedMethodInspection */
$_request->delivery_info[BROKER_CHANNEL]->basic_publish($msg, '', $_request->get(BROKER_REPLY_TO));
} catch (PhpAmqpLib\Exception\AMQPTimeoutException |
PhpAmqpLib\Exception\AMQPRuntimeException |
Throwable $e) {
$logMsg = ERROR_BROKER_EXCEPTION . $e->getMessage();
$callBackLog->fatal($logMsg);
consoleLog($res, CON_ERROR, $logMsg);
}
// if the event processing failed, reject the message, otherwise ack removing it from the queue
if (!$eventSuccess) {
$_request->delivery_info[BROKER_CHANNEL]->basic_reject($_request->delivery_info[BROKER_DELIVERY_TAG], false);
} else {
$_request->delivery_info[BROKER_CHANNEL]->basic_ack($_request->delivery_info[BROKER_DELIVERY_TAG]);
}
unset($msg);
if (!empty($conMsg)) {
consoleLog($res, (($eventSuccess) ? CON_SUCCESS : CON_ERROR), $conMsg . sprintf(ERROR_EVENT_COUNT, $requestCounter, $myRequestsPerInstance));
}
// publish event metrics if we've toggled the switch on
if ($eventTimer) {
// get the broker-event processing time
$eventTime = gasStatic::doingTime($startTime);
$data = [
SYSTEM_EVENT_NAME => SYSEV_NAME_EVENT_TIMER,
SYSTEM_EVENT_TYPE => SYSEV_TYPE_BROKER,
SYSTEM_EVENT_BROKER_ROOT_GUID => $groot,
SYSTEM_EVENT_BROKER_GUID => $childGUID,
DB_EVENT_GUID => $eventGUID,
SYSTEM_EVENT_COUNT => $requestCounter,
SYSTEM_EVENT_COUNT_TOTAL => $myRequestsPerInstance,
SYSTEM_EVENT_TIMER => $eventTime,
SYSTEM_EVENT_BROKER_EVENT => $event,
SYSTEM_EVENT_META_DATA => $request[BROKER_META_DATA],
SYSTEM_EVENT_CODE_LOC => basename(__FILE__) . COLON . __LINE__
];
if (!empty($childGUID)) $data[SYSTEM_EVENT_OGUID] = $childGUID;
@postSystemEvent($data, $childGUID, $callBackLog);
}
// exit the child if we've reached the request limit
if ($requestCounter >= $myRequestsPerInstance) {
if (getmypid() == $thisPid) {
$meta = [
META_SESSION_IP => STRING_SESSION_HOME,
META_SESSION_DAEMON => 1,
META_SESSION_MISC => INFO_BROKER_RECYCLE,
META_EVENT_GUID => $eventGUID
];
$data = [
SYSTEM_EVENT_NAME => SYSEV_NAME_BROKER_RECYCLE,
SYSTEM_EVENT_TYPE => SYSEV_TYPE_BROKER,
SYSTEM_EVENT_BROKER_ROOT_GUID => $groot,
SYSTEM_EVENT_BROKER_GUID => $childGUID,
DB_EVENT_GUID => $eventGUID,
SYSTEM_EVENT_START => $startingMemory,
SYSTEM_EVENT_PEAK => memory_get_peak_usage(true),
SYSTEM_EVENT_END => memory_get_usage(true),
SYSTEM_EVENT_BROKER_EVENT => $event,
SYSTEM_EVENT_COUNT => $requestCounter,
SYSTEM_EVENT_COUNT_TOTAL => $myRequestsPerInstance,
SYSTEM_EVENT_META_DATA => $meta,
SYSTEM_EVENT_CODE_LOC => basename(__FILE__) . COLON . __LINE__
];
@postSystemEvent($data, $eventGUID, $callBackLog);
}
consoleLog($res, CON_SYSTEM, INFO_BROKER_REQ_COUNT);
exit(0);
}
};
consoleLog($res, CON_SYSTEM, sprintf(INFO_BROKER_QUEUE_ESTABLISHED, BROKER_QUEUE_AO, $thisPid, $myRequestsPerInstance));
$brokerChannel->basic_qos(null, 1, null);
$brokerChannel->basic_consume($queue, '', false, false, false, false, $callback);
while (count($brokerChannel->callbacks)) {
try {
$brokerChannel->wait();
} catch (Throwable $t) {
$hdr = basename(__FILE__) . AT . __LINE__ . COLON;
@handleExceptionMessaging($hdr, $t->getMessage(), $foo, true);
}
}
break;
case 1 : // parent
// does nothing
break;
}
return($thisPid);
}
for ($numBrokers = 0; $numBrokers < $runningBrokers; $numBrokers++) {
$childrenPidList[] = forkMe();
}
consoleLog($res, CON_SUCCESS, sprintf(INFO_BROKER_PARENT_STARTED, count($childrenPidList), BROKER_QUEUE_AO));
// "register" the broker instantiation event
$data = [
SYSTEM_EVENT_NAME => SYSEV_NAME_GROOT_REG,
SYSTEM_EVENT_TYPE => SYSEV_TYPE_BROKER,
SYSTEM_EVENT_BROKER_ROOT_GUID => $groot,
SYSTEM_EVENT_KEY => STRING_NUMBER_CHILDREN,
SYSTEM_EVENT_VAL => $numberChildren,
SYSTEM_EVENT_CODE_LOC => basename(__FILE__) . COLON . __LINE__,
SYSTEM_EVENT_NOTES => BROKER_SYSEV_REG . rtrim($res, ": ")
];
@postSystemEvent($data, $groot, $parentLog);
// the parent process continues to run, waking-up every second to monitor it's children...
// when a child dies, it's death-rattle is caught and the child is replaced with a new process.
while (count($childrenPidList)) {
$lastPid = 0;
$newPidList = null;
$result = pcntl_waitpid(0, $status); // detect any sigchld from the parent-group
if (in_array($result, $childrenPidList)) {
$key = array_search($result, $childrenPidList);
array_splice($childrenPidList, $key, 1);
// process has already exited -- restart it
$childrenPidList[] = forkMe();
}
}