事件传播与优先级
当我们有很多handler、command时,很可能有这样的场景
- 我希望实现一个拦截性质的
handler,对事件进行预处理,只有满足要求时,才放行给后续的其他handler处理 - 我希望实现选择性的执行某些
handler,当执行了其中任何一个,就放弃执行其他的handler
接下来,我们将介绍如何实现第一条,第二条如何实现,见权限控制
PepperBot的事件传播机制

当接受到一个事件时,PepperBot会将所有可用的handler、command,按照priority进行排序,priority越大,越靠前
默认情况下,如果没有任何handler、command阻断事件的传播(stop propagation),那么就依次执行
如果有handler、command阻断了事件的传播,那么就不会执行后续的handler、command
但是,有一个前提,就是handler、command必须设置concurrency为False
handler的并发执行
对于大多数的使用场景来说,我们希望handler是并发执行的,这样可以提高性能
如果不并发(也就是顺序执行),会是什么样子呢?
假设我们有一个比较耗时的、并且是阻塞的handler,那么直到这个handler执行完毕,PepperBot才会继续执行后续的handler
如果handler之间并没有逻辑上的联系(也就是说,无所谓执行的先后顺序),那么这样的执行方式,显然会显著的降低响应速度(因为要等待之前的handler执行完毕)
PepperBot如何处理,同时存在并发执行与顺序执行的情况
假设我们有这样几个handler、command
| priority | concurrency | type | name |
|---|---|---|---|
| 500 | True | class_handler | handler1 |
| 400 | True | class_command | command1 |
| 300 | False | class_handler | handler2 |
| 200 | False | class_command | command2 |
| 100 | True | class_handler | handler3 |
| 0 | True | class_command | command3 |

可以看到,handler2、command2是顺序执行的,而其他的handler、command是并发执行的
同时,因为handler1、command1的priority比handler2、command2大,所以handler1、command1会先于handler2、command2执行
因为handler2、command2是非并发的,所以handler3、command3会在handler2、command2执行完毕后,才会执行
或者换句话说,如果在按照priority排序后的handler中,如果存在非并发的handler,则会在执行该handler之前,会等待该handler之前所有的并发handler执行完毕
顺序执行以实现事件传播的控制
只有当一个handler或者command执行完成,我们才能知道,该handler是否阻断了事件的传播
从上图可以看到,handler1、command1是并发执行的,所以假设handler1阻断了事件的传播,因为并发(同时)执行的原因,此时command1已经执行了,所以此时stop propagation并未起效,虽然handler1的优先级比command2的高
但是,对于handler2来说,它是顺序执行的,所以在handler2执行之前,会等待handler1执行完毕,此时,如果handler1阻断了事件的传播,那么handler2就不会执行了
所以总结一下,如果我们希望实现事件传播的控制,那么我们可以将handler、command设置为顺序执行,这样就可以在handler、command执行完毕后,知道是否阻断了事件的传播
通过对传播进行分组,避免干扰
回到我们一开始假设的场景
我希望实现一个拦截性质的
handler,对事件进行预处理,只有满足要求时,才放行给后续的其他handler处理
如果我的这个拦截handler,只想作用于后续的handler2,而完全不关心其他的handler
假设此时拦截handler阻断了传播,虽然确实实现了拦截handler2的执行,但是同时,也影响了其他的handler
那么,我们可以通过对传播进行分组,来避免这种干扰

现在,当拦截handler阻断了传播时,只会影响同一个传播组中的handler2,而不会影响到其他传播组
多个传播组之间,既然没有了逻辑上的联系,自然也是并发执行的
具体如何设置
priority默认为0concurrency默认为Truepropagation_group默认为default
设置class_handler
from pepperbot.store.event import PropagationConfig
class MyHandler:
config = PropagationConfig(
priority=100,
concurrency=False,
propagation_group="test",
)
async def group_message(self, ...):
...
设置class_command
@as_command(
...
priority=100,
concurrency=False,
propagation_group="test",
)
class MyCommand:
...