Skip to content

关于V2版本内部LightCacheInside存储数据使用数组方式存在数据不同步的问题 #277

@YiwanGi

Description

@YiwanGi

受影响版本

2.8.6

描述

参考内部代码 CoMessage.php fun>>>yieldByWS

        $cid = Coroutine::getuid();
        $api_id = ZMAtomic::get('wait_msg_id')->add(1);
        $hang['compare'] = $compare;
        $hang['coroutine'] = $cid;
        $hang['worker_id'] = server()->worker_id;
        $hang['result'] = null;
        SpinLock::lock('wait_api');
        $wait = LightCacheInside::get('wait_api', 'wait_api');
        $wait[$api_id] = $hang;
        LightCacheInside::set('wait_api', 'wait_api', $wait);
        SpinLock::unlock('wait_api');
        $id = swoole_timer_after($timeout * 1000, function () use ($api_id) {
            $r = LightCacheInside::get('wait_api', 'wait_api')[$api_id] ?? null;
            if (is_array($r)) {
                Coroutine::resume($r['coroutine']);
            }
        });
        Coroutine::suspend();
        SpinLock::lock('wait_api');
        $sess = LightCacheInside::get('wait_api', 'wait_api');
        $result = $sess[$api_id]['result'] ?? null;
        unset($sess[$api_id]);
        LightCacheInside::set('wait_api', 'wait_api', $sess);
        SpinLock::unlock('wait_api');
        swoole_timer_clear($id);
        if ($result === null) {
            return false;
        }
        return $result;

由于内部采用 $wait[$api_id] 方式进行存取值 在协程高频情况下 可能会存在丢失部分消息回执的情况(例如go()多机器人调用api,或多机器人群发消息等情况。参见复现方式)

该缓存类使用的是swoole的Table方式 参见官方文档 也警告不要使用数组方式存取数据
该内部类方法在多处均有使用 可能需要修改多处代码 TODO

复现步骤

        $all = OneBotV11::getAllRobot();
        foreach ($all as $bot) {
            $list = $bot->getGroupList();
            if ($list === false) {
                Console::error('群列表获取失败');
            }
            foreach ($list['data'] ?? [] as $group) {
                $rt = $bot->setPrefix(OneBotV11::API_ASYNC)->sendGroupMsg($group['group_id'],'test');
            }
        }

封装该群发消息,在多处使用,高频情况下获取群列表可能出现返回false

解决方案

内部缓存使用swoole的Table应避免使用数组方式读写数据,修改局部应用代码为独立Table表 并使用$api_id(参考)为key。

附加信息

No response

Metadata

Metadata

Assignees

Labels

2.x issue这是一个 2.x 版本的问题bug意外行为或意外问题

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions