From ad314308b7d59217b22ffd77b093af2b91edf984 Mon Sep 17 00:00:00 2001 From: inhere Date: Mon, 25 Sep 2017 18:14:24 +0800 Subject: [PATCH] update ... --- boot/app.php | 3 +- examples/asyn_mysql_pool_test.php | 2 +- examples/co_mysql_pool_test.php | 2 +- lib/sws/Application.php | 22 +- .../{Components => Async}/AsyncMysqlPool.php | 6 +- lib/sws/Async/StreamHandler.php | 28 ++ lib/sws/Cache/CacheInterface.php | 18 + lib/sws/Context/ContextManager.php | 1 + lib/sws/Context/HttpContext.php | 1 + .../CoroMysqlPool.php | 11 +- .../CoroRedisPool.php | 11 +- lib/sws/{Context => Coroutine}/Coroutine.php | 4 +- lib/sws/Memory/FileLogHandler.php | 433 ------------------ lib/sws/{Tables => Memory}/MemTable.php | 4 +- .../{Tables/User.php => Memory/UserTable.php} | 8 +- resources/middleware-app.png | Bin 0 -> 22392 bytes 16 files changed, 88 insertions(+), 466 deletions(-) rename lib/sws/{Components => Async}/AsyncMysqlPool.php (94%) create mode 100644 lib/sws/Async/StreamHandler.php create mode 100644 lib/sws/Cache/CacheInterface.php rename lib/sws/{Components => Coroutine}/CoroMysqlPool.php (74%) rename lib/sws/{Components => Coroutine}/CoroRedisPool.php (65%) rename lib/sws/{Context => Coroutine}/Coroutine.php (96%) delete mode 100644 lib/sws/Memory/FileLogHandler.php rename lib/sws/{Tables => Memory}/MemTable.php (98%) rename lib/sws/{Tables/User.php => Memory/UserTable.php} (94%) create mode 100644 resources/middleware-app.png diff --git a/boot/app.php b/boot/app.php index 7089a63..4b831de 100644 --- a/boot/app.php +++ b/boot/app.php @@ -10,6 +10,7 @@ use inhere\library\di\Container; use inhere\library\collections\Configuration; +use Sws\Async\StreamHandler; // autoload require dirname(__DIR__) . '/vendor/autoload.php'; @@ -37,7 +38,7 @@ $di->set('logger', function (Container $di) { $opts = $di->get('config')->get('logger', []); - $fileHandler = new \Monolog\Handler\StreamHandler($opts['file']); + $fileHandler = new StreamHandler($opts['file']); $mainHandler = new \Monolog\Handler\FingersCrossedHandler($fileHandler, (int)$opts['level'], $opts['bufferSize']); $logger = new \Monolog\Logger($opts['name']); diff --git a/examples/asyn_mysql_pool_test.php b/examples/asyn_mysql_pool_test.php index 2c08ce9..c7f004e 100644 --- a/examples/asyn_mysql_pool_test.php +++ b/examples/asyn_mysql_pool_test.php @@ -8,7 +8,7 @@ require dirname(__DIR__) . '/vendor/autoload.php'; use Swoole\Http\Response; -use Sws\Components\AsyncMysqlPool; +use Sws\Async\AsyncMysqlPool; $host = '127.0.0.1'; $port = 8399; diff --git a/examples/co_mysql_pool_test.php b/examples/co_mysql_pool_test.php index dbf901e..fa28e5e 100644 --- a/examples/co_mysql_pool_test.php +++ b/examples/co_mysql_pool_test.php @@ -20,7 +20,7 @@ function debug($msg, array $data = []) } -$pool = new \Sws\Components\CoroMysqlPool([ +$pool = new \Sws\Coroutine\CoroMysqlPool([ 'initSize' => 0, 'maxSize' => 1, ]); diff --git a/lib/sws/Application.php b/lib/sws/Application.php index 14f4f41..1b9311a 100644 --- a/lib/sws/Application.php +++ b/lib/sws/Application.php @@ -11,11 +11,7 @@ use inhere\console\utils\Show; use Inhere\Http\Request; use Inhere\Http\Response; -use inhere\library\collections\Configuration; -use inhere\library\log\Logger; -use Inhere\Route\ORouter; -use Inhere\Server\Helpers\StaticAccessHandler; -use Inhere\Server\Rpc\RpcDispatcher; +use Inhere\Server\Components\StaticResourceProcessor; use Inhere\Server\Servers\HttpServer; use Swoole\Http\Request as SwRequest; use Swoole\Http\Response as SwResponse; @@ -24,7 +20,6 @@ use Sws\Components\HttpHelper; use Sws\Context\ContextManager; use Sws\Context\HttpContext; -use Sws\Memory\Language; use Sws\Module\ModuleInterface; use Sws\Module\RootModule; use Sws\WebSocket\Connection; @@ -81,6 +76,19 @@ protected function beforeRun() $this->options['assets'] = $this->get('config')->get('assets', []); } + protected $middlewares = []; + + /** + * @param callable $cb middleware :: (Context $ctx, $next) -> void + * @return $this + */ + public function use(callable $cb) + { + $this->middlewares[] = $cb; + + return $this; + } + public function preLoading() { // collect routes @@ -123,7 +131,7 @@ protected function beforeServerStart() $config = $this->options['assets']; // static handle - $this->staticAccessHandler = new StaticAccessHandler(BASE_PATH, $config['ext'], $config['dirMap']); + $this->staticAccessHandler = new StaticResourceProcessor(BASE_PATH, $config['ext'], $config['dirMap']); } /** diff --git a/lib/sws/Components/AsyncMysqlPool.php b/lib/sws/Async/AsyncMysqlPool.php similarity index 94% rename from lib/sws/Components/AsyncMysqlPool.php rename to lib/sws/Async/AsyncMysqlPool.php index 00d10ee..39beef9 100644 --- a/lib/sws/Components/AsyncMysqlPool.php +++ b/lib/sws/Async/AsyncMysqlPool.php @@ -6,16 +6,16 @@ * Time: 16:30 */ -namespace Sws\Components; +namespace Sws\Async; -use Inhere\Pool\Swoole\ResourcePool; +use Inhere\Pool\Swoole\CoroSuspendPool; use Swoole\MySQL; /** * Class AsyncMysqlPool * @package Sws\Components */ -class AsyncMysqlPool extends ResourcePool +class AsyncMysqlPool extends CoroSuspendPool { /** * @var array diff --git a/lib/sws/Async/StreamHandler.php b/lib/sws/Async/StreamHandler.php new file mode 100644 index 0000000..338a419 --- /dev/null +++ b/lib/sws/Async/StreamHandler.php @@ -0,0 +1,28 @@ +url, (string) $record['formatted'], $this->onWriteEnd, FILE_APPEND); + } +} \ No newline at end of file diff --git a/lib/sws/Cache/CacheInterface.php b/lib/sws/Cache/CacheInterface.php new file mode 100644 index 0000000..95b2584 --- /dev/null +++ b/lib/sws/Cache/CacheInterface.php @@ -0,0 +1,18 @@ +options['db1']; $db = new MySQL(); -// debug('coId:' . Coroutine::getuid() . ' will create new db connection'); +// debug('coId:' . Coroutine::id() . ' will create new db connection'); $db->connect($conf); -// debug('coId:' . Coroutine::getuid() . ' a new db connection created'); +// debug('coId:' . Coroutine::id() . ' a new db connection created'); return $db; } diff --git a/lib/sws/Components/CoroRedisPool.php b/lib/sws/Coroutine/CoroRedisPool.php similarity index 65% rename from lib/sws/Components/CoroRedisPool.php rename to lib/sws/Coroutine/CoroRedisPool.php index b4d1777..e12a4b2 100644 --- a/lib/sws/Components/CoroRedisPool.php +++ b/lib/sws/Coroutine/CoroRedisPool.php @@ -6,17 +6,16 @@ * Time: 15:11 */ -namespace Sws\Components; +namespace Sws\Coroutine; -use Inhere\Pool\Swoole\ResourcePool; -use Swoole\Coroutine; +use Inhere\Pool\Swoole\CoroSuspendPool; use Swoole\Coroutine\Redis; /** * Class CoroRedisPool * @package Sws\Components */ -class CoroRedisPool extends ResourcePool +class CoroRedisPool extends CoroSuspendPool { /** * 创建新的资源实例 @@ -26,11 +25,11 @@ public function create() { $rds = new Redis(); -// debug('coId:' . Coroutine::getuid() . ' will create new redis connection'); +// debug('coId:' . Coroutine::id() . ' will create new redis connection'); $rds->connect('redis', 6379); -// debug('coId:' . Coroutine::getuid() . ' a new redis connection created'); +// debug('coId:' . Coroutine::id() . ' a new redis connection created'); return $rds; } diff --git a/lib/sws/Context/Coroutine.php b/lib/sws/Coroutine/Coroutine.php similarity index 96% rename from lib/sws/Context/Coroutine.php rename to lib/sws/Coroutine/Coroutine.php index 5b7afe0..84f8864 100644 --- a/lib/sws/Context/Coroutine.php +++ b/lib/sws/Coroutine/Coroutine.php @@ -6,14 +6,14 @@ * Time: 14:33 */ -namespace Sws\Context; +namespace Sws\Coroutine; use inhere\library\helpers\PhpHelper; use Swoole\Coroutine as SwCoroutine; /** * Class Coroutine - * @package Sws\Context + * @package Sws\Coroutine */ class Coroutine { diff --git a/lib/sws/Memory/FileLogHandler.php b/lib/sws/Memory/FileLogHandler.php deleted file mode 100644 index 47e3250..0000000 --- a/lib/sws/Memory/FileLogHandler.php +++ /dev/null @@ -1,433 +0,0 @@ - 'EMERGENCY', - self::ERROR => 'ERROR', - self::WARN => 'WARNING', - self::INFO => 'INFO', - self::PROC_INFO => 'PROC_INFO', - self::WORKER_INFO => 'WORKER_INFO', - self::DEBUG => 'DEBUG', - self::CRAZY => 'CRAZY', - ]; - - /** - * ProcessLogger constructor. - * @param array $config - */ - public function __construct(array $config = []) - { - foreach ($config as $prop => $value) { - $this->$prop = $value; - } - - $this->init(); - } - - /** - * init - */ - protected function init() - { - $this->fileHandle = null; - $this->level = (int)$this->level; - $this->logThreshold = (int)$this->logThreshold; - $this->toSyslog = (bool)$this->toSyslog; - $this->toConsole = (bool)$this->toConsole; - - if ($this->file === 'syslog') { - $this->file = null; - $this->toSyslog = true; - } - - if ($this->spiltType && !in_array($this->spiltType, [self::SPLIT_DAY, self::SPLIT_HOUR], true)) { - $this->spiltType = self::SPLIT_DAY; - } - - // open Log File - $this->open(); - } - - /** - * Debug log - * @param string $msg - * @param array $data - */ - public function debug($msg, array $data = []) - { - $this->log($msg, self::DEBUG, $data); - } - - /** - * Exception log - * @param \Throwable $e - * @param string $preMsg - */ - public function ex(\Throwable $e, $preMsg = '') - { - $preMsg = $preMsg ? "$preMsg " : ''; - - $this->log(sprintf( - "{$preMsg}Exception: %s On %s Line %s\nCode Trace:\n%s", - $e->getMessage(), - $e->getFile(), - $e->getLine(), - $e->getTraceAsString() - ), self::ERROR); - } - - /** - * Logs data to disk or stdout - * @param string $msg - * @param int $level - * @param array $data - * @return bool - */ - public function log($msg, $level = self::INFO, array $data = []) - { - if (is_numeric($level) && $level > $this->level) { - return true; - } - - $strData = $data ? json_encode($data) : ''; - - if ($this->toSyslog) { - return $this->sysLog($msg . ' ' . $strData, $level); - } - - $label = self::getLevelName($level); - $ds = FormatHelper::microTime(microtime(true)); - - // [$this->getPidRole():$this->pid] $msg - $logString = sprintf("[%s] [%s] %s %s\n", $ds, $label, trim($msg), $strData); - - // if not in daemon, print log to \STDOUT - if (!$this->toConsole) { - $this->stdout($logString, false); - } - - if ($this->fileHandle) { - $this->count++; - $this->cache[] = CliHelper::clearColor($logString); - - if ($this->count >= $this->logThreshold || $this->fileIsChanged()) { - $this->flush(); - } - } - - return true; - } - - /** - * flush - */ - public function flush() - { - if (!$this->cache) { - return true; - } - - $string = ''; - - foreach ($this->cache as $log) { - $string .= $log; - } - - if ($string) { - $this->updateLogFile(); - - fwrite($this->fileHandle, $string); - } - - $this->count = 0; - $this->cache = []; - - return true; - } - - protected function fileIsChanged() - { - if (!$this->fileHandle || !($file = $this->file)) { - return false; - } - - if (!$this->spiltType) { - return false; - } - - $str = $this->getLogFileDate(); - - return !strpos($file, '_' . $str); - } - - /** - * update the log file name. If 'log_split' is not empty and manager running to long time. - */ - protected function updateLogFile() - { - // update file. $dtStr is '_Y-m-d' or '_Y-m-d_H' - if ($this->fileIsChanged()) { - fclose($this->fileHandle); - - $logFile = $this->genLogFile(true); - $this->file = $logFile; - $this->fileHandle = @fopen($logFile, 'ab'); - - if (!$this->fileHandle) { - $this->stderr("Could not open the log file {$logFile}"); - } - } - } - - /** - * Opens the log file. If already open, closes it first. - */ - public function open() - { - if ($logFile = $this->genLogFile(true)) { - if ($this->fileHandle) { - fclose($this->fileHandle); - } - - $this->file = $logFile; - $this->fileHandle = @fopen($logFile, 'ab'); - - if (!$this->fileHandle) { - $this->stderr("Could not open the log file {$logFile}"); - } - } - } - - /** - * close - */ - public function close() - { - // close logFileHandle - if ($this->fileHandle) { - $this->flush(); - fclose($this->fileHandle); - - $this->fileHandle = null; - } - } - - /** - * gen real LogFile - * @param bool $createDir - * @return string - */ - public function genLogFile($createDir = false) - { - // log split type - if (!($type = $this->spiltType) || !($file = $this->file)) { - return $this->file; - } - - $info = pathinfo($file); - $dir = $info['dirname']; - $name = $info['filename'] ?? 'gw-manager'; - $ext = $info['extension'] ?? 'log'; - - if ($createDir) { - Directory::mkdir($dir, 0775); - } - - $str = $this->getLogFileDate(); - - return "{$dir}/{$name}_{$str}.{$ext}"; - } - - /** - * @return string - */ - public function getLogFileDate() - { - $str = ''; - - if ($this->spiltType === self::SPLIT_DAY) { - $str = date('Y-m-d'); - } elseif ($this->spiltType === self::SPLIT_HOUR) { - $str = date('Y-m-d_H'); - } - - return $str; - } - - /** - * Logs data to stdout - * @param string $text - * @param bool $nl - * @param bool|int $quit - */ - protected function stdout($text, $nl = true, $quit = false) - { - CliHelper::stdout($text, $nl, $quit); - } - - /** - * Logs data to stderr - * @param string $text - * @param bool $nl - * @param bool|int $quit - */ - protected function stderr($text, $nl = true, $quit = -200) - { - CliHelper::stderr($text, $nl, $quit); - } - - /** - * Logs data to the syslog - * @param string $msg - * @param int $level - * @return bool - */ - protected function sysLog($msg, $level) - { - switch ($level) { - case self::EMERG: - $priority = LOG_EMERG; - break; - case self::ERROR: - $priority = LOG_ERR; - break; - case self::WARN: - $priority = LOG_WARNING; - break; - case self::DEBUG: - $priority = LOG_DEBUG; - break; - case self::INFO: - case self::PROC_INFO: - case self::WORKER_INFO: - default: - $priority = LOG_INFO; - break; - } - - if (!$ret = syslog($priority, $msg)) { - $this->stderr("Unable to write to syslog\n"); - } - - return $ret; - } - - /** - * @return array - */ - public static function getLevels() - { - return self::$levels; - } - - /** - * @param int|string $level - * @return string - */ - public static function getLevelName($level) - { - if (is_numeric($level)) { - return self::$levels[$level] ?? 'Unknown'; - } - - return strtoupper($level); - } - - /** - * getFile - * @return string - */ - public function getFile() - { - return $this->file; - } - - /** - * __destruct - */ - public function __destruct() - { - $this->close(); - } -} diff --git a/lib/sws/Tables/MemTable.php b/lib/sws/Memory/MemTable.php similarity index 98% rename from lib/sws/Tables/MemTable.php rename to lib/sws/Memory/MemTable.php index 5611fbf..9afb6ce 100644 --- a/lib/sws/Tables/MemTable.php +++ b/lib/sws/Memory/MemTable.php @@ -6,13 +6,13 @@ * Time: 上午1:17 */ -namespace Sws\Tables; +namespace Sws\Memory; use Swoole\Table; /** * Class BaseTable - * @package Sws\Tables + * @package Sws\Memory * * Table使用共享内存来保存数据,在创建子进程前,务必要执行Table->create() * swoole_server中使用Table,Table->create() 必须在 swoole_server->start()前执行 diff --git a/lib/sws/Tables/User.php b/lib/sws/Memory/UserTable.php similarity index 94% rename from lib/sws/Tables/User.php rename to lib/sws/Memory/UserTable.php index a203783..d9a554e 100644 --- a/lib/sws/Tables/User.php +++ b/lib/sws/Memory/UserTable.php @@ -6,15 +6,15 @@ * Time: 下午1:05 */ -namespace Sws\Tables; +namespace Sws\Memory; use Swoole\Table; /** - * Class User - * @package Sws\Tables + * Class UserTable + * @package Sws\Memory */ -class User +class UserTable { /** * @var string diff --git a/resources/middleware-app.png b/resources/middleware-app.png new file mode 100644 index 0000000000000000000000000000000000000000..a9fc265d61333b21e7c1af99086fb03073b0d95e GIT binary patch literal 22392 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