easy-swoole / orm

31 stars 27 forks source link

重写AbstractModel中的schemaInfo会导致gone way? #216

Closed it-gan closed 2 years ago

it-gan commented 2 years ago

easyswoole框架版本号、orm组件版本号 [Version]

easyswoole: 3.4.6 orm:1.5.2

问题描述和截图 [Question]

前提条件:数据库连接wait_timeout设置了90秒,一个自定义进程读取redis数据。

封装了一个数据库基类(继承AbstractModel),然后一个普通model继承它($tableName没有指定),是通过重写基类schemaInfo读取表名的。会出现gone way? 但是如果把model中的$tableName指定了就不再出现。这是什么操作?

图片

排查情况和最小复现脚本 [Tests and Recurrence]

是否第一次获取表的schema信息,将连接defer了,后面不可以使用了?

CoreModel.php

<?php

namespace App\Model\Bad;

use EasySwoole\ORM\AbstractModel;
use EasySwoole\EasySwoole\Config;
use EasySwoole\ORM\Utility\Schema\Table;
use Illuminate\Support\Str;

class CoreModel extends AbstractModel
{
    public function schemaInfo(bool $isCache = true): Table
    {
        // 根据模型名称生成表名称
        $prefix          = Config::getInstance()->getConf('DB')['prefix'];
        $name            = preg_replace('/\\\\/', '/', get_class($this));
        $this->tableName = Str::snake(basename($name));
        if (!Str::startsWith($this->tableName, $prefix) && $prefix) {
            $this->tableName = $prefix . $this->tableName;
        }
        return parent::schemaInfo($isCache);
    }
}

Canteen.php

<?php

namespace App\Model\Bad;

class Canteen extends CoreModel
{
//    protected $tableName = "rx_canteen";
}

DBProcess.php

<?php

namespace App\Process;

use App\Model\Bad\Canteen;
use EasySwoole\Component\Process\AbstractProcess;
use EasySwoole\EasySwoole\Logger;
use EasySwoole\Redis\Redis as ESRedis;
use EasySwoole\RedisPool\RedisPool;
use Swoole\Coroutine;

class DBProcess extends AbstractProcess
{
    protected function run($arg)
    {
        while (1) {
            try {
                $data = self::rPop("db:test");
                if (empty($data)) {
                    Coroutine::sleep(3);
                    continue;
                } else {
                    $rt = self::generalModel($data);
                    Logger::getInstance()->log("DBProcess 执行成功--->" . json_encode($rt) . PHP_EOL);
                    Coroutine::sleep(1);
                }
            } catch (\Throwable $e) {
                Logger::getInstance()->log("DBProcess Throwable--->" . $e->getMessage() . $e->getTraceAsString() . $e->getFile() . $e->getLine() . PHP_EOL);
            }
        }
    }

    private static function generalModel($id = 5)
    {
        return Canteen::create()->where(["id" => $id])->field("id,name")->get();
    }

    public static function rPop($key, $num = 1)
    {
        return RedisPool::invoke(function (ESRedis $redis) use ($key, $num) {
            if ($num == 1) {
                return $redis->rPop($key);
            } else {
                $redis->startPipe();
                $redis->lRange($key, 0, $num - 1);
                $redis->lTrim($key, $num, -1);
                return $redis->execPipe();
            }
        });
    }
}