Quan666 / ELF_RSS

QQ机器人 RSS订阅 插件,订阅源建议选择 RSSHub
https://myelf.club/archives/221
GNU General Public License v3.0
539 stars 53 forks source link

当转发消息很多(27条)时,合并转发消息不会返回,导致数据库无法更新,最终导致一直重复推送相同内容 #414

Closed fkcptlst closed 1 year ago

fkcptlst commented 1 year ago

ELF_RSS 、 go-cqhttp 、 nonebot 、 Python 版本及操作系统

ELF_RSS: 2.6.17 go-cqhttp: rc5 nonebot2: 2.0.0rc3 python: 3.10.8 OS: ubuntu 20.04

列出安装的 Python 包

No response

如何复现

  1. 订阅一个经常推送的源,比如p站ai日榜:/pixiv/ranking/day_ai
  2. 设置forward=1
  3. 等待它推送、如果一次性转发超过27条就会出现上述问题。(更少估计也行,比如20条)

期望行为

转发一次即可。不会重复转发。

实际行为

一直重复转发(发了又发)

根据我昨天debug的结果,我发现在after_handler调用send_message.py: send_msgs_with_lock后就被阻塞了,后续的写数据库过程没被执行。

确切的说,是在调用send_message.py: send_msgs_with_lock: await bot.send_forward_msg后就被阻塞了(或者掐掉了)。在此之前的语句应该都能被正常执行。在此之后的语句都没有被执行。

NekoAria commented 1 year ago

我没办法复现,你能贴一下相关的日志或者截图吗?

fkcptlst commented 1 year ago

由于RSS更新不可控,因此需要手动模拟一下大批量更新的情况。

步骤:

  1. 订阅一个rss源,以pixiv的ai日排行榜为例:/pixiv/ranking/day_ai
  2. 设置forward=1
  3. 等第一次更新成功护,修改数据库的json文件: a. 修改rss.json,将last_modified改为一天前以确保能触发更新检查 b. 修改新订阅的rss源的json(pixiv日榜ai.json),删除25条entries(如果更多会导致cqhttp转发失败: cqhttp:
    [2023-04-02 12:52:09] [WARNING]: 警告: 合并转发 123456789 图片上传失败: upload failed: write conn error: writev tcp 10.0.16.15:58476->183.2.143.16:8080: writev: broken pipe

    nonebot2:

    ...
    04-02 13:01:34 [DEBUG] ELF_RSS2 | Resize image to: 1080 x 1440
    04-02 13:01:35 [DEBUG] ELF_RSS2 | Resize image to: 1368 x 2048
    04-02 13:02:26 [DEBUG] nonebot | OneBot V11 | Calling API send_group_msg
    04-02 13:02:26 [ERROR] ELF_RSS2 | pixiv日榜ai 检查更新超时,结束此次任务!
  4. 检查数据库的json文件,可以发现rss.jsonlast_modified更新了,但是pixiv日榜ai.json并没有更新(条目数比删除前的要少)

后果:

下一次推送时会将上一次的内容一并推送(因为数据库中没有记录相应的entries),而上一次没成功的话下一次也大概率不会成功,导致数据库未记录的entry越积越多,陷入恶性循环。

建议:

  1. 无论发送成功与否,都在数据库中添加相应的entry,增加两个column分别记录“成功发送与否”和“attempt次数”,attempt次数在每次尝试向qq推送时自增1,超过一定阈值则将“成功发送”标志位设置为True,避免过度重复尝试,陷入恶性循环。
  2. 对于过大的转发消息,建议分成多条进行合并转发,每一个转发稍微短一点,提高成功率
NekoAria commented 1 year ago

事实上之前没支持合并转发之前是每条消息独立的,发送失败一次就会录入缓存,同时有个字段表示发送失败, 如果下次检查更新还是失败,就去掉那个字段当作已经发送成功了。 为了避免漏消息,发送失败的同时,会尝试发送只带消息链接的简短消息。 为了支持合并转发消息,在没解决原有的解析处理逻辑设计问题 (屎山) 的情况下,简单的把检查更新的队列当成一个整体处理了。

我想如果简单分组成最多 10 条消息,可能就能解决这个问题了。 不过这还涉及到超时的问题,可能还需要再多加测试,然后再针对性地改一改。

NekoAria commented 1 year ago

说实话我实在是不推荐订阅 P 站的同时还启用合并转发,因为本来单张图片就很大的情况下,一条消息发送出来都需要很久的情况下,合并转发很可能超时,并不能很好判断是否发送成功。 有时候返回网络错误,但是过一会儿又发送成功。 合并转发还有个问题就是,有可能吞图,估计是风控。

fkcptlst commented 1 year ago

说实话我实在是不推荐订阅 P 站的同时还启用合并转发,因为本来单张图片就很大的情况下,一条消息发送出来都需要很久的情况下,合并转发很可能超时,并不能很好判断是否发送成功。 有时候返回网络错误,但是过一会儿又发送成功。 合并转发还有个问题就是,有可能吞图,估计是风控。

其实吞图我觉得问题不大,主要是如果发送失败会一直重复推送,这个是比较致命的。

NekoAria commented 1 year ago

请你帮助测试这个 commit : cb686598