This commit is contained in:
2021-08-03 18:18:09 +08:00
parent 324db2fa3f
commit 5b28c52a10
43 changed files with 755 additions and 653 deletions
-12
View File
@@ -29,7 +29,6 @@ use Server\ServerManager;
use Snowflake\Aop;
use Snowflake\Async;
use Snowflake\Cache\Redis;
use Snowflake\Channel;
use Snowflake\Di\Service;
use Snowflake\Error\ErrorHandler;
use Snowflake\Error\Logger;
@@ -423,16 +422,6 @@ abstract class BaseApplication extends Service
}
/**
* @return Channel
* @throws Exception
*/
public function getChannel(): Channel
{
return $this->get('channel');
}
/**
* @return Pool
* @throws Exception
@@ -470,7 +459,6 @@ abstract class BaseApplication extends Service
'goto' => ['class' => BaseGoto::class],
'response' => ['class' => Response::class],
'request' => ['class' => Request::class],
'channel' => ['class' => Channel::class],
'rpc' => ['class' => \Rpc\Producer::class],
'rpc-service' => ['class' => \Rpc\Service::class],
'http2' => ['class' => Http2::class],
-2
View File
@@ -19,7 +19,6 @@ use Kafka\Producer;
use Rpc\Producer as RPCProducer;
use Snowflake\Async;
use Snowflake\Cache\Redis;
use Snowflake\Channel;
use Snowflake\Error\Logger;
use Snowflake\Event;
use Snowflake\Jwt\Jwt;
@@ -50,7 +49,6 @@ use Snowflake\Pool\Pool;
* @property \Snowflake\Crontab\Producer $crontab
* @property HttpFilter $filter
* @property RPCProducer $rpc
* @property Channel $channel
* @property Shutdown $shutdown
* @property Pool $clientsPool
*/
+1 -1
View File
@@ -95,7 +95,7 @@ class Application extends BaseApplication
if (!class_exists($service)) {
throw new NotFindClassException($service);
}
$class = Snowflake::createObject($service);
$class = Snowflake::getDi()->get($service);
if (method_exists($class, 'onImport')) {
$class->onImport($this);
}
+16 -18
View File
@@ -9,11 +9,14 @@ declare(strict_types=1);
namespace Snowflake\Cache;
use Annotation\Inject;
use Exception;
use Server\Events\OnWorkerExit;
use Server\Events\OnWorkerStop;
use Snowflake\Abstracts\Component;
use Snowflake\Abstracts\Config;
use Snowflake\Core\Json;
use Snowflake\Event;
use Snowflake\Events\EventProvider;
use Snowflake\Exception\ConfigException;
use Snowflake\Snowflake;
@@ -21,35 +24,32 @@ use Snowflake\Snowflake;
* Class Redis
* @package Snowflake\Snowflake\Cache
* @see \Redis
*
* @mixin \Redis
*/
class Redis extends Component
{
/**
* @throws Exception
* @var EventProvider
*/
public function init()
{
Event::on(Event::SYSTEM_RESOURCE_CLEAN, [$this, 'destroy']);
Event::on(Event::SYSTEM_RESOURCE_RELEASES, [$this, 'release']);
Event::on(Event::SERVER_WORKER_START, [$this, 'createPool']);
Event::on(Event::SERVER_TASK_START, [$this, 'createPool']);
}
#[Inject(EventProvider::class)]
public EventProvider $eventProvider;
/**
* @throws ConfigException
* @throws Exception
*/
public function createPool()
public function init()
{
$connections = Snowflake::app()->getRedisFromPool();
$config = $this->get_config();
$length = Config::get('connections.pool.max',10);
$length = Config::get('connections.pool.max', 10);
$this->eventProvider->on(OnWorkerStop::class, [$this, 'destroy'], 0);
$this->eventProvider->on(OnWorkerExit::class, [$this, 'destroy'], 0);
$connections->initConnections('Redis:' . $config['host'], true, $length);
}
@@ -68,12 +68,11 @@ class Redis extends Component
$data = $this->{$name}(...$arguments);
} else {
$data = $this->proxy()->{$name}(...$arguments);
$this->release();
}
if (microtime(true) - $time >= 0.02) {
$this->warning('Redis:' . Json::encode([$name, $arguments]) . (microtime(true) - $time));
}
return $data;
}
@@ -94,7 +93,7 @@ if (_nx ~= 0) then
end
return 0
SCRIPT;
return $this->proxy()->eval($script, ['{lock}:' . $key, $timeout], 1);
return $this->eval($script, ['{lock}:' . $key, $timeout], 1);
}
@@ -105,8 +104,7 @@ SCRIPT;
*/
public function unlock($key): int
{
$redis = $this->proxy();
return $redis->del('{lock}:' . $key);
return $this->del('{lock}:' . $key);
}
-108
View File
@@ -1,108 +0,0 @@
<?php
namespace Snowflake;
use Closure;
use Exception;
use Snowflake\Abstracts\Component;
use SplQueue;
/**
* Class Channel
* @package Snowflake
*/
class Channel extends Component
{
private static ?array $_channels = [];
private static ?array $_waitRecover = [];
public function init()
{
Event::on(Event::SYSTEM_RESOURCE_RELEASES, [$this, 'recover']);
Event::on(Event::SERVER_WORKER_EXIT, [$this, 'cleanAll']);
}
/**
* 回收对象
*/
public function recover()
{
foreach (Channel::$_waitRecover as $key => $value) {
if (empty($value)) {
continue;
}
$channel = $this->channelInit($key);
if ($channel->count() >= 100) {
continue;
}
foreach ($value as $item) {
$channel->enqueue($item);
}
}
Channel::$_waitRecover = [];
}
/**
* @param mixed $value
* @param string $name
* @throws Exception
*/
public function push(mixed $value, string $name = ''): void
{
if (!isset(Channel::$_waitRecover[$name])) {
Channel::$_waitRecover[$name] = [];
}
Channel::$_waitRecover[$name][] = $value;
}
/**
* @param string $name
* @return bool|SplQueue
*/
private function channelInit(string $name = ''): bool|SplQueue
{
if (!isset(static::$_channels[$name]) || !(static::$_channels[$name] instanceof SplQueue)) {
static::$_channels[$name] = new SplQueue();
}
return static::$_channels[$name];
}
/**
*
* 清空缓存
*/
public function cleanAll()
{
static::$_channels = null;
static::$_channels = [];
}
/**
* @param string $name
* @param Closure $closure
* @return mixed
*/
public function pop(string $name, Closure $closure): mixed
{
$channel = $this->channelInit($name);
if ($channel->isEmpty()) {
return call_user_func($closure);
}
return $channel->dequeue();
}
}
+12 -4
View File
@@ -9,11 +9,14 @@ declare(strict_types=1);
namespace Snowflake\Error;
use Annotation\Inject;
use Exception;
use Server\Events\OnAfterRequest;
use Snowflake\Abstracts\Component;
use Snowflake\Abstracts\Config;
use Snowflake\Core\Json;
use Snowflake\Event;
use Snowflake\Events\EventProvider;
use Snowflake\Exception\ConfigException;
use Snowflake\Snowflake;
use Swoole\Coroutine;
@@ -29,15 +32,20 @@ class Logger extends Component
private array $logs = [];
/** @var EventProvider */
#[Inject(EventProvider::class)]
public EventProvider $eventProvider;
private array $sources = [];
/**
*
*/
public function init()
{
Event::on(Event::SYSTEM_RESOURCE_CLEAN, [$this, 'insert']);
Event::on(Event::SYSTEM_RESOURCE_CLEAN, [$this, 'closeSource']);
Event::on(Event::SYSTEM_RESOURCE_RELEASES, [$this, 'closeSource']);
Event::on(Event::SYSTEM_RESOURCE_RELEASES, [$this, 'insert']);
$this->eventProvider->on(OnAfterRequest::class, [$this, 'insert']);
}
+17 -50
View File
@@ -7,6 +7,7 @@ namespace Snowflake;
use Exception;
use Snowflake\Abstracts\BaseObject;
use Swoole\Coroutine;
/**
* Class Event
@@ -85,18 +86,16 @@ class Event extends BaseObject
* @param bool $isAppend
* @throws Exception
*/
public static function on($name, $callback, array $parameter = [], bool $isAppend = false)
public static function on($name, $callback, bool $isAppend = false)
{
if (!isset(static::$_events[$name])) {
static::$_events[$name] = [];
}
if ($callback instanceof \Closure) {
$callback = \Closure::bind($callback, Snowflake::app());
} else if (is_array($callback) && is_string($callback[0])) {
if (is_array($callback) && is_string($callback[0])) {
if (!class_exists($callback[0])) {
throw new Exception('Undefined callback class.');
}
$callback[0] = Snowflake::createObject($callback[0]);
$callback[0] = di($callback[0]);
}
if (static::exists($name, $callback)) {
return;
@@ -130,15 +129,10 @@ class Event extends BaseObject
/**
* @param $name
* @return bool
*/
public static function offName($name): bool
public static function offName($name): void
{
if (!static::exists($name)) {
return true;
}
unset(static::$_events[$name]);
return static::exists($name);
}
@@ -147,14 +141,11 @@ class Event extends BaseObject
* @param null $callback
* @return bool
*/
public static function exists($name, $callback = null): bool
public static function exists($name, $callback): bool
{
if (!isset(static::$_events[$name])) {
if ($callback instanceof \Closure || !isset(static::$_events[$name])) {
return false;
}
if ($callback === null) {
return true;
}
foreach (static::$_events[$name] as $event) {
[$handler, $parameter] = $event;
if ($handler === $callback) {
@@ -175,7 +166,6 @@ class Event extends BaseObject
if (!static::exists($name, $handler)) {
return null;
}
if (empty($handler)) {
return static::$_events[$name];
}
@@ -216,11 +206,14 @@ class Event extends BaseObject
*/
public static function trigger($name, $parameter = null, bool $is_remove = false): bool
{
foreach ((static::$_events[$name] ?? []) as $event) {
foreach ((static::$_events[$name] ?? []) as $key => $event) {
static::execute($event, $parameter);
if ($event instanceof \Closure) {
unset(static::$_events[$name][$key]);
}
}
if ($is_remove) {
static::offName($name);
unset(static::$_events[$name]);
}
return true;
}
@@ -229,45 +222,19 @@ class Event extends BaseObject
/**
* @param $event
* @param $parameter
* @return bool
* @return void
* @throws Exception
*/
private static function execute($event, $parameter): bool
private static function execute($event, $parameter): void
{
try {
$meta = static::mergeParams($event[1], $parameter);
if (call_user_func($event[0], ...$meta) === false) {
return false;
}
return true;
call_user_func($event[0], ...$parameter);
} catch (\Throwable $throwable) {
return logger()->addError($throwable, 'throwable');
logger()->addError($throwable, 'throwable');
return;
}
}
/**
* @param $defaultParameter
* @param array $parameter
* @return array
*/
private static function mergeParams($defaultParameter, array $parameter = []): array
{
if (empty($defaultParameter)) {
$defaultParameter = $parameter;
} else {
if (!is_array($parameter)) {
$parameter = [];
}
foreach ($parameter as $key => $value) {
$defaultParameter[] = $value;
}
}
if (!is_array($defaultParameter)) {
$defaultParameter = [$defaultParameter];
}
return $defaultParameter;
}
}
+20 -15
View File
@@ -2,31 +2,36 @@
namespace Snowflake\Events;
class EventDispatch
use Annotation\Inject;
use Snowflake\Abstracts\BaseObject;
/**
*
*/
class EventDispatch extends BaseObject
{
private EventListener $eventListener;
#[Inject(EventProvider::class)]
public EventProvider $eventProvider;
/**
* @param $event
* @param array $params
* @param object $triggerEvent
* @return object
*/
public function emit($event, array $params = [])
public function dispatch(object $triggerEvent): object
{
$events = $this->eventListener->getEventListeners($event);
if (empty($events)) {
return;
}
while ($events->valid()) {
/** @var EventDispatchInterface $interface */
$interface = $events->current();
$interface->onHandler();
if ($interface->stopPagination()) {
$lists = $this->eventProvider->getListenersForEvent($triggerEvent);
foreach ($lists as $listener) {
/** @var Struct $list */
$listener($triggerEvent);
if ($triggerEvent instanceof StoppableEventInterface && $triggerEvent->isPropagationStopped()) {
break;
}
$events->next();
}
return $triggerEvent;
}
}
-18
View File
@@ -1,18 +0,0 @@
<?php
namespace Snowflake\Events;
/**
*
*/
interface EventDispatchInterface
{
public function getZOrder(): int;
public function onHandler(): void;
public function stopPagination(): bool;
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Snowflake\Events;
/**
*
*/
interface EventInterface
{
public function process(): void;
}
-37
View File
@@ -1,37 +0,0 @@
<?php
namespace Snowflake\Events;
use SplPriorityQueue;
class EventListener
{
/** @var SplPriorityQueue[] */
private array $_events = [];
/**
* @param $event
* @param EventDispatchInterface $handler
*/
public function on($event, EventDispatchInterface $handler)
{
if (!isset($this->_events[$event])) {
$this->_events[$event] = new SplPriorityQueue();
}
$this->_events[$event]->insert($handler, $handler->getZOrder());
}
/**
* @param $event
* @return SplPriorityQueue|null
*/
public function getEventListeners($event): ?SplPriorityQueue
{
return $this->_events[$event] ?? null;
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace Snowflake\Events;
/**
*
*/
class EventProvider implements EventProviders
{
/** @var Struct[] */
private array $_listeners = [];
/**
* @param object $event
* @return iterable
*/
public function getListenersForEvent(object $event): iterable
{
$queue = new \SplPriorityQueue();
// TODO: Implement getListenersForEvent() method.
foreach ($this->_listeners as $listener) {
if (!($event instanceof $listener->event)) {
continue;
}
$queue->insert($listener, $listener->priority);
}
return $queue;
}
/**
* @param string $event
* @param callable $handler
* @param int $zOrder
*/
public function on(string $event, callable $handler, int $zOrder = 1)
{
$this->_listeners[$event][] = new Struct($event, $handler, $zOrder);
}
}
+15 -1
View File
@@ -2,7 +2,21 @@
namespace Snowflake\Events;
class EventProviders
/**
*
*/
interface EventProviders
{
/**
* @param object $event
* An event for which to return the relevant listeners.
* @return iterable<callable>
* An iterable (array, iterator, or generator) of callables. Each
* callable MUST be type-compatible with $event.
*/
public function getListenersForEvent(object $event): iterable;
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Snowflake\Events;
/**
*
*/
interface StoppableEventInterface
{
/**
* Is propagation stopped?
*
* This will typically only be used by the Dispatcher to determine if the
* previous listener halted propagation.
*
* @return bool
* True if the Event is complete and no further listeners should be called.
* False to continue calling listeners.
*/
public function isPropagationStopped() : bool;
}
+25
View File
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Snowflake\Events;
/**
*
*/
class Struct
{
public string $event;
public \Closure $listener;
public int $priority;
public function __construct(string $event, callable $listener, int $priority)
{
$this->event = $event;
$this->listener = $listener;
$this->priority = $priority;
}
}
+1 -1
View File
@@ -182,7 +182,7 @@ class Connection extends Component
return;
}
if ($client->inTransaction()) {
$client->commit();
return;
}
$this->getPool()->push($coroutineName, $client);
Context::remove($coroutineName);