This commit is contained in:
as2252258@163.com
2021-07-26 04:59:03 +08:00
parent abdaeb3e08
commit 826b3b2102
7 changed files with 394 additions and 342 deletions
+2 -20
View File
@@ -126,7 +126,7 @@ class ActiveRecord extends BaseActiveRecord
if (empty($attributes)) { if (empty($attributes)) {
return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql'); return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql');
} }
$select = self::getModelClass(); $select = duplicate(static::class);
$select->attributes = $attributes; $select->attributes = $attributes;
if (!$select->save()) { if (!$select->save()) {
return $logger->addError($select->getLastError(), 'mysql'); return $logger->addError($select->getLastError(), 'mysql');
@@ -150,7 +150,7 @@ class ActiveRecord extends BaseActiveRecord
/** @var static $select */ /** @var static $select */
$select = static::find()->where($condition)->first(); $select = static::find()->where($condition)->first();
if (empty($select)) { if (empty($select)) {
$select = self::getModelClass(); $select = duplicate(static::class);
} }
$select->attributes = $attributes; $select->attributes = $attributes;
if (!$select->save()) { if (!$select->save()) {
@@ -160,20 +160,6 @@ class ActiveRecord extends BaseActiveRecord
} }
/**
* @return static
* @throws Exception
*/
private static function getModelClass(): static
{
/** @var Channel $channel */
$channel = Snowflake::app()->get('channel');
return $channel->pop(static::class, function () {
return new static();
});
}
/** /**
* @param $action * @param $action
* @param $columns * @param $columns
@@ -306,10 +292,6 @@ class ActiveRecord extends BaseActiveRecord
$data[$key] = $this->{$item}($data[$key] ?? null); $data[$key] = $this->{$item}($data[$key] ?? null);
} }
$data = array_merge($data, $this->runRelate()); $data = array_merge($data, $this->runRelate());
$class = Snowflake::app()->getChannel();
$class->push($this, static::class);
return $data; return $data;
} }
+109 -115
View File
@@ -26,142 +26,136 @@ use Traversable;
abstract class AbstractCollection extends Component implements \IteratorAggregate, \ArrayAccess abstract class AbstractCollection extends Component implements \IteratorAggregate, \ArrayAccess
{ {
/** /**
* @var ActiveRecord[] * @var ActiveRecord[]
*/ */
protected array $_item = []; protected array $_item = [];
protected ActiveRecord|string|null $model; protected ActiveRecord|string|null $model;
protected ActiveQuery $query; protected ActiveQuery $query;
public function clean() public function clean()
{ {
unset($this->query, $this->model, $this->_item); unset($this->query, $this->model, $this->_item);
} }
/** /**
* Collection constructor. * Collection constructor.
* *
* @param $query * @param $query
* @param array $array * @param array $array
* @param string|ActiveRecord|null $model * @param string|ActiveRecord|null $model
* @throws Exception * @throws Exception
*/ */
public function __construct($query, array $array = [], string|ActiveRecord $model = null) public function __construct($query, array $array = [], string|ActiveRecord $model = null)
{ {
$this->_item = $array; $this->_item = $array;
$this->query = $query; $this->query = $query;
$this->model = $model; $this->model = duplicate($model);
parent::__construct([]); parent::__construct([]);
} }
/** /**
* @return int * @return int
*/ */
#[Pure] public function getLength(): int #[Pure] public function getLength(): int
{ {
return count($this->_item); return count($this->_item);
} }
/** /**
* @param $item * @param $item
*/ */
public function setItems($item) public function setItems($item)
{ {
$this->_item = $item; $this->_item = $item;
} }
/** /**
* @param $model * @param $model
*/ */
public function setModel($model) public function setModel($model)
{ {
$this->model = $model; $this->model = $model;
} }
/** /**
* @param $item * @param $item
*/ */
public function addItem($item) public function addItem($item)
{ {
array_push($this->_item, $item); array_push($this->_item, $item);
} }
/** /**
* @return Traversable|CollectionIterator|ArrayIterator * @return Traversable|CollectionIterator|ArrayIterator
* @throws Exception * @throws Exception
*/ */
public function getIterator(): Traversable|CollectionIterator|ArrayIterator public function getIterator(): Traversable|CollectionIterator|ArrayIterator
{ {
return new CollectionIterator($this->model, $this->query, $this->_item); return new CollectionIterator($this->model, $this->query, $this->_item);
} }
/** /**
* @return mixed * @return mixed
* @throws Exception * @throws Exception
*/ */
public function getModel(): ActiveRecord public function getModel(): ActiveRecord
{ {
if (!is_object($this->model)) { return $this->model;
$this->model = duplicate($this->model); }
$this->model->setIsCreate(false);
}
return $this->model;
}
/** /**
* @param mixed $offset * @param mixed $offset
* @return bool * @return bool
*/ */
public function offsetExists(mixed $offset): bool public function offsetExists(mixed $offset): bool
{ {
return !empty($this->_item) && isset($this->_item[$offset]); return !empty($this->_item) && isset($this->_item[$offset]);
} }
/** /**
* @param mixed $offset * @param mixed $offset
* @return ActiveRecord|null * @return ActiveRecord|null
* @throws Exception * @throws Exception
*/ */
public function offsetGet(mixed $offset): ?ActiveRecord public function offsetGet(mixed $offset): ?ActiveRecord
{ {
if (!$this->offsetExists($offset)) { if (!$this->offsetExists($offset)) {
return NULL; return NULL;
} }
if (!($this->_item[$offset] instanceof ActiveRecord)) {
return $this->model->setAttributes($this->_item[$offset]);
}
return $this->_item[$offset];
}
if ($this->_item[$offset] instanceof ActiveRecord) { /**
return $this->_item[$offset]; * @param mixed $offset
} * @param mixed $value
*/
return $this->model::populate($this->_item[$offset]); public function offsetSet(mixed $offset, mixed $value)
} {
$this->_item[$offset] = $value;
/** }
* @param mixed $offset
* @param mixed $value
*/
public function offsetSet(mixed $offset, mixed $value)
{
$this->_item[$offset] = $value;
}
/** /**
* @param mixed $offset * @param mixed $offset
*/ */
public function offsetUnset(mixed $offset) public function offsetUnset(mixed $offset)
{ {
if ($this->offsetExists($offset)) { if ($this->offsetExists($offset)) {
unset($this->_item[$offset]); unset($this->_item[$offset]);
} }
} }
} }
+1 -1
View File
@@ -56,7 +56,7 @@ class CollectionIterator extends \ArrayIterator
*/ */
protected function newModel($current): ActiveRecord protected function newModel($current): ActiveRecord
{ {
return $this->model::populate($current); return $this->model->setAttributes($current);
} }
+4 -1
View File
@@ -6,6 +6,7 @@ namespace HttpServer\Http;
use Annotation\Route\Socket; use Annotation\Route\Socket;
use Exception; use Exception;
use HttpServer\Abstracts\HttpService; use HttpServer\Abstracts\HttpService;
use HttpServer\Http\Response as HResponse;
use HttpServer\IInterface\AuthIdentity; use HttpServer\IInterface\AuthIdentity;
use JetBrains\PhpStorm\Pure; use JetBrains\PhpStorm\Pure;
use Snowflake\Abstracts\Config; use Snowflake\Abstracts\Config;
@@ -451,7 +452,7 @@ class Request extends HttpService
* @param \Swoole\Http\Request $request * @param \Swoole\Http\Request $request
* @return mixed * @return mixed
*/ */
public static function create(\Swoole\Http\Request $request): Request public static function create(\Swoole\Http\Request $request, \Swoole\Http\Response $response): Request
{ {
/** @var Request $sRequest */ /** @var Request $sRequest */
$sRequest = Context::setContext('request', new Request()); $sRequest = Context::setContext('request', new Request());
@@ -467,6 +468,8 @@ class Request extends HttpService
$sRequest->uri = $sRequest->headers->get('request_uri'); $sRequest->uri = $sRequest->headers->get('request_uri');
$sRequest->parseUri(); $sRequest->parseUri();
HResponse::create($response);
return $sRequest; return $sRequest;
} }
+73
View File
@@ -0,0 +1,73 @@
<?php
namespace Server;
use Swoole\Coroutine\Channel;
class ApplicationStore
{
private static ?ApplicationStore $applicationStore = null;
private Channel $lock;
private function __construct()
{
$this->lock = new Channel(99999);
}
/**
* @return \Server\ApplicationStore|null
*/
public static function getStore()
{
if (!(static::$applicationStore instanceof ApplicationStore)) {
static::$applicationStore = new ApplicationStore();
}
return static::$applicationStore;
}
public function add()
{
$this->lock->push(1);
return $this;
}
public function waite()
{
$this->lock->pop(-1);
}
public function done()
{
$this->lock->pop();
}
/**
* @return bool
*/
public function isBusy()
{
return !$this->lock->isEmpty();
}
/**
* @return string
*/
public function getStatus(): string
{
return env('state');
}
}
+101 -98
View File
@@ -26,121 +26,124 @@ use Throwable;
class HTTPServerListener extends Abstracts\Server class HTTPServerListener extends Abstracts\Server
{ {
protected static bool|Port $_http; protected static bool|Port $_http;
use ListenerHelper; use ListenerHelper;
private Router $router; private Router $router;
private ApplicationStore $store;
/** /**
* HTTPServerListener constructor. * HTTPServerListener constructor.
* @throws Exception * @throws Exception
*/ */
public function __construct() public function __construct()
{ {
$this->router = Snowflake::getApp('router'); $this->router = Snowflake::getApp('router');
parent::__construct(); $this->store = ApplicationStore::getStore();
} parent::__construct();
}
/** /**
* UDPServerListener constructor. * UDPServerListener constructor.
* @param Server|\Swoole\WebSocket\Server|\Swoole\Http\Server $server * @param Server|\Swoole\WebSocket\Server|\Swoole\Http\Server $server
* @param string $host * @param string $host
* @param int $port * @param int $port
* @param int $mode * @param int $mode
* @param array|null $settings * @param array|null $settings
* @return Server\Port * @return Server\Port
* @throws NotFindClassException * @throws NotFindClassException
* @throws ReflectionException * @throws ReflectionException
* @throws Exception * @throws Exception
*/ */
public static function instance(mixed $server, string $host, int $port, int $mode, ?array $settings = []): Server\Port public static function instance(mixed $server, string $host, int $port, int $mode, ?array $settings = []): Server\Port
{ {
if (!in_array($mode, [SWOOLE_TCP, SWOOLE_TCP6])) { if (!in_array($mode, [SWOOLE_TCP, SWOOLE_TCP6])) {
trigger_error('Port mode ' . $host . '::' . $port . ' must is udp listener type.'); trigger_error('Port mode ' . $host . '::' . $port . ' must is udp listener type.');
} }
/** @var static $reflect */ /** @var static $reflect */
$reflect = Snowflake::getDi()->getReflect(static::class)?->newInstance(); $reflect = Snowflake::getDi()->getReflect(static::class)?->newInstance();
static::$_http = $server->addlistener($host, $port, $mode); static::$_http = $server->addlistener($host, $port, $mode);
if (!(static::$_http instanceof Port)) { if (!(static::$_http instanceof Port)) {
trigger_error('Port is ' . $host . '::' . $port . ' must is tcp listener type.'); trigger_error('Port is ' . $host . '::' . $port . ' must is tcp listener type.');
} }
static::$_http->set($settings['settings'] ?? []); static::$_http->set($settings['settings'] ?? []);
static::$_http->on('request', [$reflect, 'onRequest']); static::$_http->on('request', [$reflect, 'onRequest']);
static::$_http->on('connect', [$reflect, 'onConnect']); static::$_http->on('connect', [$reflect, 'onConnect']);
static::$_http->on('close', [$reflect, 'onClose']); static::$_http->on('close', [$reflect, 'onClose']);
if (swoole_version() >= '4.7.0') { if (swoole_version() >= '4.7.0') {
static::$_http->on('disconnect', [$reflect, 'onDisconnect']); static::$_http->on('disconnect', [$reflect, 'onDisconnect']);
$reflect->setEvents(Constant::DISCONNECT, $settings['events'][Constant::DISCONNECT] ?? null); $reflect->setEvents(Constant::DISCONNECT, $settings['events'][Constant::DISCONNECT] ?? null);
} }
$reflect->setEvents(Constant::CLOSE, $settings['events'][Constant::CLOSE] ?? null); $reflect->setEvents(Constant::CLOSE, $settings['events'][Constant::CLOSE] ?? null);
$reflect->setEvents(Constant::CONNECT, $settings['events'][Constant::CONNECT] ?? null); $reflect->setEvents(Constant::CONNECT, $settings['events'][Constant::CONNECT] ?? null);
return static::$_http; return static::$_http;
} }
/** /**
* @param Server $server * @param Server $server
* @param int $fd * @param int $fd
* @throws Exception * @throws Exception
*/ */
public function onConnect(Server $server, int $fd) public function onConnect(Server $server, int $fd)
{ {
$this->runEvent(Constant::CONNECT, null, [$server, $fd]); $this->runEvent(Constant::CONNECT, null, [$server, $fd]);
$this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES);
} }
/** /**
* @param Request $request * @param Request $request
* @param Response $response * @param Response $response
* @throws Exception * @throws Exception
*/ */
public function onRequest(Request $request, Response $response) public function onRequest(Request $request, Response $response)
{ {
try { try {
[$request, $_] = [HRequest::create($request), HResponse::create($response)]; $request = HRequest::create($request, $response);
if ($request->is('favicon.ico')) { if ($request->is('favicon.ico')) {
throw new Exception('Not found.', 404); throw new Exception('Not found.', 404);
} }
$this->router->dispatch(); $this->router->dispatch();
} catch (ExitException | Error | Throwable $exception) { } catch (ExitException | Error | Throwable $exception) {
$response->setHeader('Content-Type', 'text/html; charset=utf-8'); $response->setHeader('Content-Type', 'text/html; charset=utf-8');
$response->status($exception->getCode() == 0 ? 500 : $exception->getCode()); $response->status($exception->getCode() == 0 ? 500 : $exception->getCode());
$response->end($exception->getMessage()); $response->end($exception->getMessage());
} finally { } finally {
$this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES);
} }
} }
/** /**
* @param Server $server * @param Server $server
* @param int $fd * @param int $fd
* @throws Exception * @throws Exception
*/ */
public function onDisconnect(Server $server, int $fd) public function onDisconnect(Server $server, int $fd)
{ {
$this->runEvent(Constant::DISCONNECT, null, [$server, $fd]); $this->runEvent(Constant::DISCONNECT, null, [$server, $fd]);
$this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES);
} }
/** /**
* @param Server $server * @param Server $server
* @param int $fd * @param int $fd
* @throws Exception * @throws Exception
*/ */
public function onClose(Server $server, int $fd) public function onClose(Server $server, int $fd)
{ {
$this->runEvent(Constant::CLOSE, null, [$server, $fd]); $this->runEvent(Constant::CLOSE, null, [$server, $fd]);
$this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES);
} }
} }
+104 -107
View File
@@ -24,142 +24,139 @@ class ServerWorker extends \Server\Abstracts\Server
{ {
/** /**
* @param Server $server * @param Server $server
* @param int $workerId * @param int $workerId
* @throws Exception * @throws Exception
*/ */
public function onWorkerStart(Server $server, int $workerId) public function onWorkerStart(Server $server, int $workerId)
{ {
$this->_setConfigCache($workerId); $this->_setConfigCache($workerId);
$annotation = Snowflake::app()->getAnnotation(); $annotation = Snowflake::app()->getAnnotation();
$annotation->read(APP_PATH . 'app'); $annotation->read(APP_PATH . 'app');
$this->runEvent(Constant::WORKER_START, null, [$server, $workerId]); $this->runEvent(Constant::WORKER_START, null, [$server, $workerId]);
$this->workerInitExecutor($server, $annotation, $workerId); $this->workerInitExecutor($server, $annotation, $workerId);
} }
/** /**
* @param Server $server * @param Server $server
* @param Annotation $annotation * @param Annotation $annotation
* @param int $workerId * @param int $workerId
* @throws ConfigException * @throws ConfigException
* @throws Exception * @throws Exception
*/ */
private function workerInitExecutor(Server $server, Annotation $annotation, int $workerId) private function workerInitExecutor(Server $server, Annotation $annotation, int $workerId)
{ {
if ($workerId < $server->setting['worker_num']) { if ($workerId < $server->setting['worker_num']) {
$loader = Snowflake::app()->getRouter(); $loader = Snowflake::app()->getRouter();
$loader->_loader(); $loader->_loader();
echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m Worker[%d].%d start.", $server->worker_pid, $workerId) . PHP_EOL; echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m Worker[%d].%d start.", $server->worker_pid, $workerId) . PHP_EOL;
$this->setProcessName(sprintf('Worker[%d].%d', $server->worker_pid, $workerId)); $this->setProcessName(sprintf('Worker[%d].%d', $server->worker_pid, $workerId));
$annotation->runtime(CONTROLLER_PATH); $annotation->runtime(CONTROLLER_PATH);
$annotation->runtime(MODEL_PATH); $annotation->runtime(MODEL_PATH);
} else { } else {
echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m Tasker[%d].%d start.", $server->worker_pid, $workerId) . PHP_EOL; echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m Tasker[%d].%d start.", $server->worker_pid, $workerId) . PHP_EOL;
$this->setProcessName(sprintf('Tasker[%d].%d', $server->worker_pid, $workerId)); $this->setProcessName(sprintf('Tasker[%d].%d', $server->worker_pid, $workerId));
$annotation->runtime(APP_PATH, [CONTROLLER_PATH]); $annotation->runtime(APP_PATH, [CONTROLLER_PATH]);
} }
} }
/**
* @param $worker_id
* @throws Exception
*/
private function _setConfigCache($worker_id)
{
putenv('state=start');
putenv('worker=' . $worker_id);
/** $serialize = file_get_contents(storage(Runtime::CONFIG_NAME));
* @param $worker_id if (empty($serialize)) {
* @throws Exception return;
*/ }
private function _setConfigCache($worker_id) Config::sets(unserialize($serialize));
{ }
putenv('state=start');
putenv('worker=' . $worker_id);
$serialize = file_get_contents(storage(Runtime::CONFIG_NAME));
if (empty($serialize)) {
return;
}
Config::sets(unserialize($serialize));
}
/** /**
* @param Server $server * @param Server $server
* @param int $workerId * @param int $workerId
* @throws Exception * @throws Exception
*/ */
public function onWorkerStop(Server $server, int $workerId) public function onWorkerStop(Server $server, int $workerId)
{ {
$this->runEvent(Constant::WORKER_STOP, null, [$server, $workerId]); $this->runEvent(Constant::WORKER_STOP, null, [$server, $workerId]);
Event::trigger(Event::SERVER_WORKER_STOP); Event::trigger(Event::SERVER_WORKER_STOP);
var_dump('worker stop .' . $workerId); fire(Event::SYSTEM_RESOURCE_CLEAN);
fire(Event::SYSTEM_RESOURCE_CLEAN); Timer::clearAll();
}
Timer::clearAll();
}
/** /**
* @param Server $server * @param Server $server
* @param int $workerId * @param int $workerId
* @throws Exception * @throws Exception
*/ */
public function onWorkerExit(Server $server, int $workerId) public function onWorkerExit(Server $server, int $workerId)
{ {
$this->runEvent(Constant::WORKER_EXIT, null, [$server, $workerId]); $this->runEvent(Constant::WORKER_EXIT, null, [$server, $workerId]);
putenv('state=exit'); putenv('state=exit');
Event::trigger(Event::SERVER_WORKER_EXIT, [$server, $workerId]); Event::trigger(Event::SERVER_WORKER_EXIT, [$server, $workerId]);
Snowflake::getApp('logger')->insert(); Snowflake::getApp('logger')->insert();
} }
/** /**
* @param Server $server * @param Server $server
* @param int $worker_id * @param int $worker_id
* @param int $worker_pid * @param int $worker_pid
* @param int $exit_code * @param int $exit_code
* @param int $signal * @param int $signal
* @throws Exception * @throws Exception
*/ */
public function onWorkerError(Server $server, int $worker_id, int $worker_pid, int $exit_code, int $signal) public function onWorkerError(Server $server, int $worker_id, int $worker_pid, int $exit_code, int $signal)
{ {
$this->runEvent(Constant::WORKER_ERROR, null, [$server, $worker_id, $worker_pid, $exit_code, $signal]); $this->runEvent(Constant::WORKER_ERROR, null, [$server, $worker_id, $worker_pid, $exit_code, $signal]);
Event::trigger(Event::SERVER_WORKER_ERROR); Event::trigger(Event::SERVER_WORKER_ERROR);
$message = sprintf('Worker#%d::%d error stop. signal %d, exit_code %d, msg %s', $message = sprintf('Worker#%d::%d error stop. signal %d, exit_code %d, msg %s',
$worker_id, $worker_pid, $signal, $exit_code, swoole_strerror(swoole_last_error(), 9) $worker_id, $worker_pid, $signal, $exit_code, swoole_strerror(swoole_last_error(), 9)
); );
write($message, 'worker-exit'); write($message, 'worker-exit');
$this->system_mail($message); $this->system_mail($message);
} }
/** /**
* @param $messageContent * @param $messageContent
* @throws Exception * @throws Exception
*/ */
protected function system_mail($messageContent) protected function system_mail($messageContent)
{ {
try { try {
$email = Config::get('email'); $email = Config::get('email');
if (!empty($email) && ($email['enable'] ?? false) == true) { if (!empty($email) && ($email['enable'] ?? false) == true) {
Help::sendEmail($email, 'Service Error', $messageContent); Help::sendEmail($email, 'Service Error', $messageContent);
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
error($e, 'email'); error($e, 'email');
} }
} }
} }