feat: avoid disorder by producer-consumer model

This commit is contained in:
lanvent
2023-04-04 05:18:09 +08:00
parent 7458a6298f
commit 5a221848e9
3 changed files with 81 additions and 27 deletions

View File

@@ -5,6 +5,7 @@ wechat channel
"""
import os
import threading
import requests
import io
import time
@@ -17,18 +18,10 @@ from lib import itchat
from lib.itchat.content import *
from bridge.reply import *
from bridge.context import *
from concurrent.futures import ThreadPoolExecutor
from config import conf
from common.time_check import time_checker
from common.expired_dict import ExpiredDict
from plugins import *
thread_pool = ThreadPoolExecutor(max_workers=8)
def thread_pool_callback(worker):
worker_exception = worker.exception()
if worker_exception:
logger.exception("Worker return exception: {}".format(worker_exception))
@itchat.msg_register(TEXT)
def handler_single_msg(msg):
@@ -73,7 +66,9 @@ def qrCallback(uuid,status,qrcode):
try:
from PIL import Image
img = Image.open(io.BytesIO(qrcode))
thread_pool.submit(img.show,"QRCode")
_thread = threading.Thread(target=img.show, args=("QRCode",))
_thread.setDaemon(True)
_thread.start()
except Exception as e:
pass
@@ -142,7 +137,7 @@ class WechatChannel(ChatChannel):
logger.debug("[WX]receive voice msg: {}".format(cmsg.content))
context = self._compose_context(ContextType.VOICE, cmsg.content, isgroup=False, msg=cmsg)
if context:
thread_pool.submit(self._handle, context).add_done_callback(thread_pool_callback)
self.produce(context)
@time_checker
@_check
@@ -150,7 +145,7 @@ class WechatChannel(ChatChannel):
logger.debug("[WX]receive text msg: {}, cmsg={}".format(json.dumps(cmsg._rawmsg, ensure_ascii=False), cmsg))
context = self._compose_context(ContextType.TEXT, cmsg.content, isgroup=False, msg=cmsg)
if context:
thread_pool.submit(self._handle, context).add_done_callback(thread_pool_callback)
self.produce(context)
@time_checker
@_check
@@ -158,7 +153,7 @@ class WechatChannel(ChatChannel):
logger.debug("[WX]receive group msg: {}, cmsg={}".format(json.dumps(cmsg._rawmsg, ensure_ascii=False), cmsg))
context = self._compose_context(ContextType.TEXT, cmsg.content, isgroup=True, msg=cmsg)
if context:
thread_pool.submit(self._handle, context).add_done_callback(thread_pool_callback)
self.produce(context)
@time_checker
@_check
@@ -168,7 +163,7 @@ class WechatChannel(ChatChannel):
logger.debug("[WX]receive voice for group msg: {}".format(cmsg.content))
context = self._compose_context(ContextType.VOICE, cmsg.content, isgroup=True, msg=cmsg)
if context:
thread_pool.submit(self._handle, context).add_done_callback(thread_pool_callback)
self.produce(context)
# 统一的发送函数每个Channel自行实现根据reply的type字段发送不同类型的消息
def send(self, reply: Reply, context: Context):

View File

@@ -5,7 +5,6 @@ wechaty channel
Python Wechaty - https://github.com/wechaty/python-wechaty
"""
import base64
from concurrent.futures import ThreadPoolExecutor
import os
import time
import asyncio
@@ -18,21 +17,18 @@ from bridge.context import *
from channel.chat_channel import ChatChannel
from channel.wechat.wechaty_message import WechatyMessage
from common.log import logger
from common.singleton import singleton
from config import conf
try:
from voice.audio_convert import any_to_sil
except Exception as e:
pass
thread_pool = ThreadPoolExecutor(max_workers=8)
def thread_pool_callback(worker):
worker_exception = worker.exception()
if worker_exception:
logger.exception("Worker return exception: {}".format(worker_exception))
@singleton
class WechatyChannel(ChatChannel):
def __init__(self):
pass
super().__init__()
def startup(self):
config = conf()
@@ -41,6 +37,10 @@ class WechatyChannel(ChatChannel):
asyncio.run(self.main())
async def main(self):
loop = asyncio.get_event_loop()
#将asyncio的loop传入处理线程
self.handler_pool._initializer= lambda: asyncio.set_event_loop(loop)
self.bot = Wechaty()
self.bot.on('login', self.on_login)
self.bot.on('message', self.on_message)
@@ -122,8 +122,4 @@ class WechatyChannel(ChatChannel):
context = self._compose_context(ctype, cmsg.content, isgroup=isgroup, msg=cmsg)
if context:
logger.info('[WX] receiveMsg={}, context={}'.format(cmsg, context))
thread_pool.submit(self._handle_loop, context, asyncio.get_event_loop()).add_done_callback(thread_pool_callback)
def _handle_loop(self,context,loop):
asyncio.set_event_loop(loop)
self._handle(context)
self.produce(context)