diff --git a/Database/ActiveRecord.php b/Database/ActiveRecord.php index 04d6c8a5..1a7c41a7 100644 --- a/Database/ActiveRecord.php +++ b/Database/ActiveRecord.php @@ -126,7 +126,7 @@ class ActiveRecord extends BaseActiveRecord if (empty($attributes)) { return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql'); } - $select = self::getModelClass(); + $select = duplicate(static::class); $select->attributes = $attributes; if (!$select->save()) { return $logger->addError($select->getLastError(), 'mysql'); @@ -150,7 +150,7 @@ class ActiveRecord extends BaseActiveRecord /** @var static $select */ $select = static::find()->where($condition)->first(); if (empty($select)) { - $select = self::getModelClass(); + $select = duplicate(static::class); } $select->attributes = $attributes; 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 $columns @@ -306,10 +292,6 @@ class ActiveRecord extends BaseActiveRecord $data[$key] = $this->{$item}($data[$key] ?? null); } $data = array_merge($data, $this->runRelate()); - - $class = Snowflake::app()->getChannel(); - $class->push($this, static::class); - return $data; } diff --git a/Database/Base/AbstractCollection.php b/Database/Base/AbstractCollection.php index 4d38c8b0..4d2a1219 100644 --- a/Database/Base/AbstractCollection.php +++ b/Database/Base/AbstractCollection.php @@ -26,142 +26,136 @@ use Traversable; abstract class AbstractCollection extends Component implements \IteratorAggregate, \ArrayAccess { - /** - * @var ActiveRecord[] - */ - protected array $_item = []; + /** + * @var ActiveRecord[] + */ + protected array $_item = []; - protected ActiveRecord|string|null $model; + protected ActiveRecord|string|null $model; - protected ActiveQuery $query; + protected ActiveQuery $query; - public function clean() - { - unset($this->query, $this->model, $this->_item); - } + public function clean() + { + unset($this->query, $this->model, $this->_item); + } - /** - * Collection constructor. - * - * @param $query - * @param array $array - * @param string|ActiveRecord|null $model - * @throws Exception - */ - public function __construct($query, array $array = [], string|ActiveRecord $model = null) - { - $this->_item = $array; - $this->query = $query; - $this->model = $model; + /** + * Collection constructor. + * + * @param $query + * @param array $array + * @param string|ActiveRecord|null $model + * @throws Exception + */ + public function __construct($query, array $array = [], string|ActiveRecord $model = null) + { + $this->_item = $array; + $this->query = $query; + $this->model = duplicate($model); - parent::__construct([]); - } + parent::__construct([]); + } - /** - * @return int - */ - #[Pure] public function getLength(): int - { - return count($this->_item); - } + /** + * @return int + */ + #[Pure] public function getLength(): int + { + return count($this->_item); + } - /** - * @param $item - */ - public function setItems($item) - { - $this->_item = $item; - } + /** + * @param $item + */ + public function setItems($item) + { + $this->_item = $item; + } - /** - * @param $model - */ - public function setModel($model) - { - $this->model = $model; - } + /** + * @param $model + */ + public function setModel($model) + { + $this->model = $model; + } - /** - * @param $item - */ - public function addItem($item) - { - array_push($this->_item, $item); - } + /** + * @param $item + */ + public function addItem($item) + { + array_push($this->_item, $item); + } - /** - * @return Traversable|CollectionIterator|ArrayIterator - * @throws Exception - */ - public function getIterator(): Traversable|CollectionIterator|ArrayIterator - { - return new CollectionIterator($this->model, $this->query, $this->_item); - } + /** + * @return Traversable|CollectionIterator|ArrayIterator + * @throws Exception + */ + public function getIterator(): Traversable|CollectionIterator|ArrayIterator + { + return new CollectionIterator($this->model, $this->query, $this->_item); + } - /** - * @return mixed - * @throws Exception - */ - public function getModel(): ActiveRecord - { - if (!is_object($this->model)) { - $this->model = duplicate($this->model); - $this->model->setIsCreate(false); - } - return $this->model; - } + /** + * @return mixed + * @throws Exception + */ + public function getModel(): ActiveRecord + { + return $this->model; + } - /** - * @param mixed $offset - * @return bool - */ - public function offsetExists(mixed $offset): bool - { - return !empty($this->_item) && isset($this->_item[$offset]); - } + /** + * @param mixed $offset + * @return bool + */ + public function offsetExists(mixed $offset): bool + { + return !empty($this->_item) && isset($this->_item[$offset]); + } - /** - * @param mixed $offset - * @return ActiveRecord|null - * @throws Exception - */ - public function offsetGet(mixed $offset): ?ActiveRecord - { - if (!$this->offsetExists($offset)) { - return NULL; - } + /** + * @param mixed $offset + * @return ActiveRecord|null + * @throws Exception + */ + public function offsetGet(mixed $offset): ?ActiveRecord + { + if (!$this->offsetExists($offset)) { + 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]; - } - - return $this->model::populate($this->_item[$offset]); - } - - /** - * @param mixed $offset - * @param mixed $value - */ - 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 - */ - public function offsetUnset(mixed $offset) - { - if ($this->offsetExists($offset)) { - unset($this->_item[$offset]); - } - } + /** + * @param mixed $offset + */ + public function offsetUnset(mixed $offset) + { + if ($this->offsetExists($offset)) { + unset($this->_item[$offset]); + } + } } diff --git a/Database/Base/CollectionIterator.php b/Database/Base/CollectionIterator.php index 5424d722..3025502e 100644 --- a/Database/Base/CollectionIterator.php +++ b/Database/Base/CollectionIterator.php @@ -56,7 +56,7 @@ class CollectionIterator extends \ArrayIterator */ protected function newModel($current): ActiveRecord { - return $this->model::populate($current); + return $this->model->setAttributes($current); } diff --git a/HttpServer/Http/Request.php b/HttpServer/Http/Request.php index e0c80f3f..da8152b6 100644 --- a/HttpServer/Http/Request.php +++ b/HttpServer/Http/Request.php @@ -6,6 +6,7 @@ namespace HttpServer\Http; use Annotation\Route\Socket; use Exception; use HttpServer\Abstracts\HttpService; +use HttpServer\Http\Response as HResponse; use HttpServer\IInterface\AuthIdentity; use JetBrains\PhpStorm\Pure; use Snowflake\Abstracts\Config; @@ -451,7 +452,7 @@ class Request extends HttpService * @param \Swoole\Http\Request $request * @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 */ $sRequest = Context::setContext('request', new Request()); @@ -467,6 +468,8 @@ class Request extends HttpService $sRequest->uri = $sRequest->headers->get('request_uri'); $sRequest->parseUri(); + + HResponse::create($response); return $sRequest; } diff --git a/Server/ApplicationStore.php b/Server/ApplicationStore.php new file mode 100644 index 00000000..e21d5738 --- /dev/null +++ b/Server/ApplicationStore.php @@ -0,0 +1,73 @@ +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'); + } + +} diff --git a/Server/HTTPServerListener.php b/Server/HTTPServerListener.php index 3fd27499..d5391156 100644 --- a/Server/HTTPServerListener.php +++ b/Server/HTTPServerListener.php @@ -26,121 +26,124 @@ use Throwable; 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. - * @throws Exception - */ - public function __construct() - { - $this->router = Snowflake::getApp('router'); - parent::__construct(); - } + /** + * HTTPServerListener constructor. + * @throws Exception + */ + public function __construct() + { + $this->router = Snowflake::getApp('router'); + $this->store = ApplicationStore::getStore(); + parent::__construct(); + } - /** - * UDPServerListener constructor. - * @param Server|\Swoole\WebSocket\Server|\Swoole\Http\Server $server - * @param string $host - * @param int $port - * @param int $mode - * @param array|null $settings - * @return Server\Port - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - public static function instance(mixed $server, string $host, int $port, int $mode, ?array $settings = []): Server\Port - { - if (!in_array($mode, [SWOOLE_TCP, SWOOLE_TCP6])) { - trigger_error('Port mode ' . $host . '::' . $port . ' must is udp listener type.'); - } + /** + * UDPServerListener constructor. + * @param Server|\Swoole\WebSocket\Server|\Swoole\Http\Server $server + * @param string $host + * @param int $port + * @param int $mode + * @param array|null $settings + * @return Server\Port + * @throws NotFindClassException + * @throws ReflectionException + * @throws Exception + */ + public static function instance(mixed $server, string $host, int $port, int $mode, ?array $settings = []): Server\Port + { + if (!in_array($mode, [SWOOLE_TCP, SWOOLE_TCP6])) { + trigger_error('Port mode ' . $host . '::' . $port . ' must is udp listener type.'); + } - /** @var static $reflect */ - $reflect = Snowflake::getDi()->getReflect(static::class)?->newInstance(); - static::$_http = $server->addlistener($host, $port, $mode); - if (!(static::$_http instanceof Port)) { - trigger_error('Port is ' . $host . '::' . $port . ' must is tcp listener type.'); - } + /** @var static $reflect */ + $reflect = Snowflake::getDi()->getReflect(static::class)?->newInstance(); + static::$_http = $server->addlistener($host, $port, $mode); + if (!(static::$_http instanceof Port)) { + trigger_error('Port is ' . $host . '::' . $port . ' must is tcp listener type.'); + } - static::$_http->set($settings['settings'] ?? []); - static::$_http->on('request', [$reflect, 'onRequest']); - static::$_http->on('connect', [$reflect, 'onConnect']); - static::$_http->on('close', [$reflect, 'onClose']); - if (swoole_version() >= '4.7.0') { - static::$_http->on('disconnect', [$reflect, 'onDisconnect']); - $reflect->setEvents(Constant::DISCONNECT, $settings['events'][Constant::DISCONNECT] ?? null); - } - $reflect->setEvents(Constant::CLOSE, $settings['events'][Constant::CLOSE] ?? null); - $reflect->setEvents(Constant::CONNECT, $settings['events'][Constant::CONNECT] ?? null); - return static::$_http; - } + static::$_http->set($settings['settings'] ?? []); + static::$_http->on('request', [$reflect, 'onRequest']); + static::$_http->on('connect', [$reflect, 'onConnect']); + static::$_http->on('close', [$reflect, 'onClose']); + if (swoole_version() >= '4.7.0') { + static::$_http->on('disconnect', [$reflect, 'onDisconnect']); + $reflect->setEvents(Constant::DISCONNECT, $settings['events'][Constant::DISCONNECT] ?? null); + } + $reflect->setEvents(Constant::CLOSE, $settings['events'][Constant::CLOSE] ?? null); + $reflect->setEvents(Constant::CONNECT, $settings['events'][Constant::CONNECT] ?? null); + return static::$_http; + } - /** - * @param Server $server - * @param int $fd - * @throws Exception - */ - public function onConnect(Server $server, int $fd) - { - $this->runEvent(Constant::CONNECT, null, [$server, $fd]); + /** + * @param Server $server + * @param int $fd + * @throws Exception + */ + public function onConnect(Server $server, int $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 Response $response - * @throws Exception - */ - public function onRequest(Request $request, Response $response) - { - try { - [$request, $_] = [HRequest::create($request), HResponse::create($response)]; - if ($request->is('favicon.ico')) { - throw new Exception('Not found.', 404); - } - $this->router->dispatch(); - } catch (ExitException | Error | Throwable $exception) { - $response->setHeader('Content-Type', 'text/html; charset=utf-8'); - $response->status($exception->getCode() == 0 ? 500 : $exception->getCode()); - $response->end($exception->getMessage()); - } finally { - $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); - } - } + /** + * @param Request $request + * @param Response $response + * @throws Exception + */ + public function onRequest(Request $request, Response $response) + { + try { + $request = HRequest::create($request, $response); + if ($request->is('favicon.ico')) { + throw new Exception('Not found.', 404); + } + $this->router->dispatch(); + } catch (ExitException | Error | Throwable $exception) { + $response->setHeader('Content-Type', 'text/html; charset=utf-8'); + $response->status($exception->getCode() == 0 ? 500 : $exception->getCode()); + $response->end($exception->getMessage()); + } finally { + $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); + } + } - /** - * @param Server $server - * @param int $fd - * @throws Exception - */ - public function onDisconnect(Server $server, int $fd) - { - $this->runEvent(Constant::DISCONNECT, null, [$server, $fd]); + /** + * @param Server $server + * @param int $fd + * @throws Exception + */ + public function onDisconnect(Server $server, int $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 int $fd - * @throws Exception - */ - public function onClose(Server $server, int $fd) - { - $this->runEvent(Constant::CLOSE, null, [$server, $fd]); + /** + * @param Server $server + * @param int $fd + * @throws Exception + */ + public function onClose(Server $server, int $fd) + { + $this->runEvent(Constant::CLOSE, null, [$server, $fd]); - $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); - } + $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); + } } diff --git a/Server/Worker/ServerWorker.php b/Server/Worker/ServerWorker.php index 33e5cb8f..9904bf55 100644 --- a/Server/Worker/ServerWorker.php +++ b/Server/Worker/ServerWorker.php @@ -24,142 +24,139 @@ class ServerWorker extends \Server\Abstracts\Server { - /** - * @param Server $server - * @param int $workerId - * @throws Exception - */ - public function onWorkerStart(Server $server, int $workerId) - { - $this->_setConfigCache($workerId); - $annotation = Snowflake::app()->getAnnotation(); - $annotation->read(APP_PATH . 'app'); + /** + * @param Server $server + * @param int $workerId + * @throws Exception + */ + public function onWorkerStart(Server $server, int $workerId) + { + $this->_setConfigCache($workerId); + $annotation = Snowflake::app()->getAnnotation(); + $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 Annotation $annotation - * @param int $workerId - * @throws ConfigException - * @throws Exception - */ - private function workerInitExecutor(Server $server, Annotation $annotation, int $workerId) - { - if ($workerId < $server->setting['worker_num']) { - $loader = Snowflake::app()->getRouter(); - $loader->_loader(); + /** + * @param Server $server + * @param Annotation $annotation + * @param int $workerId + * @throws ConfigException + * @throws Exception + */ + private function workerInitExecutor(Server $server, Annotation $annotation, int $workerId) + { + if ($workerId < $server->setting['worker_num']) { + $loader = Snowflake::app()->getRouter(); + $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; - $this->setProcessName(sprintf('Worker[%d].%d', $server->worker_pid, $workerId)); + 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)); - $annotation->runtime(CONTROLLER_PATH); - $annotation->runtime(MODEL_PATH); - } else { - echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m Tasker[%d].%d start.", $server->worker_pid, $workerId) . PHP_EOL; + $annotation->runtime(CONTROLLER_PATH); + $annotation->runtime(MODEL_PATH); + } else { + 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); - /** - * @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)); - if (empty($serialize)) { - return; - } - Config::sets(unserialize($serialize)); - } + $serialize = file_get_contents(storage(Runtime::CONFIG_NAME)); + if (empty($serialize)) { + return; + } + Config::sets(unserialize($serialize)); + } - /** - * @param Server $server - * @param int $workerId - * @throws Exception - */ - public function onWorkerStop(Server $server, int $workerId) - { - $this->runEvent(Constant::WORKER_STOP, null, [$server, $workerId]); + /** + * @param Server $server + * @param int $workerId + * @throws Exception + */ + public function onWorkerStop(Server $server, int $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 int $workerId - * @throws Exception - */ - public function onWorkerExit(Server $server, int $workerId) - { - $this->runEvent(Constant::WORKER_EXIT, null, [$server, $workerId]); + /** + * @param Server $server + * @param int $workerId + * @throws Exception + */ + public function onWorkerExit(Server $server, int $workerId) + { + $this->runEvent(Constant::WORKER_EXIT, null, [$server, $workerId]); - putenv('state=exit'); + putenv('state=exit'); Event::trigger(Event::SERVER_WORKER_EXIT, [$server, $workerId]); Snowflake::getApp('logger')->insert(); - } + } - /** - * @param Server $server - * @param int $worker_id - * @param int $worker_pid - * @param int $exit_code - * @param int $signal - * @throws Exception - */ - 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]); + /** + * @param Server $server + * @param int $worker_id + * @param int $worker_pid + * @param int $exit_code + * @param int $signal + * @throws Exception + */ + 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]); - 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', - $worker_id, $worker_pid, $signal, $exit_code, swoole_strerror(swoole_last_error(), 9) - ); - write($message, 'worker-exit'); + $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) + ); + write($message, 'worker-exit'); - $this->system_mail($message); - } + $this->system_mail($message); + } - /** - * @param $messageContent - * @throws Exception - */ - protected function system_mail($messageContent) - { - try { - $email = Config::get('email'); - if (!empty($email) && ($email['enable'] ?? false) == true) { - Help::sendEmail($email, 'Service Error', $messageContent); - } - } catch (\Throwable $e) { - error($e, 'email'); - } - } + /** + * @param $messageContent + * @throws Exception + */ + protected function system_mail($messageContent) + { + try { + $email = Config::get('email'); + if (!empty($email) && ($email['enable'] ?? false) == true) { + Help::sendEmail($email, 'Service Error', $messageContent); + } + } catch (\Throwable $e) { + error($e, 'email'); + } + } }