Releases: imiphp/imi
紧急修复问题
测试用例加持,兼容 PHP 7.1-7.4、Swoole 4.3-4.4
更新内容
新增
-
增加单元测试(PHP7.1-7.4、nightly 全部通过),从此不再担心修复一个 bug,产生更多 bug。这是一个长期任务,需要不断充实测试用例。参与开源项目经历是个很好的面试谈判筹码,欢迎大家来贡献测试代码,你好我好大家好!
-
新增 Imi\Util\Coroutine::create(),与 imigo() 行为一致
-
新增 Imi\Util\Http\MessageUtil 类
-
新增框架优先级定义,常量类:Imi\Util\ImiPriority
修复
-
修复热重启问题:worker exit timeout, forced to terminate
-
修复 PDO Statement 无法命中缓存问题
-
修复日志重复写入问题
-
修复 MySQL->query() 方法不记录最后执行 SQL 语句问题
-
修复当设置task_enable_coroutine但不设置enable_coroutine时,task事件监听参数错误问题
-
修复类型声明
-
修复 RedisManager::getNewInstance() 无法被 RedisManager::release() 释放问题
-
修正 Redis 相关类型注释
-
修复 withAddedHeader() 问题
-
修复使用 TAutoInject 时,有父类导致无法正常注入的问题
-
修复Callback、CallableValue注解无法注入属性问题
-
修复配置值注入、常量注入注解,无法注入到属性问题
优化
-
优化 BeanProxy::getConfigInjects()
-
优化 Imi\Db\Query\Result
-
非 worker 进程投递的 task,不再自动 finish
-
同步池子 getResource() 不再有可能返回 null,一律抛出异常
-
ITaskHandler->handle() 支持返回值自动 finish
-
规范内部监听 IMI.INITED 事件的优先级
-
优化 BeanProxy,现在不用等到回收周期,立即会被释放
-
注入属性值的注解类改为 Imi\Aop\Annotation\BaseInjectValue
-
进程、进程池进程,强制开启协程化
测试用例计划及进度
- Aop
- Config
- Cache
- Db
- Enum
- Event
- Inject
- Redis
- HttpServer
- HttpValidate
- WebSocketServer
- TCPServer
- UDPServer
- Task
- Lock
- Log
- Model
- Process
- Utils
专注单体应用的 PHP 协程应用开发框架
imi 介绍
imi 是基于 PHP 协程应用开发框架,它支持 HttpApi、WebSocket、TCP、UDP 应用开发。
由 Swoole 提供强力驱动,Swoole 拥有常驻内存、协程非阻塞 IO 等特性。
框架遵守 PSR 标准规范,提供 AOP、注解、连接池、请求上下文管理、ORM模型等常用组件。
imi 的模型支持关联关系的定义,增删改查一把梭!
作者介绍
宇润,江苏无锡人,94年出生。初中自己接触易语言,从此踏入代码的世界。
2013 年开发并发布 YurunPHP 框架(现已停止维护)。
2017 年开始正式玩 git 和发布开源项目,开源的东西都是自己能用到才会去做,不会为了造轮子而造,一切为了实用。
2018 年接触 Swoole,打开了新世界的大门,原来 PHP 还能这么玩!
2018年4月16日,我为 imi 写下了第一个字节的代码。
2018年6月21日,发布了第一个公开版本 v0.0.1。
经过一年实战,2019年6月21日,一周年之际正式发布 v1.0.0 版本。
宇润部分开源项目:imi、YurunHttp、YurunOAuthLogin、PaySDK、ChineseUtil
核心组件
- Server (Http/Websocket/Tcp/Udp)
- 容器 (PSR-11)
- Aop 注入
- Http 中间件 (PSR-15)
- MySQL 连接池 (协程&同步,主从,负载均衡)
- Redis 连接池 (协程&同步,负载均衡)
- Db 连贯操作
- 关系型数据库 模型
- 跨进程共享内存表 模型
- Redis 模型
- 日志 (PSR-3 / File + Console)
- 缓存 (PSR-16 / File + Redis)
- 验证器 (Valitation)
- Task 异步任务
- 进程/进程池
- 命令行开发辅助工具
- 业务代码热更新
扩展组件
开始使用
基于 imi 的项目
SixMQ (宇润)
慢点博客 (慢点)
其它项目因工作原因不便透露,已知我所在公司、私单项目正在运行 imi。
起源 & 设计 & 未来
起源
上面提到,我 2018 年接触 Swoole,打开了新世界的大门,原来 PHP 还能这么玩!
我认为的最好的学习方法,那就是去用,没有实际的功能去实现,学了也会容易忘,不算真正学会。之前我也有 YurunPHP 框架的开发经验,于是决定造个框架吧。
设计
开发 imi 之前,研究了好几个当时比较出名的框架,看到 Swoft 后,最终决定在 imi 框架大量使用注解。至于注解的优缺点,相比百度能比我说得更好,这里就不再复制粘贴一遍了。
目前大部分 Swoole 框架大都在强调微服务,但 imi 的设计理念确是:
微服务可以有,但不是必须
我认为绝大部分开发者的公司,用不着,或者根本没有必要上微服务。微服务的开发、维护成本会比较大,没有一定规模和业务量的,如果强行上微服务会本末倒置,给自己找麻烦。
imi 目前实现了最基础的 imi-rpc 组件,以及支持了 hprose 协议。虽然还没有更多深入的实现,但这都说明了 imi 的设计理念,可以有,就看做不做。
所以,imi 目前主打的还是单体应用开发。项目跑在 Swoole 下,可以比在 fpm 下性能更好,承载访问量更大,尤其是在大量调用第三方接口的 I/O 密集型场景。
WebSocket、TCP、UDP 协议的开发,也是 Swoole 带来的一大优势。
当然,Swoole 用来开发中间件也是相当不错的,不能只把眼光放在 curd 上。
未来
imi 未来也会逐步向微服务方面探索和发展,只不过现在更想做好眼前的单体应用开发。
联系我们
Github 反馈:https://github.com/Yurunsoft/IMI/issues
Segmentfault 提问:https://segmentfault.com/
开源中国 问答:https://www.oschina.net/question
欢迎真正喜欢代码,而不是仅仅当作是工作的朋友,加入 imi 开发组!
自动管理请求上下文,新增参数过滤器
2个多月没有刷版本号,imi并没有凉,而是因为我实在太忙啦!
我们公司项目使用imi已经上线,这两个多月大部分时候是针对imi做bug修复,以及开发体验的细节上的提升。
这次 v0.3 版本发布是这两个月工作成果的一次总结,在此感谢群友们为imi做出的贡献!
最后,距离imi的 v1.0 正式版发布越来越近啦!
更新日志
新增
-
新增方法参数过滤器FilterArg
-
新增ArrayUtil::random()方法,获取随机成员
-
新增imigo函数(启动一个协程,自动创建和销毁上下文)
-
新增imiCallable函数(为传入的回调自动创建和销毁上下文,并返回新的回调)
-
新增IMI.REQUEST_CONTENT.CREATE、IMI.REQUEST_CONTENT.DESTROY事件
-
新增注解:DbInject、RedisInject、PoolResource
可用于注入连接池中的资源对象到属性 -
新增支持根据记录数计算总页数,Pagination->calcPageCount
-
缓存注解允许指定hash方法,默认为md5
调整/增强
-
调整模型生成逻辑,生成表结构定义在基类,实际的模型类继承基类
修改了表结构重新生成模型,也不用担心会覆盖掉模型类中自己写的方法 -
现在注入方法的Before也可以修改参数了
-
ExtractData 注解从此脱离 HttpValidation 注解依赖
-
调整默认runtime路径为:项目命名空间根下的.runtime目录中
避免默认在/tmp目录中,可能被linux内置清理给清掉了 -
热更新进程默认将runtime目录加入排除
-
调整连接池配置maxActiveTime默认值为null,新增maxUsedTime参数
-
调整连接池配置,当gcInterval为null时,不启动定时器
-
禁止在 MacOS 下设置进程名,解决报错问题
-
连接池配置默认minResources调整为1
-
数据库查询器的join方法现在支持对表名使用as设定别名
例:Db::query()->join('table as alias') -
为 PDO Statement 兼容支持 bool 类型值代入
-
Cache相关注解的key属性,支持用{:args}代入所有方法参数的 hash 值
-
当使用Swoole协程Redis时,支持使用_serialize()方法
-
新增路由初始化时的服务器类型判断
-
调整热更新检测用到的文件路径到runtime中
-
View 注解的 renderType 属性默认设置从 html 改为 json
原因:使用 imi 更推荐是用于开发接口,而不是用于后端页面渲染
修复
-
修正错误的注释
-
修复Session中间件潜在问题
-
修复ExtractData注解在特定情况无效问题
-
修复内存表模型,当属性名和Column注解中设定不一致时的问题
-
修复使用内存表模型时的Trying to get property of non-object问题
-
修复buildRuntime问题
-
修复Statement问题
-
修复数据库连接回收后还有残留的问题(Statement缓存化的原因)
-
修复连接池资源释放,以及并发情况下数量超过maxResources配置的问题
-
修复池子重复初始化问题
-
修复数据库关键词处理逻辑问题
-
修复当删除文件时,热更新报错问题
-
修复一个notice问题
-
修复部分场景下,框架内部无法正常启动命令行
-
修复查询器leftJoin()方法实际为inner join的问题
-
修复WS、TCP、UDP注解中间件问题
-
修复缓存功能在非服务器上下文下无法使用的问题
-
修复使用 ? 预处理SQL的问题
-
修复 imi/buildImiRuntime 后存在的注解修改无效问题
-
修复重复 send() 导致的 Http request is finished 问题
-
修复WebSocket无法握手问题
-
修复少数环境中无法正常启动项目的问题
-
修复配置文件注入属性的问题
-
修复 logCacheNumber 数字判定 bug
-
修复 Call to a member function isVariadic() on null 问题
-
修复 TCP、UDP 作为子服务器时的 setting 问题
-
修复配置路由问题
-
修复进程池进程名称问题
-
修复命令行参数解析不严谨的问题
-
修复类没有被use的问题
-
修复验证失败时,buildMessage存在的问题
1秒增量热更新 + 60余项改进
距离上次发布差不多一个月了,这期间 imi 稳步推进,修复各项问题的同时,增加了不少实用组件和注解。
此次更新,在开发项目的体验也有巨大的提升。imi 的热更新采用了最新的增量更新技术,原本我们的实际项目在 WSL 下热重启需要 6 秒(根据文件增多,逐渐变慢),现在使用框架核心运行时缓存
+热更新重启采用增量方式
,不管文件增加多少只需 1 秒左右,即可完成热重新重启,极速的体验~
另外我们的框架核心运行时缓存、项目运行时缓存、数据库 Statement
复用等优化,也为开发、生产时的性能及体验打下了坚实的基础。
我们将持续为性能优化,为可靠性优化。
在此要特别感谢 @wi1dcard 一直以来的讨论交流,感谢群里每一位同学。
当前 imi 还不是正式版,就快了,请耐心等待哦!
更新日志:
新增
Redis
-
新增RedisManager类(getNewInstance/getInstance/release/getDefaultPoolName)
-
新增Redis类,用于快捷操作,如:Imi\Redis\Redis::set($key, $value)
-
新增 redis.quickFromRequestContext 配置项,支持配置Redis快捷操作类,使用RequestContext独享连接还是连接池实时争抢
-
Redis连接池配置新增支持uri格式
缓存
-
新增RedisHash缓存驱动
-
新增 Cacheable、CacheEvict、CachePut 注解
-
实现 Cacheable 注解中的 Lockable 嵌套使用
锁
- 新增 Lock,支持注解锁 Lockable,默认带有 RedisLock 支持
配置
-
新增支持 Config::get('@currentServer.xxx') 用法,当前服务器配置中不存在则取 @app 中的配置
-
增加注入值注解的概念,支持 ConfigValue 等注解,可用于注解参数使用配置值
注解
-
新增 Callback 注解,其 class 可配合 Inject 注解,实现表示bean类方法回调
-
Condition注解的args属性,增加默认值
-
新增 Compare、ValidateValue 用于验证的注解
-
新增 ConstValue 注解,从从常量中读取值注入注解属性
验证器
-
Http 验证器新增支持验证 $headers、$cookie、$session
-
为验证器增加$this支持
其它
-
新增支持忽略路由URL大小写
-
实现进程名称统一管理
-
新增支持方法参数注入
-
为Bean类统一增加__clone支持
-
实现了unset()模型类属性的处理
-
新增用于过滤字段的列表 Imi\Util\FilterableList
-
MySQL、Redis连接池配置新增支持uri格式
-
新增支持.env环境变量
-
数据库查询器支持 replace into 用法
-
Model->save()实现方式改为replace
-
@ExtractData 现在可以导出单独的$get/$post/$body等数据了
-
新增jsonBodyIsObject配置项,设置post body为json时,转为对象还是数组,默认为false数组。可以和@app.jsonBodyIsObject或@currentServer.jsonBodyIsObject配合使用
-
新增 Pagination 分页计算类
-
新增 Imi\Util\ObjectArrayHelper::filter() 过滤对象或数组属性的方法
-
新增热重启耗时输出
优化
-
完善CoroutineRedisHandler类魔术方法注释
-
因PHP BUG,放弃使用匿名类,Bean类采用eval()+动态类名,不再使用include Bean缓存文件,Bean缓存相关配置及方法移除。因此,性能有所提升。
-
Worker 进程启动时,重新加载项目配置及组件
-
调整Db、Redis获取默认连接池名称,使用@currentServer配置
-
现在缓存的$ttl参数支持传递\DateInterval类型了
-
完善 LazyArrayObject
-
将Redis模块中获取到的实例对象,统一改为 Imi\Redis\RedisHandler
-
优化热更新提示内容、重启逻辑,改为增量方式,性能更高
-
新增支持构建框架预加载缓存,提升项目开发时的热更新性能
-
优化onShutdown()时,日志处理如果发生错误或异常,直接输出错误信息
不兼容的调整
-
Imi\Redis\Redis 类更名为 Imi\Redis\CoroutineRedisHandler (连接池中如果有指定,请修改)
-
方法验证抛出的异常信息,不再包含 "xxx Parameter verification is incorrect" 信息
-
调整验证注解的args参数格式,注意与之前版本不兼容
-
弃用Swoole内置序列化,改为php序列化。原因:Swoole官方未来将不再维护序列化功能
-
信息提示英文规范
修复
-
修复Db类获取默认连接池名称问题
-
修复常量注解处理错误
-
修复master进程的事件无法触发问题
-
修复服务器配置中注入HttpRoute失效问题
-
修复热更新在特定情况下filemtime warning问题
-
修复当使用Swoole MySQL驱动时,Result->getRowCount()报错问题
-
修复开启一键协程化时,文件缓存写入失败问题
-
修复一些场景下的可变参数处理问题
-
修复使用Swoole协程MySQL时,fetchAll \PDO::FETCH_COLUMN 如果不指定$fetchArgument,结果为null问题
-
修复热重启后,@app.pools配置更改无效问题
-
修复一处潜在的notice问题
-
修复出现重复中间件时的问题
-
修复因@serializable注解导致的,模型插入更新数据缺失问题
-
修复dev/ext生成问题
新增支持验证器、Http 验证器、枚举
此次更新除了日常修复bug以外,提升了数据库操作性能,新增验证器、Http 验证器、枚举。距离1.0
正式版发布已经不远啦!
验证器
// 限于篇幅,只列出其中一种验证,其它的请查阅文档
@Decimal(min=-0.01, max=999.99, accuracy=2, message="小数必须大于等于{min},小于等于{max},小数点最多保留{accuracy}位小数,当前值为{:value}")
枚举
<?php
namespace ImiDemo\HttpDemo\MainServer\Enum;
use Imi\Enum\BaseEnum;
use Imi\Enum\Annotation\EnumItem;
class Status extends BaseEnum
{
/**
* @EnumItem("正确")
*/
const YES = 1;
/**
* @EnumItem("错误")
*/
const NO = 0;
}
// 使用:
// 根据名称获得常量值
Status::getValue('YES');
// 根据值获得文字说明
Status::getText(Status::YES);
// 根据值获得 @EnumItem 注解对象
Status::getData(Status::YES);
// 获取枚举类中所有名称
Status::getNames();
// 获取枚举类中所有值
Status::getValues();
更新日志:
新增
- 新增支持类常量注解,支持Enum枚举(https://doc.imiphp.com/components/struct/enum.html)
- 新增验证器(https://doc.imiphp.com/components/validation/index.html)
- 新增Http参数验证器(https://doc.imiphp.com/components/httpserver/validation.html)
- 新增 Worker::isTask() 方法
- 新增 dev/ext 工具,生成 IDE 帮助文件
优化
- 注解扫描支持更多命名空间
- 完善 buildRuntime 报错提示
- 优化冷启动、热重启时错误刷屏问题
- 调整BeanFactory实例化对象初始化执行顺序为:__construct -> injectProps -> __init
- 新增支持数据库 statement 缓存化,避免重复创建 statement,提升性能
- 优化数据库查询器查询时出现错误的处理
- AroundJoinPoint->proceed()方法支持传参
修复
- 修复 IMI.MAIN_SERVER.WORKER.START.APP 只执行一次的问题
- 修复致命错误出错代码定位错误问题
- 修正 PoolItem 未按照设计思路计数的问题
- 修复注入属性问题
- 修复修改注解并热重启后没有生效的问题
- 修复部分类无法注入问题
- 修复PDO模式下,MySQL超时报MySQL server has gone away的问题
性能提升50%,支持连接池负载均衡、事务嵌套
关于此次更新
有一些热心开发者经常问我imi的性能怎么样,稳定性怎么样。由于imi也才刚刚起步,之前并没有对这方面进行测试和优化。
最近一段时间,经过努力,imi 的启动性能、运行性能以及稳定性,全部都有巨大的提升。
针对返回json
的api
环境(无数据库操作)下测试(worker_num=2,并发1000),新版比旧版并发性能提高了50%以上。
下面详细讲解一下,我们所做的工作。
启动性能
在框架初始化完成事件IMI.INITED
中,运行一个imi/buildRuntime
工具进程。
这个工具里面,扫描项目中所有注解,将它们保存到缓存文件中。(对了,现在的imi拥有一个专门用于存放运行时文件的目录,原本零零散散的文件现在都统一了,默认在临时目录,可以通过配置指定。)
然后在Worker
进程中,加载缓存文件,避免重复扫描注解。降低对硬盘读取次数,提高了海量性能!
同样的,在热更新检测到文件更改后,在重启之前,再一次运行imi/buildRuntime
工具,然后再执行重启操作。
这样,在启动项目以及热重启时,节省了毫无价值的多次硬盘读取。
运行性能
首先,imi
的对象代理,使用的是匿名类继承原本的类的方式。在之前的版本中,生成匿名类的过程中,针对所有方法都做了代理。调用任意方法都需要进入imi
的代理方法中进行额外的处理计算。
在最新版的 imi 中,只针对注入了的方法做代理,所以减少了许多不必要的方法调用以及判断处理等,所以运行性能提升巨大。
稳定性
这个就要说到在 imi 中出现过多次的奇怪问题了,在最近终于弄懂,能够确定是 php
本身的 bug
。
我已经把这个bug
反馈给php
了:https://bugs.php.net/bug.php?id=77050
然而其实这个bug
早在2016
年就被人发现,至今没有修复,先吐槽一下……
这个 bug
是使用 eval
实例化匿名类出现的问题,之前说了,imi 的对象代理使用的是匿名类继承原本的类的方式。具体问题这里不再阐述,具体进 bug
反馈页面里看测试代码吧。
后来 imi 使用的是写入文件,然后include的方式来实例化。然而,在一键协程化的支持后,又出现了新的问题。
很难用语言进行描述,总之目前已经完美解决了这个问题。具体解决方式可以查阅BeanFactory.php
的git日志。
更新日志
新增
-
实现连接池负载均衡,模式:轮流、随机
-
新增 AnnotationManager 来进行注解统一管理
-
新增支持 MySQL 事务嵌套
-
新增支持注入带有注解的方法
-
新增日志trace精简配置项(实现性功能)
-
新增项目初始化完毕提示(App Inited)
优化
-
优化对象代理类性能
-
优化事件处理性能
-
将运行时生成的文件统一归类到runtime目录中
-
实现注解缓存机制,减少Worker进程中不必要的文件I/O
-
当启用Session中间件时,只有写入了数据,才会发送SessionID响应头
-
当启用Session中间件时,如果不写入数据,将不再保存(避免正常访问及压测时,写入了过多无意义的数据)
-
调整Worker::getWorkerID()实现方式
-
优化 Imi::getNamespacePath() 方法尽可能返回绝对路径
-
优化池子异常信息
修复
-
修复删除bean类缓存时,未删除文件夹问题
-
解决实例化Bean类相关、一键协程化开启后的问题
-
修复
BeanFactory::newInstance()
可能会引起的问题 -
优化模型提取属性实现方式,解决特殊情况下影响关联的问题
-
修复 AbstractMessage 和 ServerRequest 问题
-
修复模型 Serializable 注解在特定情况下部分失效的问题
-
修复文件日志驱动可能报warning的问题
-
修复特殊情况下注解扫描加载的问题
-
修正注释问题
支持主从,DB及模型大量提升和改进
新增
- 新增支持配置数据库主从连接池,智能选择对应库连接
原连接池名后加.slave即为从库配置,非必设;如果配置了,默认查询走从库,增删改走主库;如果在事务中,默认都走主库
-
新增模型写入数据处理前后事件(
BeforeParseData
、AfterParseData
) -
新增
ModelEvents::AFTER_QUERY
事件监听接口 -
新增支持
ExtractProperty
注解,提取字段中的属性到当前模型 -
新增模型序列化配置注解(
Serializable
、Serializables
) -
新增支持为
Transaction
注解,设定事务类型及是否自动提交事务
Transaction(autoCommit="自动提交事务true/false,默认为true")
事务类型:
事务嵌套(默认)
Transaction(type=TransactionType::NESTING)
该方法必须在事务中被调用
Transaction(type=TransactionType::REQUIREMENT)
如果当前不在事务中则开启事务
Transaction(type=TransactionType::AUTO)
-
新增支持 Swoole Redis 使用
scan object sort migrate hscan sscan zsca
-
新增启动时显示系统、PHP、Swoole、时区信息
-
新增服务启动时显示工作进程数量
优化
-
调整__CLASS__、get_called_class()为面向对象写法
-
EventParam
支持引用传参 -
ModelEvents::AFTER_FIND
事件支持修改model -
增加事务注解处理容错判断
-
新增数据库连接回收时,回滚事务
-
当在模型类中使用
Transaction
注解时,不指定连接池名称,则获取模型连接池名称 -
增加数据库资源open方法返回值
-
优化Db容错
-
调整和优化连接池,现在会抛出获取资源失败的异常
-
调整SQL信息格式
-
新增
IHashCode
、THashCode
,连接池资源用它 -
调整
EventParam
类属性命名,减少冲突可能性 -
调整使用 Redis 的键命名(连接上下文、连接分组、Session)
-
调整连接上下文采用 HASH 存储
-
调整连接分组采用 SET 存储
修复
-
修复模型类非static方法下,调用事件存在的问题
-
修复模型类非static方法下,调用
query()
方法错误的问题 -
修复模型关联更新
orphanRemoval
失效问题 -
修复模型序列化问题
-
修复 IEvent 方法带有 static 的问题
-
修复一处引用返回值潜在问题
不兼容更改
- 调整模型静态方法事件名
原本为
类名事件名
,现在是类名:事件名
- 修正数据库操作 join 方法默认改为 inner join
v0.1.0 正式发布,支持模型多态关联!
值此中秋佳节来临之际,imi 日渐完善,决定提升版本,从v0.0.x
升为v0.1.x
,依旧处于实战开发完善阶段。
祝大家放假快乐!~
新增
-
新增支持模型多态一对一、一对多、多对多
-
新增支持模型关联延迟查询
-
新增支持
@AutoSelect(alwaysShow=false)
用法,可以隐藏序列化后非自动查询的字段
优化
-
格式化代码,使用空格代替制表符
-
使用更优雅的方式实现IMI.APP.INIT事件
-
优化模型生成工具的生成、覆盖、跳过提示
修复
-
修复valid()问题
-
修复部分情况下热更新路径判定错误
新增支持模型关联关系、延迟收包
新增:
-
新增支持模型一对一、一对多、多对多关系(增删改查)
-
新增支持协程Redis延迟收包
-
新增支持协程MySQL延迟收包
-
新增启动工具时输出imi图标
-
新增项目初始化事件(在该时间执行完前,不会处理请求)
-
新增支持数据库查询器setData/setField/setFieldExp/setFieldInc/setFieldDec
优化:
-
优化部分代码
-
补充IQuery接口方法
修复:
-
修复使用容器实例化的类方法,引用返回值报错问题(不支持引用返回,仅解决报错问题)
-
修复获取上传文件没有form字段名称
-
调整getUploadedFiles方法注释中返回类型,支持IDE提示
-
修复ITaskHandler $server类型问题