22事件管理器,用于管理事件与事件监听器
33"""
44import inspect
5+ import threading
56from collections .abc import Callable
67from dataclasses import dataclass , field
78from typing import Any , TypeVar
89
9- from murainbot .common import save_exc_dump
10- from murainbot .core import ConfigManager
10+ from murainbot .common import exc_logger
1111from murainbot .core .ThreadPool import async_task
1212from murainbot .utils import Logger
1313
1414logger = Logger .get_logger ()
1515
16+ _event_lock = threading .Lock ()
17+
1618
1719class _Event :
1820 """
@@ -34,30 +36,28 @@ def call(self):
3436 """
3537 按优先级顺序同步触发所有监听器
3638 """
37- if self .__class__ in event_listeners :
38- for listener in sorted (event_listeners [self .__class__ ], key = lambda i : i .priority , reverse = True ):
39- try :
40- res = listener .func (self , ** listener .kwargs )
41- except Exception as e :
42- if ConfigManager .GlobalConfig ().debug .save_dump :
43- dump_path = save_exc_dump (f"监听器中发生错误" )
44- else :
45- dump_path = None
46- logger .error (f"监听器中发生错误: { repr (e )} "
47- f"{ f"\n 已保存异常到 { dump_path } " if dump_path else "" } " ,
48- exc_info = True )
49- continue
50- if res is True :
51- return True
52- return False
53- return None
39+ with _event_lock :
40+ if self .__class__ not in event_listeners :
41+ return None
42+
43+ listeners_list = sorted (event_listeners [self .__class__ ], key = lambda i : i .priority , reverse = True )
44+
45+ for listener in listeners_list :
46+ try :
47+ res = listener .func (self , ** listener .kwargs )
48+ except Exception as e :
49+ exc_logger (e , "监听器中发生错误" )
50+ continue
51+ if res is True :
52+ return True
53+ return False
5454
5555
5656T = TypeVar ('T' , bound = '_Event' )
5757
5858
59- # 定义事件监听器的数据类
60- @dataclass (order = True )
59+ # 定义事件监听器的数据类,使用frozen是为了保证数据是只读的来避免可能的线程安全问题
60+ @dataclass (order = True , frozen = True )
6161class EventListener :
6262 """
6363 事件监听器数据类
@@ -91,7 +91,8 @@ def event_listener(event_class: type[T], priority: int = 0, **kwargs):
9191 def wrapper (func : Callable [[T , ...], Any ]):
9292 # 注册事件监听器
9393 listener = EventListener (priority = priority , func = func , kwargs = kwargs )
94- event_listeners .setdefault (event_class , []).append (listener )
94+ with _event_lock :
95+ event_listeners .setdefault (event_class , []).append (listener )
9596 return func
9697
9798 return wrapper
@@ -109,26 +110,25 @@ def unregister_listener(event_class: type[T], func: Callable[[T, ...], Any]):
109110 if not issubclass (event_class , _Event ):
110111 raise TypeError ("event_class 类必须是 _Event 的子类" )
111112
112- listeners_list = event_listeners .get (event_class )
113+ with _event_lock :
114+ listeners_list = event_listeners .get (event_class )
113115
114- if not listeners_list :
115- raise ValueError (f"事件类型 { event_class .__name__ } 没有已注册的监听器。" )
116+ if not listeners_list :
117+ raise ValueError (f"事件类型 { event_class .__name__ } 没有已注册的监听器。" )
116118
117- # 查找所有与给定函数匹配的监听器对象
118- listeners_to_remove = [listener for listener in listeners_list if listener .func == func ]
119+ # 查找所有与给定函数匹配的监听器对象
120+ listeners_to_remove = [listener for listener in listeners_list if listener .func == func ]
119121
120- if not listeners_to_remove :
121- # 如果没有找到匹配的函数
122- raise ValueError (f"未找到函数 { func .__name__ } 对应的监听器,无法为事件 { event_class .__name__ } 注销。" )
122+ if not listeners_to_remove :
123+ # 如果没有找到匹配的函数
124+ raise ValueError (f"未找到函数 { func .__name__ } 对应的监听器,无法为事件 { event_class .__name__ } 注销。" )
123125
124- # 移除所有找到的监听器
125- removed_count = 0
126- for listener_obj in listeners_to_remove :
127- listeners_list .remove (listener_obj )
128- removed_count += 1
126+ # 移除所有找到的监听器
127+ for listener_obj in listeners_to_remove :
128+ listeners_list .remove (listener_obj )
129129
130- if not listeners_list :
131- del event_listeners [event_class ]
130+ if not listeners_list :
131+ del event_listeners [event_class ]
132132
133133
134134class Event (_Event ):
@@ -139,28 +139,29 @@ class Event(_Event):
139139 def _call_hook (self , listener : EventListener ):
140140 return Hook (self , listener ).call ()
141141
142- def call (self ):
142+ def call (self ) -> list [ tuple [ EventListener , Any ]] | None :
143143 """
144144 按优先级顺序同步触发所有监听器
145145 """
146- if self .__class__ in event_listeners :
147- res_list = []
148- for listener in sorted (event_listeners [self .__class__ ], key = lambda i : i .priority , reverse = True ):
149- if self ._call_hook (listener ):
150- logger .debug (f"由 Hook 跳过监听器: { listener .func .__name__ } " )
151- continue
152- try :
153- res = listener .func (self , ** listener .kwargs )
154- except Exception as e :
155- if ConfigManager .GlobalConfig ().debug .save_dump :
156- dump_path = save_exc_dump (f"监听器中发生错误" )
157- else :
158- dump_path = None
159- logger .error (f"监听器中发生错误: { repr (e )} "
160- f"{ f"\n 已保存异常到 { dump_path } " if dump_path else "" } " ,
161- exc_info = True )
162- continue
163- res_list .append (res )
146+ with _event_lock :
147+ if self .__class__ not in event_listeners :
148+ return None
149+
150+ listeners_list = sorted (event_listeners [self .__class__ ], key = lambda i : i .priority , reverse = True )
151+
152+ results = []
153+ for listener in listeners_list :
154+ if self ._call_hook (listener ):
155+ logger .debug (f"由 Hook 跳过监听器: { listener .func .__name__ } " )
156+ continue
157+ try :
158+ res = listener .func (self , ** listener .kwargs )
159+ except Exception as e :
160+ exc_logger (e , "监听器中发生错误" )
161+ continue
162+ results .append ((listener , res ))
163+
164+ return results
164165
165166 @async_task
166167 def call_async (self ):
0 commit comments