北大侠客行MUD论坛

 找回密码
 注册
搜索
热搜: 新手 wiki 升级
查看: 1044|回复: 10

【mudlet】事件系统设计

[复制链接]
发表于 2024-8-28 11:00:59 | 显示全部楼层 |阅读模式
本帖最后由 yisr 于 2024-9-5 07:34 PM 编辑

背景:
在 Mudlet 社区,有两篇文章引发了我对事件系统改进的思考:

1. 杰哥的吐槽帖: 他对 Mudlet 原生事件系统的不足之处进行了批评。
   链接: https://www.pkuxkx.net/forum/thread-49239-1-1.html

2. Paotin++ 的入门系列: 他详细介绍了更高级的事件系统设计。
   链接: https://www.pkuxkx.net/forum/thread-49406-1-1.html

这些内容让我意识到,Mudlet 目前的事件系统存在一些无法满足复杂需求的局限性。

问题分析:
Mudlet 自带的事件系统非常基础,主要通过两个函数 registerAnonymousEventHandler 和 registerNamedEventHandler 来注册事件。然而,这些函数的功能非常有限,难以应对复杂的事件场景。例如:

- 你可以分别注册两个事件处理器,一个用于在“系统下载完成”时播放音乐,另一个用于播放动画。
- 但当你希望在某个时刻仅播放音乐而不播放动画时,Mudlet 无法直接处理。你需要额外的逻辑来暂时禁用动画播放的事件处理器。
- 更复杂的是,如果你在另一个场景中又需要播放动画,由于之前禁用了它,它将不会被触发。这导致事件处理逻辑变得混乱且难以管理。

此外,这两个函数还无法对特定的文本行(如触发器匹配的行)进行事件注册,这进一步限制了事件系统的灵活性。

设计目标:
为了解决这些问题,我计划设计一个更强大的事件系统,使 Mudlet 能够更灵活地处理复杂的事件逻辑。
======================================================================================================================
为了更好地理解事件机制,我们可以通过一个生活中的类比来解释其原理:以招聘为例,涉及到三个主要角色:单位、人才市场和应聘者。

类比解释:
单位相当于需要发布任务的一方,他们有明确的用人需求,但不能直接与应聘者联系。应聘者则是拥有特定技能的人,他们也无法直接与单位联系。两者之间的连接必须通过人才市场来实现。

- 单位发布招聘信息: 每个单位根据自己的用人需求,在人才市场发布招聘信息,列出需要的技能或能力。可以有选择的指定在哪些人中挑选。也可以有选择的指定招聘人数。
- 应聘者登记信息: 应聘者在人才市场登记自己的技能和求职意向。可以有选择的指定在哪些单位里面挑选。也可以有选择的指定需要挑选出几个单位。
- 人才市场匹配: 人才市场会根据双方提供的信息进行匹配。然后进入下一步的执行阶段。

在这个事件机制的类比中:
- 单位的招聘信息相当于任务的发布。
- 应聘者的登记相当于事件的监听。
- 人才市场则是匹配任务和监听的中心。它根据特定的触发条件来执行匹配。然后进入下一步的执行阶段。
在这个事件当中,所有模块都是独立运作的。不会出现各模块相互干扰和冲突的情况。
======================================================================================================================
这是一份全新设计的任务管理系统框架,涵盖了从任务发布到实时监控的各个方面,确保系统的扩展性、灵活性和可维护性。下面是详细的系统模块概述和设计理念:

系统模块概述

一、任务管理模块 (TaskManager)

1. 任务管理操作
   包括任务的创建、更新、删除和查询,这些功能都是围绕对任务的直接操作进行的。
   - 任务创建: 提供接口允许用户创建新任务,并设置任务的各种属性(任务ID、任务名称、优先级、执行次数限制、监听者限制、触发名列表、函数名列表、任务依赖关系等)。
   - 任务更新: 允许用户更新已存在的任务属性(如任务名、优先级、执行次数限制、监听者列表、触发名列表、函数名列表等),并重新评估任务状态和依赖关系。
   - 任务删除: 允许用户删除指定任务,并处理可能存在的依赖关系。
   - 任务查询: 提供接口允许用户根据任务ID、状态、优先级、发布人姓名或其他属性查询任务,支持单个任务查询和批量查询。

2. 任务执行与状态管理
   将任务的执行过程、生命周期管理和状态监控相关功能合并在一起,集中处理任务的执行和状态变更。
   - 任务执行与生命周期管理: 控制任务的执行过程,追踪执行次数,并在任务完成或达到执行次数限制时更新任务状态。支持监听者执行任务,并记录执行历史。
   - 状态管理: 监控和更新任务状态,包括未开始、进行中、完成、挂起等,确保任务在正确的状态下执行。

3. 任务依赖与协调
   将任务依赖管理和任务之间的通信与协调功能合并,用于处理任务之间的依赖关系和交互。
   - 任务依赖管理: 管理任务之间的依赖关系,确保任务按顺序正确执行。包括构建任务依赖图、检查依赖任务是否完成,以及检测循环依赖问题。
   - 任务之间的通信与协调: 支持任务之间的数据交换和协作执行,通过消息队列、事件通知、共享内存等机制,实现任务间的实时通信与协调。

4. 历史记录与优化
   将历史记录管理与存储查询效率的优化功能合并,集中处理与任务执行记录相关的功能。
   - 历史记录管理: 保存任务的历史执行记录,包括每次任务执行的时间、执行结果等信息,便于后续查询和分析。
   - 历史记录的存储与查询效率: 优化历史记录的存储方式,通过归档旧记录或分区存储提升存储效率,并采用索引或优化查询策略,确保高效查询历史记录。

5. 模块化与扩展性
   单独列出系统的模块化设计和扩展性功能,以便系统能够灵活应对未来的需求变化。
   - 扩展性与模块化: 采用模块化设计,使各功能模块能够独立开发、测试和部署。支持插件式架构,实现功能的动态加载和扩展,提升系统的可扩展性和维护性。

二、监听者管理模块 (ListenerManager)

1. 监听者管理操作
   包括监听者的注册、更新、删除和查询,这些功能都是围绕对监听者的直接操作进行的。
   - 监听者注册: 提供接口允许监听者在系统中注册,并定义其能力、可接取的任务类型和触发名。
   - 监听者更新: 允许用户更新已注册的监听者属性(如能力、可接取的任务类型、触发名等),并重新评估监听者的匹配任务范围。
   - 监听者删除: 允许用户删除指定监听者,并处理与其相关的任务分配或依赖关系。
   - 监听者查询: 提供接口允许用户根据监听者ID、状态或能力查询监听者信息,支持单个监听者查询和批量查询。

2. 监听者执行与状态管理
   将监听者的任务接取过程、生命周期管理和状态监控相关功能合并在一起,集中处理监听者的执行情况和状态变更。
   - 监听者执行与生命周期管理: 追踪监听者的任务接取情况,控制监听者的生命周期,包括接取任务次数限制、任务完成后的状态变更或移除。支持任务分配给监听者,并记录每次任务的接取和执行历史。
   - 状态管理: 监控和更新监听者的状态,包括在线、离线、忙碌等,确保监听者在正确的状态下接取任务并执行。

3. 任务分配与协调
   将监听者的负载管理和任务之间的协调功能合并,用于处理监听者的任务分配和任务之间的交互。
   - 负载管理: 实时监控监听者的任务负载,确保任务分配的均衡性,避免监听者超负荷工作。系统根据监听者的当前负载动态调整任务分配策略。
   - 任务与监听者之间的通信与协调: 支持任务与监听者之间的数据交换和协作执行,通过消息队列、事件通知、共享内存等机制,实现任务与监听者间的实时通信与协调。

4. 历史记录与优化
   将监听者的历史记录管理与存储查询效率的优化功能合并,集中处理与监听者任务接取和执行记录相关的功能。
   - 历史记录管理: 保存监听者的任务接取与执行历史,包括每次任务接取的时间、执行结果等信息,便于后续查询和分析。
   - 历史记录的存储与查询效率: 优化历史记录的存储方式,通过归档旧记录或分区存储提升存储效率,并采用索引或优化查询策略,确保高效查询监听者的历史记录。

5. 模块化与扩展性
   单独列出系统的模块化设计和扩展性功能,以便系统能够灵活应对未来的需求变化。
   - 扩展性与模块化: 采用模块化设计,使各功能模块能够独立开发、测试和部署。支持插件式架构,实现功能的动态加载和扩展,提升系统的可扩展性和维护性。

三、触发和函数管理模块 (TriggerFunctionManager)

1. 触发名和函数名管理
   包括触发名和函数名的定义、更新和删除,这些功能都是围绕对触发名和函数名的直接管理操作进行的。
   - 触发名管理: 统一定义和管理系统中的触发名,确保所有触发名在系统中唯一且一致。为任务和监听者模块提供接口,便于它们使用这些触发名。
   - 函数名管理: 统一定义和管理系统中的函数名,确保系统中所有函数调用的一致性和正确性。
   - 触发名和函数名更新: 允许更新已有的触发名和函数名信息,如名称、描述等,并根据需要进行验证和调整。
   - 触发名和函数名删除: 允许删除不再使用或重复定义的触发名和函数名,并确保相关依赖关系得到正确处理。

2. 自动补全和验证
   将自动补全和验证功能合并在一起,集中处理触发名和函数名的输入校验与辅助功能。
   - 自动补全: 提供接口支持触发名和函数名的自动补全功能,帮助用户快速输入和选择正确的名称,减少输入错误。
   - 验证: 验证用户输入的触发名和函数名是否存在于系统中,防止误输入或使用未定义的名称。验证接口在任务或监听者模块调用触发名或函数名时进行检查,确保其合法性。

3. 查询与配置支持
   将触发名和函数名的查询功能合并,用于支持用户和系统模块的配置需求。
   - 触发名查询: 提供接口允许用户或系统模块查询现有的触发名,便于配置任务和监听者。
   - 函数名查询: 提供接口允许用户或系统模块查询现有的函数名,确保函数调用的准确性。
   - 配置支持: 根据查询结果提供详细信息,支持任务和监听者模块对触发名和函数名的正确配置。

4. 模块化与扩展性
   单独列出系统的模块化设计和扩展性功能,以便系统能够灵活应对未来的需求变化。
   - 扩展性与模块化: 采用模块化设计,使触发名和函数名的管理能够独立开发、测试和部署。系统支持插件式架构,实现功能的动态加载和扩展,提升系统的可扩展性和维护性。


四. 匹配与分配模块 (Matcher)

功能:

- 任务与监听者匹配: 基于任务的要求和监听者的能力、负载情况,进行自动匹配,并生成任务-监听者的配对方案。
- 匹配规则与优先级: 支持复杂的匹配规则和优先级管理,确保关键任务优先得到匹配。
- 负载均衡: 根据监听者的当前负载情况,智能调度任务,避免某些监听者过载或闲置。
- 任务调度策略: 支持多种任务调度策略(如先来先服务、优先级队列等),根据实际需求灵活调整。

优势:

- 提供智能化的匹配与分配机制,支持多样化的匹配规则和调度策略。
- 确保系统资源的高效利用,避免过载和资源浪费。

5. 日志与历史记录模块 (LogManager)

功能:

- 操作日志记录: 记录系统中的所有关键操作,包括任务创建、分配、执行等,提供全面的操作日志。
- 历史记录存储: 将任务和监听者的执行历史记录保存到数据库中,便于后续查询和分析。
- 日志查询与分析: 提供接口支持日志的按需查询,并支持基于时间、任务、监听者等维度的分析功能。
- 调试与审计: 为系统管理员提供调试与审计工具,通过查询和分析日志,排查问题并优化系统性能。

优势:

- 详细的日志记录和历史存储,有助于系统的回溯、调试和优化。
- 支持多维度的日志查询与分析,提升系统的可监控性和可审计性。

6. 实时监控模块 (RealTimeMonitor)

功能:

- 任务榜单: 实时显示系统中的任务状态,包括活跃任务、待处理任务、完成任务等,并支持按优先级、状态等筛选和排序。
- 监听者榜单: 实时显示监听者的状态和负载情况,支持按负载、状态等维度筛选和排序。
- 状态筛选与排序: 支持对任务和监听者的状态进行筛选和排序,便于用户快速找到所需信息。
- 搜索功能: 提供任务和监听者的搜索功能,支持基于关键字的快速查询。
- 实时刷新: 系统自动刷新任务和监听者榜单,确保显示数据的实时性。

优势:

- 提供全面的系统监控功能,实时跟踪任务和监听者的状态。
- 支持多种筛选、排序和搜索功能,帮助用户快速获取所需信息。

总结:

这个全新的任务管理系统框架设计,涵盖了从任务发布、监听者管理到匹配分配、日志记录和实时监控的完整工作流程。各个模块各司其职,通过统一接口和数据结构实现模块间的有效协作。系统设计的核心理念是扩展性、灵活性和可维护性,确保系统能够适应不同规模和复杂度的任务管理需求。

通过这样的设计,系统不仅能高效管理任务和监听者,还能在动态环境中保持高度的响应能力和可靠性,适用于广泛的应用场景,如事件驱动的自动化系统、复杂任务调度平台等。
======================================================================================================================
数据表结构设计

2.1. 任务发布表结构 (TaskTable)

- 任务ID (TaskID):唯一标识任务的ID(自动生成)。
- 发布人姓名 (PublisherName):任务发布者的姓名(默认为角色ID)。
- 任务名 (TaskName):任务的名称,描述任务的目的或内容。
- 触发名列表 (TriggerNames):任务可由哪些触发名进行激活(数组或列表形式)。
- 函数名列表 (FunctionNames):任务需要执行的功能列表,定义任务的具体执行操作(数组或列表形式)。
- 任务优先级 (Priority):任务的优先级,用于任务调度和排序(默认为1,数字越小优先级越高)。
- 可执行次数 (ExecutionLimit):任务可以被执行的最大次数,限制任务的重复执行次数(默认1次)。
- 监听者限制列表 (ListenerNames):指定哪些监听者可以接取此任务(数组或列表形式,默认为所有监听者)。
- 前置任务 (PreviousTaskID):此任务依赖的前一个任务的ID,必须先完成前置任务才能执行当前任务。
- 后续任务 (NextTaskID):此任务的后一个任务的ID,当前任务完成后触发后续任务的执行。
- 任务状态 (Status):任务的当前状态(如"活跃"、"挂起"、"完成"等)。
- 创建时间 (CreatedAt):任务的创建时间,记录任务的生成时间戳。
- 历史记录 (History):任务的历史执行记录,存储任务的执行过程、结果和状态变化。

2.2. 监听者登记表结构 (ListenerTable)

- 登记人姓名 (RegistrarName):登记监听者信息的人员姓名(默认为角色ID)。
- 监听者ID (ListenerID):唯一标识监听者的ID(自动生成)。
- 监听者姓名 (ListenerName):监听者的姓名,标识监听者的唯一名称。
- 触发名列表 (TriggerNames):监听者可由哪些触发名激活,表示监听者监听的触发事件(数组或列表形式)。
- 函数名列表 (FunctionNames):监听者可以执行的功能列表,指定监听者具备的能力(数组或列表形式)。
- 任务接取列表 (TaskNames):监听者可接取的任务列表,指定监听者可以接取的任务范围(数组或列表形式,默认为所有任务)。
- 可接任务次数 (TaskLimit):监听者可以接取任务的次数限制,math.huge表示无限次数(默认为无穷大)。
- 当前负载 (CurrentLoad):监听者当前正在处理的任务负载,表示监听者当前正在进行的任务数量(默认为0)。
- 监听者状态 (Status):监听者的当前状态(如“活跃”、“挂起”等)。
- 注册时间 (RegisteredAt):监听者注册系统的时间,表示监听者信息被登记的时间戳。
- 历史记录 (History):监听者的任务接取与执行记录,记录监听者的任务历史及执行详情(文本或JSON格式存储)。

2.3. 触发名管理表结构 (TriggerTable)
- 触发名ID (TriggerID):唯一标识触发名的ID。
- 触发名 (TriggerName):触发事件的名称。
- 描述 (Description):对触发名的描述。
- 创建时间 (CreatedAt):触发名记录的创建时间。

2.4. 触发事件管理表结构 (TriggerEventTable)
- 触发事件ID (EventID):唯一标识触发事件的ID。
- 触发名ID (TriggerID):关联的触发名ID,外键链接到 TriggerTable。
- 触发事件 (EventName):具体的触发事件名称。
- 条件 (Condition):触发事件的具体条件或描述。
- 创建时间 (CreatedAt):触发事件记录的创建时间。

2.5. 函数名管理表结构 (FunctionTable)
- 函数名ID (FunctionID):唯一标识函数名的ID。
- 函数名 (FunctionName):系统中注册的函数名称。
- 描述 (Description):对函数名的描述。
- 创建时间 (CreatedAt):函数名记录的创建时间。

2.6. 具体函数管理表结构 (SpecificFunctionTable)
- 具体函数ID (SpecificFunctionID):唯一标识具体函数的ID。
- 函数名ID (FunctionID):关联的函数名ID,外键链接到 FunctionTable。
- 具体函数名称 (SpecificFunctionName):具体函数名称。
- 执行逻辑 (ExecutionLogic):具体函数的执行逻辑或脚本。
- 创建时间 (CreatedAt):具体函数记录的创建时间。

2.7. 实时任务榜表结构 (BoardTable)
- 实时任务榜ID (BoardTableID):指定我要使用哪一个实时任务榜。
- 任务 (TaskID):关联的任务,从数据库中读取TaskTable到BoardTable中。
- 监听者 (Listener):关联的监听者,从数据库中读取 ListenerTable到BoardTable中。
======================================================================================================================
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2024-8-28 11:04:41 | 显示全部楼层
本帖最后由 dtp 于 2024-8-28 11:06 AM 编辑

不想执行你注册它干嘛。真是的。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2024-8-28 11:08:45 | 显示全部楼层
本帖最后由 yisr 于 2024-8-28 11:09 AM 编辑
dtp 发表于 2024-8-28 11:04 AM
不想执行你注册它干嘛。真是的。

因为有些地方需要同时执行"播放音乐"和"播放动画"。
而有些地方只需要执行"播放音乐"。
所有都要注册,但是并不需要都要执行。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2024-8-28 11:11:01 | 显示全部楼层
1.

lua版本的事件机制,可以参考:

https://www.pkuxkx.net/forum/thread-49068-2-1.html

2.

你需要的是实现一个状态机的模式

不同状态下对不同事件用不同的代码进行处理

参考

https://www.pkuxkx.net/forum/thread-48864-1-1.html

里的8楼

最简单的话,就是维护一个table,事件名和对应的处理函数。


北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2024-8-28 14:13:28 | 显示全部楼层
[quote]yisr 发表于 2024-8-28 11:08 AM
因为有些地方需要同时执行

把播放音乐和播放动画扔进一个带有逻辑判断的函数,然后注册这个函数,在下载完成的时候执行从而判断需要播放什么,就行了。
不需要把问题复杂化。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2024-8-28 14:14:57 | 显示全部楼层
sulryn 发表于 2024-8-28 02:13 PM
[quote]yisr 发表于 2024-8-28 11:08 AM
因为有些地方需要同时执行

这样做到后面容易更复杂。

控制权太底层了。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2024-8-28 14:24:23 | 显示全部楼层
jarlyyn 发表于 2024-8-28 02:14 PM
这样做到后面容易更复杂。

控制权太底层了。

我会选择以后再考虑!先简单处理掉就行!
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2024-8-28 15:01:07 | 显示全部楼层
jarlyyn 发表于 2024-8-28 02:14 PM
这样做到后面容易更复杂。

控制权太底层了。

感谢杰哥!!!
把我的需求都已经写出来了。哈哈。
学习!学习!学习!
我也是通过你的贴子,才有了项目设计的想法。
模块已经设计好了,在贴子中已经更新。
请指正!
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2024-8-28 15:06:28 | 显示全部楼层
哦,原来是个小码农。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2024-8-28 15:07:58 | 显示全部楼层
dtp 发表于 2024-8-28 03:06 PM
哦,原来是个小码农。

并非码农。
我只提供思路。
所有的内容都是chatGPT写的。
chatGPT非常的强大。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|北大侠客行MUD ( 京ICP备16065414号-1 )

GMT+8, 2024-11-23 08:46 PM , Processed in 0.010680 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表