mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-23 00:25:35 +08:00
add timer tick
This commit is contained in:
@@ -12,13 +12,13 @@
|
|||||||
`\ZM\Annotation\OneBot\BotCommand` 注解事件类,在经过全局别名后,你也可以使用 `\BotCommand` 作为注解事件,效果相同。
|
`\ZM\Annotation\OneBot\BotCommand` 注解事件类,在经过全局别名后,你也可以使用 `\BotCommand` 作为注解事件,效果相同。
|
||||||
|
|
||||||
## 别名列表
|
## 别名列表
|
||||||
|
|
||||||
| 全类名 | 别名 |
|
| 全类名 | 别名 |
|
||||||
|--------------------------------------------------------|-------------------------|
|
|--------------------------------------------------------|-------------------------|
|
||||||
| `\ZM\Annotation\Framework\BindEvent` | `BindEvent` |
|
| `\ZM\Annotation\Framework\BindEvent` | `BindEvent` |
|
||||||
| `\ZM\Annotation\Framework\Cron` | `Cron` |
|
| `\ZM\Annotation\Framework\Cron` | `Cron` |
|
||||||
| `\ZM\Annotation\Framework\Init` | `Init` |
|
| `\ZM\Annotation\Framework\Init` | `Init` |
|
||||||
| `\ZM\Annotation\Framework\Setup` | `Setup` |
|
| `\ZM\Annotation\Framework\Setup` | `Setup` |
|
||||||
|
| `\ZM\Annotation\Framework\Tick` | `Tick` |
|
||||||
| `\ZM\Annotation\Http\Controller` | `Controller` |
|
| `\ZM\Annotation\Http\Controller` | `Controller` |
|
||||||
| `\ZM\Annotation\Http\Route` | `Route` |
|
| `\ZM\Annotation\Http\Route` | `Route` |
|
||||||
| `\ZM\Annotation\Middleware\Middleware` | `Middleware` |
|
| `\ZM\Annotation\Middleware\Middleware` | `Middleware` |
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class_alias(\ZM\Annotation\Framework\BindEvent::class, 'BindEvent');
|
|||||||
class_alias(\ZM\Annotation\Framework\Cron::class, 'Cron');
|
class_alias(\ZM\Annotation\Framework\Cron::class, 'Cron');
|
||||||
class_alias(\ZM\Annotation\Framework\Init::class, 'Init');
|
class_alias(\ZM\Annotation\Framework\Init::class, 'Init');
|
||||||
class_alias(\ZM\Annotation\Framework\Setup::class, 'Setup');
|
class_alias(\ZM\Annotation\Framework\Setup::class, 'Setup');
|
||||||
|
class_alias(\ZM\Annotation\Framework\Tick::class, 'Tick');
|
||||||
|
|
||||||
class_alias(\ZM\Annotation\Http\Controller::class, 'Controller');
|
class_alias(\ZM\Annotation\Http\Controller::class, 'Controller');
|
||||||
class_alias(\ZM\Annotation\Http\Route::class, 'Route');
|
class_alias(\ZM\Annotation\Http\Route::class, 'Route');
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use ZM\Config\ZMConfig;
|
|||||||
use ZM\Container\ContainerHolder;
|
use ZM\Container\ContainerHolder;
|
||||||
use ZM\Logger\ConsoleLogger;
|
use ZM\Logger\ConsoleLogger;
|
||||||
use ZM\Middleware\MiddlewareHandler;
|
use ZM\Middleware\MiddlewareHandler;
|
||||||
|
use ZM\Schedule\Timer;
|
||||||
use ZM\Store\Database\DBException;
|
use ZM\Store\Database\DBException;
|
||||||
use ZM\Store\Database\DBQueryBuilder;
|
use ZM\Store\Database\DBQueryBuilder;
|
||||||
use ZM\Store\Database\DBWrapper;
|
use ZM\Store\Database\DBWrapper;
|
||||||
@@ -55,6 +56,29 @@ function zm_sleep(float|int $time)
|
|||||||
Adaptive::sleep($time);
|
Adaptive::sleep($time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个计时器(Timer::tick() 的别名)
|
||||||
|
*
|
||||||
|
* @param int $ms 时间(毫秒)
|
||||||
|
* @param callable $callback 回调函数
|
||||||
|
* @param int $times 重复次数(如果为 0 或 -1,则永久循环,其他大于 0 的数为限定次数)
|
||||||
|
*/
|
||||||
|
function zm_timer_tick(int $ms, callable $callback, int $times = 0): int
|
||||||
|
{
|
||||||
|
return Timer::tick($ms, $callback, $times);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个延后一次性计时器,只在指定毫秒后执行一次即销毁(Timer::after() 的别名)
|
||||||
|
*
|
||||||
|
* @param int $ms 时间(毫秒)
|
||||||
|
* @param callable $callback 回调函数
|
||||||
|
*/
|
||||||
|
function zm_timer_after(int $ms, callable $callback): int
|
||||||
|
{
|
||||||
|
return Timer::after($ms, $callback);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取协程接口
|
* 获取协程接口
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ use Doctrine\Common\Annotations\AnnotationReader;
|
|||||||
use Koriym\Attributes\AttributeReader;
|
use Koriym\Attributes\AttributeReader;
|
||||||
use Koriym\Attributes\DualReader;
|
use Koriym\Attributes\DualReader;
|
||||||
use ZM\Annotation\Framework\Cron;
|
use ZM\Annotation\Framework\Cron;
|
||||||
|
use ZM\Annotation\Framework\Tick;
|
||||||
use ZM\Annotation\Http\Controller;
|
use ZM\Annotation\Http\Controller;
|
||||||
use ZM\Annotation\Http\Route;
|
use ZM\Annotation\Http\Route;
|
||||||
use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
||||||
use ZM\Annotation\Middleware\Middleware;
|
use ZM\Annotation\Middleware\Middleware;
|
||||||
use ZM\Schedule\Schedule;
|
use ZM\Schedule\Schedule;
|
||||||
|
use ZM\Schedule\Timer;
|
||||||
use ZM\Store\FileSystem;
|
use ZM\Store\FileSystem;
|
||||||
use ZM\Utils\HttpUtil;
|
use ZM\Utils\HttpUtil;
|
||||||
|
|
||||||
@@ -62,6 +64,7 @@ class AnnotationParser
|
|||||||
Route::class => [[$this, 'addRouteAnnotation']],
|
Route::class => [[$this, 'addRouteAnnotation']],
|
||||||
Closed::class => [fn () => false],
|
Closed::class => [fn () => false],
|
||||||
Cron::class => [[resolve(Schedule::class), 'addSchedule']],
|
Cron::class => [[resolve(Schedule::class), 'addSchedule']],
|
||||||
|
Tick::class => [[Timer::class, 'registerTick']],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,7 +243,13 @@ class AnnotationParser
|
|||||||
return $o;
|
return $o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parseSpecial($annotation, $same_method_annotations = null): ?bool
|
/**
|
||||||
|
* 单独解析特殊注解
|
||||||
|
*
|
||||||
|
* @param object|string $annotation 注解对象
|
||||||
|
* @param null|array $same_method_annotations 相同方法下的其他注解列表(可为数组或 null)
|
||||||
|
*/
|
||||||
|
public function parseSpecial(object|string $annotation, ?array $same_method_annotations = null): ?bool
|
||||||
{
|
{
|
||||||
foreach (($this->special_parsers[$annotation::class] ?? []) as $parser) {
|
foreach (($this->special_parsers[$annotation::class] ?? []) as $parser) {
|
||||||
$result = $parser($annotation, $same_method_annotations);
|
$result = $parser($annotation, $same_method_annotations);
|
||||||
|
|||||||
25
src/ZM/Annotation/Framework/Tick.php
Normal file
25
src/ZM/Annotation/Framework/Tick.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ZM\Annotation\Framework;
|
||||||
|
|
||||||
|
use Symfony\Contracts\Service\Attribute\Required;
|
||||||
|
use ZM\Annotation\AnnotationBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Annotation
|
||||||
|
* @NamedArgumentConstructor()
|
||||||
|
* @Target("METHOD")
|
||||||
|
*/
|
||||||
|
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
|
||||||
|
class Tick extends AnnotationBase
|
||||||
|
{
|
||||||
|
#[Required]
|
||||||
|
public int $tick_ms;
|
||||||
|
|
||||||
|
public function __construct(int $tick_ms, public int $worker_id = 0)
|
||||||
|
{
|
||||||
|
$this->tick_ms = $tick_ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -199,14 +199,14 @@ class WorkerEventListener
|
|||||||
// 从 plugins 目录加载插件,包含 phar 和文件夹形式
|
// 从 plugins 目录加载插件,包含 phar 和文件夹形式
|
||||||
$count = PluginManager::addPluginsFromDir($load_dir);
|
$count = PluginManager::addPluginsFromDir($load_dir);
|
||||||
if ($count !== 0) {
|
if ($count !== 0) {
|
||||||
logger()->info('Loaded ' . $count . ' user plugins from plugin dir');
|
logger()->debug('已加载 ' . $count . ' 个普通插件');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从 composer 依赖加载插件
|
// 从 composer 依赖加载插件
|
||||||
if (config('global.plugin.composer_plugin_enable', true)) {
|
if (config('global.plugin.composer_plugin_enable', true)) {
|
||||||
$count = PluginManager::addPluginsFromComposer();
|
$count = PluginManager::addPluginsFromComposer();
|
||||||
if ($count !== 0) {
|
if ($count !== 0) {
|
||||||
logger()->info('Loaded ' . $count . ' user plugins from composer');
|
logger()->info('已加载 ' . $count . ' 个 Composer 插件');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class Framework
|
|||||||
public const VERSION_ID = 681;
|
public const VERSION_ID = 681;
|
||||||
|
|
||||||
/** @var string 版本名称 */
|
/** @var string 版本名称 */
|
||||||
public const VERSION = '3.0.0-beta7';
|
public const VERSION = '3.0.0-beta8';
|
||||||
|
|
||||||
/** @var array 传入的参数 */
|
/** @var array 传入的参数 */
|
||||||
protected array $argv;
|
protected array $argv;
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ class PluginManager
|
|||||||
foreach (self::$plugins as $name => $meta) {
|
foreach (self::$plugins as $name => $meta) {
|
||||||
// 除了内建插件外,输出 log 告知启动插件
|
// 除了内建插件外,输出 log 告知启动插件
|
||||||
if ($meta->getPluginType() !== ZM_PLUGIN_TYPE_NATIVE) {
|
if ($meta->getPluginType() !== ZM_PLUGIN_TYPE_NATIVE) {
|
||||||
logger()->info('Enabling plugin: ' . $name);
|
logger()->info('正在启用插件 ' . $name);
|
||||||
}
|
}
|
||||||
// 先判断依赖关系,如果声明了依赖,但依赖不合规则报错崩溃
|
// 先判断依赖关系,如果声明了依赖,但依赖不合规则报错崩溃
|
||||||
foreach ($meta->getDependencies() as $dep_name => $dep_version) {
|
foreach ($meta->getDependencies() as $dep_name => $dep_version) {
|
||||||
@@ -257,6 +257,11 @@ class PluginManager
|
|||||||
foreach ($entity->getInits() as $init) {
|
foreach ($entity->getInits() as $init) {
|
||||||
AnnotationMap::addSingleAnnotation($init);
|
AnnotationMap::addSingleAnnotation($init);
|
||||||
}
|
}
|
||||||
|
// 设置 TimerTick 注解
|
||||||
|
foreach ($entity->getTimerTicks() as $tick) {
|
||||||
|
AnnotationMap::addSingleAnnotation($tick);
|
||||||
|
$parser->parseSpecial($tick);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 如果设置了 Autoload file,那么将会把 psr-4 的加载路径丢进 parser
|
// 如果设置了 Autoload file,那么将会把 psr-4 的加载路径丢进 parser
|
||||||
foreach ($meta->getAutoloadPsr4() as $namespace => $path) {
|
foreach ($meta->getAutoloadPsr4() as $namespace => $path) {
|
||||||
|
|||||||
29
src/ZM/Plugin/Traits/TickTrait.php
Normal file
29
src/ZM/Plugin/Traits/TickTrait.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ZM\Plugin\Traits;
|
||||||
|
|
||||||
|
use ZM\Annotation\Framework\Tick;
|
||||||
|
|
||||||
|
trait TickTrait
|
||||||
|
{
|
||||||
|
protected array $ticks = [];
|
||||||
|
|
||||||
|
public function addTimerTick(int $ms, callable $callback, int $worker_id = 0): void
|
||||||
|
{
|
||||||
|
$tick = new Tick($ms, $worker_id);
|
||||||
|
if (is_array($callback)) {
|
||||||
|
$tick->class = $callback[0];
|
||||||
|
$tick->method = $callback[1];
|
||||||
|
} elseif ($callback instanceof \Closure) {
|
||||||
|
$tick->method = $callback;
|
||||||
|
}
|
||||||
|
$this->ticks[] = $tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTimerTicks(): array
|
||||||
|
{
|
||||||
|
return $this->ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,4 +18,5 @@ class ZMPlugin
|
|||||||
use Traits\PluginLoadTrait;
|
use Traits\PluginLoadTrait;
|
||||||
use Traits\RouteTrait;
|
use Traits\RouteTrait;
|
||||||
use Traits\PluginPackTrait;
|
use Traits\PluginPackTrait;
|
||||||
|
use Traits\TickTrait;
|
||||||
}
|
}
|
||||||
|
|||||||
32
src/ZM/Schedule/Timer.php
Normal file
32
src/ZM/Schedule/Timer.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ZM\Schedule;
|
||||||
|
|
||||||
|
use ZM\Annotation\Framework\Tick;
|
||||||
|
use ZM\Framework;
|
||||||
|
|
||||||
|
class Timer
|
||||||
|
{
|
||||||
|
public static function tick(int $ms, callable $callback, int $times = 0): int
|
||||||
|
{
|
||||||
|
return Framework::getInstance()->getDriver()->getEventLoop()->addTimer($ms, $callback, $times);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function after(int $ms, callable $callback): int
|
||||||
|
{
|
||||||
|
return Framework::getInstance()->getDriver()->getEventLoop()->addTimer($ms, $callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function registerTick(Tick $v): void
|
||||||
|
{
|
||||||
|
if ($v->class !== '' && $v->method !== '') {
|
||||||
|
self::tick($v->tick_ms, [resolve($v->class), $v->method]);
|
||||||
|
} elseif (is_callable($v->method)) {
|
||||||
|
self::tick($v->tick_ms, $v->method);
|
||||||
|
} else {
|
||||||
|
logger()->warning('注册的 Tick 定时器回调函数错误');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user