diff --git a/Annotation/Inject.php b/Annotation/Inject.php index 4dc1b5ef..af411d9c 100644 --- a/Annotation/Inject.php +++ b/Annotation/Inject.php @@ -17,14 +17,14 @@ use Snowflake\Snowflake; { - /** - * Inject constructor. - * @param string $className - * @param array $args - */ - public function __construct(private string $className, private array $args = []) - { - } + /** + * Inject constructor. + * @param string $className + * @param array $args + */ + public function __construct(private string $className, private array $args = []) + { + } /** @@ -34,44 +34,44 @@ use Snowflake\Snowflake; * @throws ReflectionException * @throws Exception */ - public function execute(mixed $class, mixed $method = null): bool - { - $injectValue = $this->parseInjectValue(); - if (!($method instanceof ReflectionProperty)) { - $method = new ReflectionProperty($class, $method); - } + public function execute(mixed $class, mixed $method = null): bool + { + $injectValue = $this->parseInjectValue(); + if (!($method instanceof ReflectionProperty)) { + $method = Snowflake::getDi()->getClassProperty($class, $method); + if (!$method) { + return false; + } + } - /** @var ReflectionProperty $class */ - if ($method->isPrivate() || $method->isProtected()) { - $method = 'set' . ucfirst($class->getName()); - if (!method_exists($class, $method)) { - return false; - } - $class->$method($injectValue); - } else { - $class->{$method->getName()} = $injectValue; - } - return true; - } + /** @var ReflectionProperty $class */ + if ($method->isPrivate() || $method->isProtected()) { + $method = 'set' . ucfirst($class->getName()); + if (!method_exists($class, $method)) { + return false; + } + $class->$method($injectValue); + } else { + $class->{$method->getName()} = $injectValue; + } + return true; + } - /** - * @return mixed - * @throws Exception - */ - private function parseInjectValue(): mixed - { - if (class_exists($this->className)) { - $injectValue = Snowflake::createObject($this->className, $this->args); - } else if (Snowflake::app()->has($this->className)) { - $injectValue = Snowflake::app()->get($this->className); - } else { - $injectValue = $this->className; - } -// if (!empty($this->args) && is_object($injectValue)) { -// Snowflake::configure($injectValue, $this->args); -// } - return $injectValue; - } + /** + * @return mixed + * @throws Exception + */ + private function parseInjectValue(): mixed + { + if (class_exists($this->className)) { + $injectValue = Snowflake::getDi()->get($this->className, $this->args); + } else if (Snowflake::app()->has($this->className)) { + $injectValue = Snowflake::app()->get($this->className); + } else { + $injectValue = $this->className; + } + return $injectValue; + } } diff --git a/Annotation/Loader.php b/Annotation/Loader.php index 3792fdcd..1855a2b9 100644 --- a/Annotation/Loader.php +++ b/Annotation/Loader.php @@ -27,10 +27,16 @@ class Loader extends BaseObject { - private array $_classes = []; + private static array $_classes = []; - private array $_directory = []; + private static array $_directory = []; + + + private static array $_property = []; + + + private static array $_methods = []; private array $_annotationMaps = []; @@ -41,7 +47,7 @@ class Loader extends BaseObject */ public function getDirectory(): array { - return $this->_directory; + return static::$_directory; } /** @@ -60,7 +66,7 @@ class Loader extends BaseObject */ public function getClasses(): array { - return $this->_classes; + return static::$_classes; } @@ -71,14 +77,13 @@ class Loader extends BaseObject */ public function getProperty(string $class, string $property = ''): mixed { - if (!isset($this->_classes[$class])) { + if (!isset(static::$_property[$class])) { return null; } - $properties = $this->_classes[$class]['property']; - if (!empty($property) && isset($properties[$property])) { - return $properties[$property]; + if (!empty($property)) { + return static::$_property[$class][$property] ?? []; } - return $properties; + return static::$_property[$class]; } @@ -109,10 +114,10 @@ class Loader extends BaseObject */ public function getMethod(string $class, string $method = ''): array { - if (!isset($this->_classes[$class])) { + if (!isset(static::$_classes[$class])) { return []; } - $properties = $this->_classes[$class]['methods']; + $properties = static::$_classes[$class]['methods']; if (!empty($method) && isset($properties[$method])) { return $properties[$method]; } @@ -126,7 +131,7 @@ class Loader extends BaseObject */ public function getTarget(string $class): array { - return $this->_classes[$class] ?? []; + return static::$_classes[$class] ?? []; } @@ -144,8 +149,8 @@ class Loader extends BaseObject if ($path->isDir()) { $iterator = new DirectoryIterator($path->getRealPath()); $directory = rtrim($path->getRealPath(), '/'); - if (!isset($this->_directory[$directory])) { - $this->_directory[$directory] = []; + if (!isset(static::$_directory[$directory])) { + static::$_directory[$directory] = []; } $this->_scanDir($iterator, $namespace); } else { @@ -181,7 +186,7 @@ class Loader extends BaseObject $_array = $this->_methods($replace, $_array); $_array = $this->_properties($replace, $_array); - $this->_classes[$replace->getName()] = $_array; + static::$_classes[$replace->getName()] = $_array; } catch (Throwable $throwable) { $this->addError($throwable, 'throwable'); } @@ -237,6 +242,9 @@ class Loader extends BaseObject } $_method[] = $attribute->newInstance(); } + + static::$_methods[$replace->getName()][$method->getName()] = $_method; + $_array['methods'][$method->getName()] = $_method; } return $_array; @@ -260,6 +268,9 @@ class Loader extends BaseObject } $_property[] = $attribute->newInstance(); } + + static::$_property[$replace->getName()][$method->getName()] = $_property; + $_array['property'][$method->getName()] = $_property; } return $_array; @@ -275,7 +286,7 @@ class Loader extends BaseObject { try { $path = '/' . trim($path, '/'); - foreach ($this->_directory as $key => $_path) { + foreach (static::$_directory as $key => $_path) { $key = '/' . trim($key, '/'); if (!str_starts_with($key, $path) || in_array($key, $outPath)) { continue; @@ -317,7 +328,7 @@ class Loader extends BaseObject $array = '/' . trim(implode('/', $array), '/'); - $this->_directory[$array][] = $className; + static::$_directory[$array][] = $className; } @@ -333,7 +344,7 @@ class Loader extends BaseObject $annotation = Snowflake::getAnnotation(); foreach ($classes as $className) { - $annotations = $this->_classes[$className] ?? null; + $annotations = static::$_classes[$className] ?? null; if ($annotations === null) { continue; } diff --git a/Database/Base/BaseActiveRecord.php b/Database/Base/BaseActiveRecord.php index 2ab47cda..8b746ad7 100644 --- a/Database/Base/BaseActiveRecord.php +++ b/Database/Base/BaseActiveRecord.php @@ -11,6 +11,7 @@ namespace Database\Base; use Annotation\Event; +use Annotation\Inject; use ArrayAccess; use Database\ActiveQuery; use Database\ActiveRecord; @@ -71,9 +72,15 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess protected ?string $primary = NULL; + /** + * @var array + */ private array $_annotations = []; + /** + * @var Application|null + */ protected ?Application $container; @@ -82,11 +89,23 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess */ protected bool $isNewExample = TRUE; + + /** + * @var array + */ protected array $actions = []; + + /** + * @var Relation|null + */ + #[Inject(Relation::class)] protected ?Relation $_relation; + /** + * @var array + */ private array $_with = []; /** @@ -123,19 +142,11 @@ abstract class BaseActiveRecord extends Component implements IOrm, ArrayAccess /** - * @throws NotFindClassException - * @throws ReflectionException * @throws Exception */ public function init() { $this->container = Snowflake::app(); - if (!Context::hasContext(Relation::class)) { - $relation = Snowflake::createObject(Relation::class); - $this->_relation = Context::setContext(Relation::class, $relation); - } else { - $this->_relation = Context::getContext(Relation::class); - } } diff --git a/Database/DatabasesProviders.php b/Database/DatabasesProviders.php index b50b8e82..ddd4e4fa 100644 --- a/Database/DatabasesProviders.php +++ b/Database/DatabasesProviders.php @@ -7,6 +7,7 @@ namespace Database; use Annotation\IAnnotation; use Exception; use ReflectionException; +use Server\Constant; use Snowflake\Abstracts\Providers; use Snowflake\Application; use Snowflake\Event; @@ -38,7 +39,6 @@ class DatabasesProviders extends Providers $this->_pooLength = Config::get('databases.pool', ['min' => 0, 'max' => 1]); Event::on(Event::SERVER_TASK_START, [$this, 'createPool']); - Event::on(Event::SERVER_WORKER_START, [$this, 'createPool']); } @@ -80,7 +80,6 @@ class DatabasesProviders extends Providers /** * @param $database * @return array - * @throws \Snowflake\Exception\ConfigException */ private function _settings($database): array { diff --git a/Server/ServerManager.php b/Server/ServerManager.php index 3c996859..a873f1d0 100644 --- a/Server/ServerManager.php +++ b/Server/ServerManager.php @@ -3,8 +3,10 @@ namespace Server; use Closure; +use Exception; use ReflectionException; use Server\SInterface\CustomProcess; +use Server\SInterface\TaskExecute; use Server\Task\ServerTask; use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; @@ -173,7 +175,7 @@ class ServerManager extends Abstracts\Server * @param array $config * @throws NotFindClassException * @throws ReflectionException - * @throws \Exception + * @throws Exception */ private function startListenerHandler(ServerManager $context, array $config) { @@ -355,6 +357,29 @@ class ServerManager extends Abstracts\Server } + /** + * @param TaskExecute|string $handler + * @param array $params + * @param int $workerId + * @throws Exception + */ + public function task(TaskExecute|string $handler, array $params = [], int $workerId = 0) + { + if ($workerId === null || $workerId <= $this->server->setting['worker_num']) { + $workerId = random_int($this->server->setting['worker_num'] + 1, + $this->server->setting['worker_num'] + 1 + $this->server->setting['task_worker_num']); + } + if (is_string($handler)) { + $implements = Snowflake::getDi()->getReflect($handler); + if (!in_array(TaskExecute::class, $implements->getInterfaceNames())) { + throw new Exception('Task must instance ' . TaskExecute::class); + } + $handler = $implements->newInstanceArgs($params); + } + $this->server->task(serialize($handler), $workerId); + } + + /** * @param array $events * @throws NotFindClassException diff --git a/Server/Worker/ServerWorker.php b/Server/Worker/ServerWorker.php index aa274185..62bf9a01 100644 --- a/Server/Worker/ServerWorker.php +++ b/Server/Worker/ServerWorker.php @@ -3,12 +3,15 @@ namespace Server\Worker; use Exception; +use Psr\Log\Test\TestLogger; use Server\Constant; +use Server\ServerManager; use Snowflake\Abstracts\Config; use Snowflake\Event; use Snowflake\Runtime; use Snowflake\Snowflake; use Swoole\Server; +use Swoole\Timer; /** @@ -30,15 +33,16 @@ class ServerWorker extends \Server\Abstracts\Server $annotation = Snowflake::app()->getAnnotation(); $annotation->read(APP_PATH . 'app'); - $loader = Snowflake::app()->getRouter(); - $loader->_loader(); - $this->runEvent(Constant::WORKER_START, null, [$server, $workerId]); if ($workerId >= $server->setting['worker_num'] + 1) { + $loader = Snowflake::app()->getRouter(); + $loader->_loader(); + $annotation->runtime(CONTROLLER_PATH); + $annotation->runtime(MODEL_PATH); + } else { + $annotation->runtime(APP_PATH, [CONTROLLER_PATH]); } - Event::trigger(Event::SERVER_ON_WORKER_START, [$server, $workerId]); - name($server->worker_pid, 'Worker.' . $workerId); } @@ -62,20 +66,34 @@ class ServerWorker extends \Server\Abstracts\Server /** * @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); + + fire(Event::SYSTEM_RESOURCE_CLEAN); + + 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]); + + putenv('state=exit'); + + Event::trigger(Event::SERVER_WORKER_EXIT, [$server, $worker_id]); + + Snowflake::getApp('logger')->insert(); } @@ -85,10 +103,51 @@ class ServerWorker extends \Server\Abstracts\Server * @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); + + $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); + } + + + /** + * @param $messageContent + * @throws Exception + */ + protected function system_mail($messageContent) + { + try { + $email = Config::get('email'); + if (empty($email) || !$email['enable']) { + return; + } + $transport = (new \Swift_SmtpTransport($email['host'], $email['465'])) + ->setUsername($email['username']) + ->setPassword($email['password']); + $mailer = new \Swift_Mailer($transport); + + // Create a message + $message = (new \Swift_Message('Wonderful Subject')) + ->setFrom([$email['send']['address'] => $email['send']['nickname']]) + ->setBody('Here is the message itself'); + + foreach ($email['receive'] as $item) { + $message->setTo([$item['address'], $item['address'] => $item['nickname']]); + } + $mailer->send($messageContent); + } catch (\Throwable $e) { + error($e, 'email'); + } } } diff --git a/System/Di/Container.php b/System/Di/Container.php index b26c4a93..37112179 100644 --- a/System/Di/Container.php +++ b/System/Di/Container.php @@ -47,6 +47,8 @@ class Container extends BaseObject */ private array $_reflection = []; + private array $_reflectionProperty = []; + private array $_property = []; @@ -68,7 +70,7 @@ class Container extends BaseObject * @throws ReflectionException * @throws Exception */ - public function get($class, $constrict = [], $config = []): mixed + public function get($class, array $constrict = [], array $config = []): mixed { if (isset($this->_singletons[$class])) { return $this->_singletons[$class]; @@ -198,10 +200,10 @@ class Container extends BaseObject */ public function getClassProperty(string $class, string $property = null): ReflectionProperty|null|array { - if (!isset($this->_property[$class])) { + if (!isset($this->_reflectionProperty[$class])) { return null; } - $properties = $this->_property[$class]; + $properties = $this->_reflectionProperty[$class]; if (!empty($property)) { return $properties[$property] ?? null; } @@ -246,24 +248,25 @@ class Container extends BaseObject /** * @param ReflectionClass $reflectionClass - * @return $this + * @return void */ - private function scanProperty(ReflectionClass $reflectionClass): static + private function scanProperty(ReflectionClass $reflectionClass): void { - $lists = $reflectionClass->getProperties(ReflectionProperty::IS_PUBLIC | + $properties = $reflectionClass->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED ); $className = $reflectionClass->getName(); - foreach ($lists as $list) { - $targets = $list->getAttributes(Inject::class); + foreach ($properties as $property) { + $targets = $property->getAttributes(Inject::class); if (count($targets) < 1) { continue; } - $this->_property[$className][$list->getName()] = $targets[0]->newInstance(); + $this->_reflectionProperty[$className][$property->getName()] = $property; + + $this->_property[$className][$property->getName()] = $targets[0]->newInstance(); } - return $this; } diff --git a/System/Event.php b/System/Event.php index c69bef5c..58f4ae90 100644 --- a/System/Event.php +++ b/System/Event.php @@ -87,7 +87,7 @@ class Event extends BaseObject * @param bool $isAppend * @throws Exception */ - public static function on($name, $callback, $parameter = [], $isAppend = false) + public static function on($name, $callback, array $parameter = [], bool $isAppend = false) { if (!isset(static::$_events[$name])) { static::$_events[$name] = []; @@ -204,7 +204,7 @@ class Event extends BaseObject * @return bool * @throws Exception */ - public function dispatch($name, $params = [], $scope = null): bool + public function dispatch($name, array $params = [], $scope = null): bool { return static::trigger($name, $params, $scope); } diff --git a/function.php b/function.php index 05802992..c28d2c31 100644 --- a/function.php +++ b/function.php @@ -553,37 +553,18 @@ if (!function_exists('storage')) { } -if (!function_exists('listen')) { - - - /** - * @param $name - * @param $callback - * @param $params - * @param $isAppend - * @throws Exception - * @throws Exception - */ - function listen($name, $callback, $params = [], $isAppend = true) - { - Event::on($name, $callback, $params, $isAppend); - } - -} - - if (!function_exists('event')) { /** * @param $name * @param $callback - * @param $params - * @param $isAppend + * @param array $params + * @param bool $isAppend * @throws Exception * @throws Exception */ - function event($name, $callback, $params = [], $isAppend = true) + function event($name, $callback, array $params = [], bool $isAppend = true) { Event::on($name, $callback, $params, $isAppend); }