问题背景
在 webman + Swoole 环境下,当 Worker 进程退出时,ThinkPHP ORM 的 PDOConnection::__destruct() 会触发 Swoole 协程错误(详见 top-think/think-orm#853)。
虽然这是上游 think-orm 的 bug,但 webman 的 think-orm 插件可以在 DbManager 层面提供防御性清理机制。
当前行为
DbManager 使用 Context::onDestroy() 在请求结束时将连接返回连接池:
// vendor/webman/think-orm/src/DbManager.php:76-82
Context::onDestroy(function () use ($connection, $name) {
try {
$connection && static::$pools[$name]->put($connection);
} catch (Throwable) {
// ignore
}
});
但这只处理请求级清理,不处理 Worker 级退出。
建议方案
在 DbManager 中添加静态方法,用于在 Worker 停止前清理所有连接:
/**
* 关闭所有连接池(Worker 停止时调用)
*/
public static function closeAllPools(): void
{
foreach (static::$pools as $name => $pool) {
// 关闭 Context 中持有的连接
$key = "think-orm.connections.$name";
$connection = \Webman\Context::get($key);
if ($connection) {
try {
$connection->close();
} catch (\Throwable $e) {
// ignore
}
\Webman\Context::set($key, null);
}
// 关闭池中的空闲连接
try {
$pool->closeConnections();
} catch (\Throwable $e) {
// ignore
}
}
}
然后在 ThinkOrm bootstrap 类中注册 onWorkerStop 回调:
// vendor/webman/think-orm/src/ThinkOrm.php
public static function start($worker): void
{
// ... 现有初始化代码 ...
if ($worker) {
$worker->onWorkerStop = function () {
DbManager::closeAllPools();
};
}
}
优势
- 集中管理:连接清理逻辑在插件内部,用户无需手动处理
- 防御性编程:即使上游 think-orm 未修复,也能避免错误
- 向后兼容:不影响现有功能,只是增加了 Worker 退出时的清理
环境信息
- PHP: 8.4.22
- Swoole: 6.2.1
- webman: 2.2.1
- webman/think-orm: 2.1.x
- topthink/think-orm: 4.0.51
相关 Issue
问题背景
在 webman + Swoole 环境下,当 Worker 进程退出时,ThinkPHP ORM 的
PDOConnection::__destruct()会触发 Swoole 协程错误(详见 top-think/think-orm#853)。虽然这是上游 think-orm 的 bug,但 webman 的 think-orm 插件可以在
DbManager层面提供防御性清理机制。当前行为
DbManager使用Context::onDestroy()在请求结束时将连接返回连接池:但这只处理请求级清理,不处理 Worker 级退出。
建议方案
在
DbManager中添加静态方法,用于在 Worker 停止前清理所有连接:然后在
ThinkOrmbootstrap 类中注册onWorkerStop回调:优势
环境信息
相关 Issue