Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48298ef1f7 | |||
| d4a1e9c8d7 | |||
| f9ac567bfe | |||
| be7c5da071 | |||
| fec0715c40 |
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PHPSTORM_META {
|
||||||
|
registerArgumentsSet(
|
||||||
|
'router_actions',
|
||||||
|
\App\Controller\SiteController::class . '@globSetting'
|
||||||
|
);
|
||||||
|
|
||||||
|
expectedArguments(\Kiri\Router\Router::get(), 1, argumentsSet('router_actions'));
|
||||||
|
expectedArguments(\Kiri\Router\Router::post(), 1, argumentsSet('router_actions'));
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
namespace Kiri\Router\Annotate;
|
namespace Kiri\Router\Annotate;
|
||||||
|
|
||||||
use Kiri\Di\Interface\InjectMethodInterface;
|
use Kiri\Di\Interface\InjectMethodInterface;
|
||||||
|
use Kiri\Router\Defer\DeferRegistry;
|
||||||
|
|
||||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||||
class Defer implements InjectMethodInterface
|
class Defer implements InjectMethodInterface
|
||||||
@@ -18,11 +19,6 @@ class Defer implements InjectMethodInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $class
|
|
||||||
* @param string $method
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function dispatch(string $class, string $method): void
|
public function dispatch(string $class, string $method): void
|
||||||
{
|
{
|
||||||
DeferRegistry::add($class, $method, $this);
|
DeferRegistry::add($class, $method, $this);
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kiri\Router\Defer;
|
||||||
|
|
||||||
|
use Kiri;
|
||||||
|
use Kiri\Router\Annotate\Defer;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use ReflectionClass;
|
||||||
|
use Swoole\Coroutine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defer 回调执行器 — 统一处理协程安全的上下文注入与异步执行
|
||||||
|
*/
|
||||||
|
class DeferExecutor
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行一批 Defer 回调
|
||||||
|
*
|
||||||
|
* @param Defer[] $defers
|
||||||
|
*/
|
||||||
|
public static function run(array $defers): void
|
||||||
|
{
|
||||||
|
if (empty($defers)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = self::captureRequest();
|
||||||
|
$response = self::captureResponse();
|
||||||
|
|
||||||
|
if (Coroutine::getCid() <= 0) {
|
||||||
|
self::executeSync($defers, $request, $response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Coroutine::create(function () use ($defers, $request, $response) {
|
||||||
|
self::executeSync($defers, $request, $response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为实例注入 request/response 上下文
|
||||||
|
*/
|
||||||
|
public static function inject(object $instance): object
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request = self::captureRequest();
|
||||||
|
if ($request !== null) {
|
||||||
|
self::setProperty($instance, 'request', $request);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = self::captureResponse();
|
||||||
|
if ($response !== null) {
|
||||||
|
self::setProperty($instance, 'response', $response);
|
||||||
|
}
|
||||||
|
} catch (\Throwable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function executeSync(
|
||||||
|
array $defers,
|
||||||
|
?ServerRequestInterface $request,
|
||||||
|
?ResponseInterface $response
|
||||||
|
): void {
|
||||||
|
foreach ($defers as $defer) {
|
||||||
|
try {
|
||||||
|
self::invokeDefer($defer, $request, $response);
|
||||||
|
} catch (\Throwable $throwable) {
|
||||||
|
\Kiri::getLogger()->error('Defer callback failed: ' . $throwable->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function invokeDefer(
|
||||||
|
Defer $defer,
|
||||||
|
?ServerRequestInterface $request,
|
||||||
|
?ResponseInterface $response
|
||||||
|
): void {
|
||||||
|
$callback = $defer->callback;
|
||||||
|
$params = $defer->params;
|
||||||
|
|
||||||
|
if (is_array($callback)) {
|
||||||
|
[$class, $method] = $callback;
|
||||||
|
$instance = self::resolveInstance($class, $request, $response);
|
||||||
|
call_user_func([$instance, $method], ...$params);
|
||||||
|
} else {
|
||||||
|
$instance = self::resolveInstance($callback, $request, $response);
|
||||||
|
call_user_func([$instance, '__invoke'], ...$params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function resolveInstance(
|
||||||
|
string $class,
|
||||||
|
?ServerRequestInterface $request,
|
||||||
|
?ResponseInterface $response
|
||||||
|
): object {
|
||||||
|
$instance = Kiri::getDi()->get($class);
|
||||||
|
|
||||||
|
if ($instance instanceof DeferHandler) {
|
||||||
|
if ($request !== null) {
|
||||||
|
$instance->request = $request;
|
||||||
|
}
|
||||||
|
if ($response !== null) {
|
||||||
|
$instance->response = $response;
|
||||||
|
}
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request !== null) {
|
||||||
|
self::setProperty($instance, 'request', $request);
|
||||||
|
}
|
||||||
|
if ($response !== null) {
|
||||||
|
self::setProperty($instance, 'response', $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function setProperty(object $instance, string $name, mixed $value): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$reflect = new ReflectionClass($instance);
|
||||||
|
if (!$reflect->hasProperty($name)) return;
|
||||||
|
$prop = $reflect->getProperty($name);
|
||||||
|
if ($prop->isStatic()) return;
|
||||||
|
$prop->setAccessible(true);
|
||||||
|
$prop->setValue($instance, $value);
|
||||||
|
} catch (\Throwable) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function captureRequest(): ?ServerRequestInterface
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (function_exists('request')) return \request();
|
||||||
|
} catch (\Throwable) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function captureResponse(): ?ResponseInterface
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (function_exists('response')) return \response();
|
||||||
|
} catch (\Throwable) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kiri\Router\Defer;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defer 回调基类 — 提供 request/response 上下文属性
|
||||||
|
*
|
||||||
|
* 所有需要在 #[Defer] 回调中访问请求上下文的类应继承此类。
|
||||||
|
* DeferExecutor 会自动将父协程的 request/response 注入到这两个属性。
|
||||||
|
*/
|
||||||
|
abstract class DeferHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @var ServerRequestInterface 当前请求上下文 (DeferExecutor 自动注入) */
|
||||||
|
public ServerRequestInterface $request;
|
||||||
|
|
||||||
|
/** @var ResponseInterface 当前响应上下文 (DeferExecutor 自动注入) */
|
||||||
|
public ResponseInterface $response;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Kiri\Router\Annotate;
|
namespace Kiri\Router\Defer;
|
||||||
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
@@ -18,9 +18,6 @@ class DeferProxyGenerator
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $className
|
|
||||||
* @param array $construct
|
|
||||||
* @return object
|
|
||||||
* @throws \ReflectionException
|
* @throws \ReflectionException
|
||||||
*/
|
*/
|
||||||
public static function create(string $className, array $construct): object
|
public static function create(string $className, array $construct): object
|
||||||
@@ -59,8 +56,6 @@ class DeferProxyGenerator
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $className
|
|
||||||
* @return string
|
|
||||||
* @throws \ReflectionException
|
* @throws \ReflectionException
|
||||||
*/
|
*/
|
||||||
private static function generate(string $className): string
|
private static function generate(string $className): string
|
||||||
@@ -70,32 +65,20 @@ class DeferProxyGenerator
|
|||||||
$stmts = [];
|
$stmts = [];
|
||||||
|
|
||||||
foreach ($methods as $methodName => $defers) {
|
foreach ($methods as $methodName => $defers) {
|
||||||
if (!$reflect->hasMethod($methodName)) {
|
if (!$reflect->hasMethod($methodName)) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$method = $reflect->getMethod($methodName);
|
$method = $reflect->getMethod($methodName);
|
||||||
if ($method->isPrivate() || $method->isStatic() || $method->isFinal() || $method->isConstructor() || $method->isDestructor()) {
|
if ($method->isPrivate() || $method->isStatic() || $method->isFinal() || $method->isConstructor() || $method->isDestructor()) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmts[] = self::buildMethod($method);
|
$stmts[] = self::buildMethod($method);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($stmts)) {
|
if (empty($stmts)) return '';
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$classNode = new Stmt\Class_(
|
$classNode = new Stmt\Class_(
|
||||||
new Name($className . '__DeferProxy'),
|
new Name($className . '__DeferProxy'),
|
||||||
[
|
['extends' => new Name\FullyQualified($className), 'stmts' => $stmts]
|
||||||
'extends' => new Name\FullyQualified($className),
|
|
||||||
'stmts' => $stmts,
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$namespace = $reflect->getNamespaceName();
|
$namespace = $reflect->getNamespaceName();
|
||||||
|
|
||||||
$namespaceNode = new Stmt\Namespace_(
|
$namespaceNode = new Stmt\Namespace_(
|
||||||
$namespace !== '' ? new Name($namespace) : null,
|
$namespace !== '' ? new Name($namespace) : null,
|
||||||
[$classNode]
|
[$classNode]
|
||||||
@@ -106,10 +89,6 @@ class DeferProxyGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ReflectionMethod $method
|
|
||||||
* @return Stmt\ClassMethod
|
|
||||||
*/
|
|
||||||
private static function buildMethod(ReflectionMethod $method): Stmt\ClassMethod
|
private static function buildMethod(ReflectionMethod $method): Stmt\ClassMethod
|
||||||
{
|
{
|
||||||
$methodName = $method->getName();
|
$methodName = $method->getName();
|
||||||
@@ -130,16 +109,12 @@ class DeferProxyGenerator
|
|||||||
|
|
||||||
$var = new Expr\Variable($param->getName());
|
$var = new Expr\Variable($param->getName());
|
||||||
|
|
||||||
$params[] = new Node\Param(
|
$params[] = new Node\Param($var, $default, $type,
|
||||||
$var,
|
|
||||||
$default,
|
|
||||||
$type,
|
|
||||||
byRef: $param->isPassedByReference(),
|
byRef: $param->isPassedByReference(),
|
||||||
variadic: $param->isVariadic()
|
variadic: $param->isVariadic()
|
||||||
);
|
);
|
||||||
|
|
||||||
$args[] = new Node\Arg(
|
$args[] = new Node\Arg($var,
|
||||||
$var,
|
|
||||||
byRef: $param->isPassedByReference(),
|
byRef: $param->isPassedByReference(),
|
||||||
unpack: $param->isVariadic()
|
unpack: $param->isVariadic()
|
||||||
);
|
);
|
||||||
@@ -151,19 +126,12 @@ class DeferProxyGenerator
|
|||||||
$returnType = new Name($refReturnType->getName());
|
$returnType = new Name($refReturnType->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
$parentCall = new Expr\StaticCall(
|
|
||||||
new Name('parent'),
|
|
||||||
$methodName,
|
|
||||||
$args
|
|
||||||
);
|
|
||||||
|
|
||||||
$stmts = [
|
$stmts = [
|
||||||
new Stmt\Expression(new Expr\Assign(new Expr\Variable('result'), $parentCall)),
|
new Stmt\Expression(new Expr\Assign(new Expr\Variable('result'),
|
||||||
|
new Expr\StaticCall(new Name('parent'), $methodName, $args))),
|
||||||
new Stmt\Expression(
|
new Stmt\Expression(
|
||||||
new Expr\StaticCall(
|
new Expr\StaticCall(
|
||||||
new Name\FullyQualified(DeferRegistry::class),
|
new Name\FullyQualified(DeferRegistry::class), 'execute', [
|
||||||
'execute',
|
|
||||||
[
|
|
||||||
new Node\Arg(new Expr\ClassConstFetch(new Name\FullyQualified($method->getDeclaringClass()->getName()), 'class')),
|
new Node\Arg(new Expr\ClassConstFetch(new Name\FullyQualified($method->getDeclaringClass()->getName()), 'class')),
|
||||||
new Node\Arg(new Node\Scalar\String_($methodName)),
|
new Node\Arg(new Node\Scalar\String_($methodName)),
|
||||||
]
|
]
|
||||||
@@ -172,66 +140,49 @@ class DeferProxyGenerator
|
|||||||
new Stmt\Return_(new Expr\Variable('result')),
|
new Stmt\Return_(new Expr\Variable('result')),
|
||||||
];
|
];
|
||||||
|
|
||||||
return new Stmt\ClassMethod(
|
return new Stmt\ClassMethod($methodName, [
|
||||||
$methodName,
|
|
||||||
[
|
|
||||||
'flags' => $method->isPublic() ? Stmt\Class_::MODIFIER_PUBLIC : Stmt\Class_::MODIFIER_PROTECTED,
|
'flags' => $method->isPublic() ? Stmt\Class_::MODIFIER_PUBLIC : Stmt\Class_::MODIFIER_PROTECTED,
|
||||||
'params' => $params,
|
'params' => $params,
|
||||||
'returnType' => $returnType,
|
'returnType' => $returnType,
|
||||||
'stmts' => $stmts,
|
'stmts' => $stmts,
|
||||||
]
|
]);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \ReflectionParameter $param
|
|
||||||
* @return Node\Expr
|
|
||||||
*/
|
|
||||||
private static function buildDefaultValue(\ReflectionParameter $param): Node\Expr
|
private static function buildDefaultValue(\ReflectionParameter $param): Node\Expr
|
||||||
{
|
{
|
||||||
if (!$param->isDefaultValueAvailable()) {
|
if (!$param->isDefaultValueAvailable()) {
|
||||||
return new Expr\ConstFetch(new Name('null'));
|
return new Expr\ConstFetch(new Name('null'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $param->getDefaultValue();
|
$value = $param->getDefaultValue();
|
||||||
|
|
||||||
return match (true) {
|
return match (true) {
|
||||||
is_bool($value) => new Expr\ConstFetch(new Name($value ? 'true' : 'false')),
|
is_bool($value) => new Expr\ConstFetch(new Name($value ? 'true' : 'false')),
|
||||||
is_int($value) => new Node\Scalar\LNumber($value),
|
is_int($value) => new Node\Scalar\LNumber($value),
|
||||||
is_float($value) => new Node\Scalar\DNumber($value),
|
is_float($value) => new Node\Scalar\DNumber($value),
|
||||||
is_string($value)=> new Node\Scalar\String_($value),
|
is_string($value) => new Node\Scalar\String_($value),
|
||||||
is_array($value) => new Expr\Array_(
|
is_array($value) => new Expr\Array_(array_map(
|
||||||
array_map(fn($k, $v) => new Expr\ArrayItem(
|
fn($k, $v) => new Expr\ArrayItem(
|
||||||
self::buildDefaultValueFromScalar($v),
|
self::buildDefaultValueFromScalar($v),
|
||||||
is_string($k) ? new Node\Scalar\String_($k) : null
|
is_string($k) ? new Node\Scalar\String_($k) : null
|
||||||
), array_keys($value), $value)
|
), array_keys($value), $value
|
||||||
),
|
)),
|
||||||
default => new Expr\ConstFetch(new Name('null')),
|
default => new Expr\ConstFetch(new Name('null')),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $value
|
|
||||||
* @return Node\Expr
|
|
||||||
*/
|
|
||||||
private static function buildDefaultValueFromScalar(mixed $value): Node\Expr
|
private static function buildDefaultValueFromScalar(mixed $value): Node\Expr
|
||||||
{
|
{
|
||||||
return match (true) {
|
return match (true) {
|
||||||
is_bool($value) => new Expr\ConstFetch(new Name($value ? 'true' : 'false')),
|
is_bool($value) => new Expr\ConstFetch(new Name($value ? 'true' : 'false')),
|
||||||
is_int($value) => new Node\Scalar\LNumber($value),
|
is_int($value) => new Node\Scalar\LNumber($value),
|
||||||
is_float($value) => new Node\Scalar\DNumber($value),
|
is_float($value) => new Node\Scalar\DNumber($value),
|
||||||
is_string($value)=> new Node\Scalar\String_($value),
|
is_string($value) => new Node\Scalar\String_($value),
|
||||||
default => new Expr\ConstFetch(new Name('null')),
|
default => new Expr\ConstFetch(new Name('null')),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $className
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
private static function getCacheFile(string $className): ?string
|
private static function getCacheFile(string $className): ?string
|
||||||
{
|
{
|
||||||
if (self::$cacheDir === null) {
|
if (self::$cacheDir === null) {
|
||||||
@@ -241,7 +192,6 @@ class DeferProxyGenerator
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$cacheDir . str_replace('\\', '_', $className) . '__DeferProxy.php';
|
return self::$cacheDir . str_replace('\\', '_', $className) . '__DeferProxy.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Kiri\Router\Annotate;
|
namespace Kiri\Router\Defer;
|
||||||
|
|
||||||
|
use Kiri\Router\Annotate\Defer;
|
||||||
|
|
||||||
class DeferRegistry
|
class DeferRegistry
|
||||||
{
|
{
|
||||||
@@ -12,12 +14,6 @@ class DeferRegistry
|
|||||||
private static array $registry = [];
|
private static array $registry = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $class
|
|
||||||
* @param string $method
|
|
||||||
* @param Defer $defer
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function add(string $class, string $method, Defer $defer): void
|
public static function add(string $class, string $method, Defer $defer): void
|
||||||
{
|
{
|
||||||
$key = self::key($class, $method);
|
$key = self::key($class, $method);
|
||||||
@@ -26,8 +22,6 @@ class DeferRegistry
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $class
|
|
||||||
* @param string $method
|
|
||||||
* @return Defer[]
|
* @return Defer[]
|
||||||
*/
|
*/
|
||||||
public static function get(string $class, string $method): array
|
public static function get(string $class, string $method): array
|
||||||
@@ -36,10 +30,6 @@ class DeferRegistry
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $class
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function hasAny(string $class): bool
|
public static function hasAny(string $class): bool
|
||||||
{
|
{
|
||||||
$prefix = $class . '::';
|
$prefix = $class . '::';
|
||||||
@@ -53,7 +43,6 @@ class DeferRegistry
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $class
|
|
||||||
* @return array<string, Defer[]> method => Defer[]
|
* @return array<string, Defer[]> method => Defer[]
|
||||||
*/
|
*/
|
||||||
public static function getAll(string $class): array
|
public static function getAll(string $class): array
|
||||||
@@ -71,9 +60,7 @@ class DeferRegistry
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $class
|
* 异步执行 Defer 回调 — 委托 DeferExecutor 处理协程安全与上下文注入
|
||||||
* @param string $method
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public static function execute(string $class, string $method): void
|
public static function execute(string $class, string $method): void
|
||||||
{
|
{
|
||||||
@@ -85,30 +72,12 @@ class DeferRegistry
|
|||||||
$defers = self::$registry[$key];
|
$defers = self::$registry[$key];
|
||||||
unset(self::$registry[$key]);
|
unset(self::$registry[$key]);
|
||||||
|
|
||||||
foreach ($defers as $defer) {
|
DeferExecutor::run($defers);
|
||||||
try {
|
|
||||||
$callback = $defer->callback;
|
|
||||||
$params = $defer->params;
|
|
||||||
|
|
||||||
if (is_array($callback)) {
|
|
||||||
[$cbClass, $cbMethod] = $callback;
|
|
||||||
$instance = \Kiri::getDi()->get($cbClass);
|
|
||||||
call_user_func([$instance, $cbMethod], ...$params);
|
|
||||||
} else {
|
|
||||||
$instance = \Kiri::getDi()->get($callback);
|
|
||||||
call_user_func([$instance, '__invoke'], ...$params);
|
|
||||||
}
|
|
||||||
} catch (\Throwable $throwable) {
|
|
||||||
\Kiri::getLogger()->error('Defer callback failed: ' . $throwable->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除指定类的所有 Defer 注册,用于热重载时清理失效类
|
* 移除指定类的所有 Defer 注册
|
||||||
* @param string $class
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public static function removeClass(string $class): void
|
public static function removeClass(string $class): void
|
||||||
{
|
{
|
||||||
@@ -122,7 +91,6 @@ class DeferRegistry
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取注册表统计信息,用于内存监控
|
|
||||||
* @return array{totalKeys: int, totalDefer: int}
|
* @return array{totalKeys: int, totalDefer: int}
|
||||||
*/
|
*/
|
||||||
public static function getStats(): array
|
public static function getStats(): array
|
||||||
@@ -138,20 +106,12 @@ class DeferRegistry
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function clear(): void
|
public static function clear(): void
|
||||||
{
|
{
|
||||||
self::$registry = [];
|
self::$registry = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $class
|
|
||||||
* @param string $method
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function key(string $class, string $method): string
|
private static function key(string $class, string $method): string
|
||||||
{
|
{
|
||||||
return $class . '::' . $method;
|
return $class . '::' . $method;
|
||||||
+9
-17
@@ -6,6 +6,7 @@ namespace Kiri\Router;
|
|||||||
use Closure;
|
use Closure;
|
||||||
use Kiri;
|
use Kiri;
|
||||||
use Kiri\Router\Annotate\Defer;
|
use Kiri\Router\Annotate\Defer;
|
||||||
|
use Kiri\Router\Defer\DeferExecutor;
|
||||||
use Kiri\Router\Format\IFormat;
|
use Kiri\Router\Format\IFormat;
|
||||||
use Kiri\Router\Format\MixedFormat;
|
use Kiri\Router\Format\MixedFormat;
|
||||||
use Kiri\Router\Format\NoBody;
|
use Kiri\Router\Format\NoBody;
|
||||||
@@ -196,27 +197,18 @@ class Handler implements RequestHandlerInterface
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* 异步执行 Defer 回调 — 委托 DeferExecutor 处理协程安全与上下文注入
|
||||||
*/
|
*/
|
||||||
private function executeDeferred(): void
|
private function executeDeferred(): void
|
||||||
{
|
{
|
||||||
foreach ($this->deferred as $defer) {
|
if (empty($this->deferred)) {
|
||||||
try {
|
return;
|
||||||
$callback = $defer->callback;
|
}
|
||||||
$params = $defer->params;
|
|
||||||
|
|
||||||
if (is_array($callback)) {
|
$defers = $this->deferred;
|
||||||
[$class, $method] = $callback;
|
$this->deferred = [];
|
||||||
$instance = Kiri::getDi()->get($class);
|
|
||||||
call_user_func([$instance, $method], ...$params);
|
DeferExecutor::run($defers);
|
||||||
} else {
|
|
||||||
$instance = Kiri::getDi()->get($callback);
|
|
||||||
call_user_func([$instance, '__invoke'], ...$params);
|
|
||||||
}
|
|
||||||
} catch (\Throwable $throwable) {
|
|
||||||
\Kiri::getLogger()->error('Defer callback failed: ' . $throwable->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -262,9 +262,9 @@ class Router
|
|||||||
$usedArtifact = $router->importArtifact($artifact, $appChangedFiles);
|
$usedArtifact = $router->importArtifact($artifact, $appChangedFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$usedArtifact) {
|
// routes 目录中的显式路由文件必须每次重建路由表时重新 include。
|
||||||
|
// route artifact 只加速注解路由,不能替代 routes/*.php 的注册副作用。
|
||||||
$this->read_dir_file(APP_PATH . 'routes');
|
$this->read_dir_file(APP_PATH . 'routes');
|
||||||
}
|
|
||||||
|
|
||||||
if (!$routeChanged && !empty($appChangedFiles) && ($scanConfig['cache_enabled'] ?? false)) {
|
if (!$routeChanged && !empty($appChangedFiles) && ($scanConfig['cache_enabled'] ?? false)) {
|
||||||
$scanner->scanFiles($appChangedFiles, APP_PATH . 'app/', null, !$usedArtifact);
|
$scanner->scanFiles($appChangedFiles, APP_PATH . 'app/', null, !$usedArtifact);
|
||||||
|
|||||||
+10
-14
@@ -7,7 +7,7 @@ namespace Kiri\Router;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Kiri\Router\Annotate\Defer;
|
use Kiri\Router\Annotate\Defer;
|
||||||
use Kiri\Router\Annotate\DeferRegistry;
|
use Kiri\Router\Defer\DeferRegistry;
|
||||||
use Kiri\Router\Base\NotFoundController;
|
use Kiri\Router\Base\NotFoundController;
|
||||||
use Kiri\Router\Constrict\RequestMethod;
|
use Kiri\Router\Constrict\RequestMethod;
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
@@ -164,7 +164,7 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
|||||||
$array[] = [
|
$array[] = [
|
||||||
'path' => $path,
|
'path' => $path,
|
||||||
'method' => $method,
|
'method' => $method,
|
||||||
'handler' => $controller
|
'handler' => $controller,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return $array;
|
return $array;
|
||||||
@@ -311,16 +311,12 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->methods[$requestMethod . '_' . $path] = new RouteEntry(
|
$middlewares = is_array($entry['middlewares'] ?? null) ? $entry['middlewares'] : [];
|
||||||
requestMethod: $requestMethod,
|
$sourceFile = is_string($sourceFile) ? $this->normalizePath($sourceFile) : null;
|
||||||
path: $path,
|
$sourceKind = is_string($entry['source_kind'] ?? null) ? $entry['source_kind'] : 'attribute';
|
||||||
class: $class,
|
$deferred = is_array($entry['deferred'] ?? null) ? $entry['deferred'] : [];
|
||||||
method: $method,
|
|
||||||
middlewares: is_array($entry['middlewares'] ?? null) ? $entry['middlewares'] : [],
|
$this->methods[$requestMethod . '_' . $path] = new RouteEntry(requestMethod: $requestMethod, path: $path, class: $class, method: $method, middlewares: $middlewares, sourceFile: $sourceFile, sourceKind: $sourceKind, deferred: $deferred);
|
||||||
sourceFile: is_string($sourceFile) ? $this->normalizePath($sourceFile) : null,
|
|
||||||
sourceKind: is_string($entry['source_kind'] ?? null) ? $entry['source_kind'] : 'attribute',
|
|
||||||
deferred: is_array($entry['deferred'] ?? null) ? $entry['deferred'] : [],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -379,8 +375,8 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $class
|
* @param array $response
|
||||||
* @param string $method
|
* @param array $middlewares
|
||||||
* @return Defer[]
|
* @return Defer[]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user