Files
namaste/config/bootstrap.inc
gramps 373ebc8c93 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.
2026-04-05 09:49:30 -07:00

241 lines
9.9 KiB
PHP

<?php
define('PHP_MINIMUM_VERSION', 70401);
/**
* common directives for rabbitMQ daemons to load environment configuration:
* - set directory paths
* - install the autoloader
* - install the amqp library (rabbitMQ) if required (defined in constants)
* - declare globals
* - load the common files/functions
* - initialize the singleton configuration global
*
* this file should be required by ALL rabbitMQ daemons (brokers)
*
* @author mike@givingassistant.org
* @version 1.0
*
* HISTORY:
* --------
* 06-07-17 MKS initial coding
* 06-13-17 mks reversed the config file paradigm - the default is now to load a development-level
* configuration and overwrite it with the env.xml file, if it exists.
* 05-31-18 mks CORE-1011: update for new XML broker services configuration
* 06-08-18 mks CORE-1034: deprecated prodBox XML tag
* 06-13-18 mks CORE-1048: improved diagnostic logging/start-up messages, deprecated node-check
* 06-15-18 mks CORE-1045: deprecated CONFIG_ID_NODE tag
* 07-10-18 mks CORE-773: replaced echo statements with consoleLog()
* 07-24-18 mks CORE-1097: cleaning up logging output
* 09-02-18 mks DB-43: Parse exception-handling wrappers around require statements
* 11-29-18 mks DB-51: cleaning up debug/log messages
* 05-23-19 mks DB-116: work-around for array_key_first() (PHP 7.3 only function)
* 10-12-20 mks DB-156: fixed debug check for broker services
*
*/
$eos = (isset($_SERVER['HTTP_USER_AGENT'])) ? '<br />' : PHP_EOL;
$res = 'BOOT: '; // console log identifier
function gt(): string
{
global $res;
$cs = ' [ S]';
return('[' . date("d/m/y@H:i:s", time()) . ']' . $cs . $res);
}
// add a version check for php
if (PHP_VERSION_ID < PHP_MINIMUM_VERSION) exit ('A version of PHP >= 7.4.1 is required to run Namaste.' . PHP_EOL);
$topDir = dirname( __DIR__ );
if (!file_exists($topDir . '/logs')) { // <-- using the logs literal because constants not loaded yet
echo gt() . 'ERROR - LOG DIRECTORY DOES NOT EXIST - NAMASTE CANNOT RUN.' . PHP_EOL;
echo gt() . 'Please fix this problem immediately.' . PHP_EOL . PHP_EOL;
die();
}
// set-up the log files
$logFile = $topDir . '/logs/namaste.log';
$logErrors = $topDir . '/logs/namaste_err.log';
$logs = [ $logFile, $logErrors ];
foreach ($logs as $log) {
if (!file_exists($log)) {
echo gt() . 'Creating logfile: ' . $log . PHP_EOL;
touch($log);
}
}
// redirect i/o for console logging
if (!isset($_REDIRECT)) $_REDIRECT = true;
if ($_REDIRECT) {
@fclose(STDIN);
@fclose(STDOUT);
@fclose(STDERR);
}
@$STDIN = fopen('/dev/null', 'r');
if (!@$STDOUT = fopen($logFile, 'a+b')) {
echo gt() . 'Error - unable to open ' . $logFile . ' for logging' . PHP_EOL;
exit(1);
}
if (!@$STDERR = fopen($logErrors, 'a+b')) {
if (!$STDOUT) {
echo gt() . 'Error - unable to open ' . $logErrors . ' for error logging' . PHP_EOL;
} else {
fwrite($STDOUT, gt() . 'Error - unable to open: ' . $logErrors . ' for error logging' . PHP_EOL);
}
exit(1);
}
// =-=-=-=-= from this point forward, must use fwrite(STDERR|STDOUT) for console logging =-=-=-=-=
fwrite($STDOUT, gt() . 'Loading common files...' . PHP_EOL);
// load the files stored in the common directory
foreach(glob($topDir . '/common/*.php') as $filename) {
fwrite($STDOUT, gt() . 'Loading: ' . $filename . PHP_EOL);
try {
/** @noinspection PhpIncludeInspection */
require_once($filename);
} catch (ParseError $p) {
echo gt() . 'Caught parse exception in ' . $filename . PHP_EOL;
echo gt() . $p->getMessage() . PHP_EOL;
exit(1);
}
}
// ---------------------- system constants and error messages are now available -------------------------
$classesDir = $topDir . DIR_CLASSES;
$configDir = $topDir . DIR_CONFIG;
$amqpLib = $topDir . DIR_LIB;
$templateDir = $topDir . DIR_CLASSES . DIR_TEMPLATE;
$logDir = $topDir . DIR_LOGS;
date_default_timezone_set(STRING_SYS_TZ);
fwrite($STDOUT, gt() . 'Loading framework autoloader...' . PHP_EOL);
try {
/** @noinspection PhpIncludeInspection */
require($topDir . FILE_AUTOLOADER);
} catch (ParseError $p) {
echo gt() . 'Caught parse exception in ' . $topDir . FILE_AUTOLOADER . PHP_EOL;
echo gt() . $p->getMessage() . PHP_EOL;
exit(1);
}
if(file_exists($classesDir)) {
Autoloader::register_directory($classesDir);
Autoloader::register_directory($templateDir);
}
fwrite($STDOUT, gt() . 'Loading vendor-library autoloader...' . PHP_EOL);
// php-amqplib load (v2)
if (!file_exists($amqpLib)) {
fwrite($STDERR, getDateTime() . CON_SYSTEM . $res . ERROR_LIB_404 . $amqpLib . PHP_EOL);
die();
}
try {
$loadFile = $amqpLib . '/vendor/autoload.php';
/** @noinspection PhpIncludeInspection */
require_once $loadFile;
} catch (ParseError $p) {
echo gt() . 'Caught parse exception in ' . $loadFile . PHP_EOL;
echo gt() . $p->getMessage() . PHP_EOL;
exit(1);
}
use /** @noinspection PhpUnusedAliasInspection */ PhpAmqpLib\Connection\AMQPStreamConnection;
use /** @noinspection PhpUnusedAliasInspection */ PhpAmqpLib\Channel\AMQPChannel;
use /** @noinspection PhpUnusedAliasInspection */ PhpAmqpLib\Message\AMQPMessage;
// check to ensure required functions are installed and supported on the server.
// if not, then error to the console and exit.
// pcntl extension is disabled in Apache PHP but enabled in cli-PHP
if (!extension_loaded('pcntl') and !isset($_SERVER['HTTP_USER_AGENT'])) {
consoleLog($res, CON_ERROR, 'API for Process Control may be missing. See: http://www.php.net/manual/en/pcntl.installation.php');
}
if (extension_loaded('pcntl') and isset($_SERVER['HTTP_USER_AGENT'])) {
consoleLog($res, CON_ERROR, 'PCNTL extension SHOULD NOT BE LOADED IN APACHE-PHP! (SECURITY VIOLATION)');
exit(1);
}
/**
* initialize the static configuration object which is used throughout the framework
*
* Since there does not exist a way to gracefully handle errors via the error object,
* we have to output generated errors to STDOUT and let the console operator proceed
* from there with whatever diagnostics we supplied.
*
* generally speaking, we load the namaste.xml configuration -- which, by design, is
* a development-level configuration file.
*
* the env.xml file is optional -- if it exists, it will be loaded and duplicate keys
* in the namaste.xml file will be replaced by the env.xml elements.
*
*/
fwrite($STDOUT, gt() . 'Loading base configuration....' . PHP_EOL);
if (!file_exists($configDir . FILE_BASE_CONFIG)) {
fwrite($STDERR, gt() . ' [ !] COMMON - could not locate base configuration file.' . PHP_EOL);
fwrite($STDERR, gt() . ' [ !] check that ' . FILE_BASE_CONFIG . ' exists in the' . PHP_EOL);
fwrite($STDERR, gt() . ' [ !] directory: ' . $configDir . '.' . PHP_EOL);
} else {
// load the base configuration
if (!gasConfig::singleton($configDir . FILE_BASE_CONFIG, FILE_TYPE_XML)) {
fwrite($STDERR, gt() . ' [ !] COMMON - could not load base configuration file.' . PHP_EOL);
fwrite($STDERR, gt() . ' [ !] file: ' . FILE_BASE_CONFIG . PHP_EOL);
fwrite($STDERR, gt() . ' [ !] directory: ' . $configDir . PHP_EOL);
exit(1);
}
}
// make sure a base config was loaded
if (empty(gasConfig::$settings)) {
fwrite($STDERR, gt() . ' [ !] COMMON - unknown error raised loading base configuration file - program ends.' . PHP_EOL);
}
if (!isset(gasConfig::$settings[CONFIG_ID][CONFIG_ID_ENV])) {
fwrite($STDERR, gt() . ' [ !] COMMON - Have not defined environment status relative to an environment.' . PHP_EOL);
fwrite($STDERR, gt() . ' Check the base configuration file: ' . FILE_BASE_CONFIG . PHP_EOL);
fwrite($STDERR, gt() . ' for the xml-label: ' . CONFIG_ID_ENV . PHP_EOL);
exit(1);
}
fwrite($STDOUT, gt() . 'Loading and layering env configuration....' . PHP_EOL);
// load the environment configuration -- if an error occurs loading the env.xml file, then execution will cease.
if (file_exists($configDir . FILE_ENV_CONFIG)) {
gasConfig::addConfig($configDir . FILE_ENV_CONFIG, FILE_TYPE_XML);
if (!gasConfig::$status) {
fwrite($STDERR, gt() . ' [ !] COMMON - Unable to successfully load the namaste.xml file.' . PHP_EOL);
exit(1);
}
}
// set the rabbitMQ debug if namaste has debug on in the XML under broker-services
define('AMQP_DEBUG', ((gasConfig::$settings[CONFIG_BROKER_SERVICES][CONFIG_BROKER_DEBUG]) ? true : false));
// deprecated via CORE-1011
//// these are the only valid node names
//fwrite($STDOUT, gt() . 'Validating service environments....' . PHP_EOL);
//$validNodes = [ CONFIG_ID_NODE_NAMASTE, CONFIG_ID_NODE_ADMIN, CONFIG_ID_NODE_DEV ];
//if (!in_array(gasConfig::$settings[CONFIG_ID][CONFIG_ID_NODE], $validNodes)) {
// $msg = sprintf(' [ X] COMMON - check the configuration: %s is not a valid node id (cfg.id.nodename)', gasConfig::$settings[CONFIG_ID][CONFIG_ID_NODE]);
// fwrite($STDERR, $msg);
// exit(1);
//}
// initialize the global objects - failures for each object are generated within the object's constructors
// and are sent to stdout...
// initialize the global Resource Manager object
fwrite($STDOUT, gt() . $res . 'Loading resource manager....' . PHP_EOL);
if (!isset(gasResourceManager::$available) or !gasResourceManager::$available) {
gasResourceManager::singleton();
if (!gasResourceManager::$IPL) {
consoleLog($res, CON_ERROR, ERROR_FW_IPL);
} else {
gasResourceManager::$available = true;
}
}
// initialize the global Memcache object
fwrite($STDOUT, gt() . $res . 'Loading memcache manager....' . PHP_EOL);
if (!isset(gasCache::$available) or !gasCache::$available) {
gasCache::singleton();
}
fwrite($STDOUT, gt() . $res . 'Loading static manager....' . PHP_EOL);
if (!isset(gasStatic::$available) or !gasStatic::$available) {
gasStatic::singleton();
}