事件驱动架构
基于不可变数据结构和完善的事件系统,提供可靠的状态管理。
ModuForge 是一个基于 Rust 的状态管理和数据转换框架,专注于不可变数据结构和事件驱动架构。它提供了无业务绑定的编辑器核心实现,可以通过扩展进行定制和扩展,支持任何业务场景的需求。
工作方式: 定义基础节点、标记和约束,然后定义扩展添加行为。
model: 基础数据的定义,包括节点(Node),标记(Mark),约束(Schema)等。
state: 状态管理,主要负责状态的更新,插件的调度。
transform: 事务的实现,类似数据库事务。保证操作的原子性,保证数据的一致性。可以扩展最小的操作单元。
core: 组合 model、state、transform 进一步实现编辑器的核心功能,添加并收集扩展。
rules: 规则引擎系统,包含表达式解析、后端执行、引擎核心和模板系统。
moduforge-rs/
├── core/ # 核心功能模块
│ ├── src/
│ │ ├── lib.rs # 核心库入口
│ │ ├── async_processor.rs # 异步任务处理器
│ │ ├── async_runtime.rs # 异步运行时环境
│ │ ├── error.rs # 错误类型和处理
│ │ ├── event.rs # 事件系统
│ │ ├── extension.rs # 扩展机制
│ │ ├── extension_manager.rs # 扩展管理器
│ │ ├── flow.rs # 流程控制
│ │ ├── helpers/ # 辅助函数
│ │ ├── history_manager.rs # 历史记录管理
│ │ ├── mark.rs # 标记系统
│ │ ├── metrics.rs # 指标系统
│ │ ├── middleware.rs # 中间件支持
│ │ ├── node.rs # 节点系统
│ │ ├── runtime.rs # 运行时环境
│ │ └── types.rs # 核心类型定义
│ └── Cargo.toml # 核心模块依赖配置
│
├── model/ # 数据模型模块
│ ├── src/
│ │ ├── lib.rs # 模型定义入口
│ │ ├── node.rs # 节点定义
│ │ ├── mark.rs # 标记定义
│ │ ├── attrs.rs # 属性定义
│ │ ├── mark_type.rs # 标记类型定义
│ │ ├── node_type.rs # 节点类型定义
│ │ ├── schema.rs # 模式定义
│ │ ├── content.rs # 内容匹配定义
│ │ ├── error.rs # 错误类型和处理
│ │ ├── id_generator.rs # ID 生成器
│ │ ├── node_pool.rs # 节点池管理
│ │ └── types.rs # 通用类型定义
│ └── Cargo.toml # 模型模块依赖配置
│
├── transform/ # 数据转换模块
│ ├── src/
│ │ ├── lib.rs # 转换功能入口
│ │ ├── attr_step.rs # 属性步骤
│ │ ├── draft.rs # 草稿系统
│ │ ├── mark_step.rs # 标记步骤
│ │ ├── node_step.rs # 节点步骤
│ │ ├── patch.rs # 补丁系统
│ │ ├── step.rs # 步骤定义
│ │ └── transform.rs # 转换系统
│ └── Cargo.toml # 转换模块依赖配置
│
├── state/ # 状态管理模块
│ ├── src/
│ │ ├── lib.rs # 状态管理入口
│ │ ├── error.rs # 错误类型和处理
│ │ ├── gotham_state.rs # Gotham 状态管理
│ │ ├── logging.rs # 日志系统
│ │ ├── ops.rs # 操作定义
│ │ ├── plugin.rs # 插件系统
│ │ ├── resource.rs # 资源管理
│ │ ├── resource_table.rs # 资源表
│ │ ├── state.rs # 状态管理
│ │ └── transaction.rs # 事务处理
│ └── Cargo.toml # 状态模块依赖配置
│
├── rules/ # 规则引擎模块
│ ├── expression/ # 表达式解析和处理
│ ├── backend/ # 规则引擎后端
│ ├── engine/ # 规则引擎核心
│ └── template/ # 模板系统
│
├── macros/ # 宏定义模块
│ ├── src/
│ │ ├── lib.rs # 宏定义入口
│ │ ├── command.rs # 命令宏
│ │ ├── extension.rs # 扩展宏
│ │ ├── mark.rs # 标记宏
│ │ ├── node.rs # 节点宏
│ │ └── plugin.rs # 插件宏
│ └── Cargo.toml # 宏模块依赖配置
│
├── demo/ # 示例和演示代码
│ ├── src/
│ ├── Cargo.toml
│ └── README.md
│
├── docs/ # 项目文档
│ ├── node-budget-mapping.md # Node模型到业务映射
│ ├── architecture_use_cases.md # 架构应用场景分析
│ ├── plugin-development-guide.md # 插件开发指南
│ └── ... # 其他分析文档
│
├── test-data/ # 测试数据
├── Cargo.toml # 工作空间配置文件
├── Cargo.lock # 依赖锁定文件
├── rustfmt.toml # Rust 代码格式化配置
├── release.toml # 发布配置
└── .gitignore # Git 忽略文件配置
State 是编辑器的核心状态管理组件,负责维护编辑器的整体状态。它包含以下关键特性:
Configuration
结构体管理编辑器的配置信息,包括插件列表、文档结构定义等fields_instances
管理所有插件的状态数据node_pool
管理文档的节点池version
字段追踪状态变更resource_manager
管理全局资源State 提供了以下主要功能:
GlobalResourceManager 是编辑器运行时的全局资源管理器,负责管理所有注册的资源和状态。它包含以下关键特性:
ResourceTable
管理所有注册的资源GothamState
管理特定于Gotham框架的状态Send
和 Sync
trait,确保可以在线程间安全传递和共享clear
方法用于清理所有资源GlobalResourceManager 的主要使用场景:
GlobalResourceManager 使用案例
以下是一个使用 GlobalResourceManager 的典型场景:
// 1. 定义自定义资源类型
#[derive(Debug)]
struct CacheManager {
data: HashMap<String, String>,
}
impl Resource for CacheManager {
fn name(&self) -> Cow<str> {
"CacheManager".into()
}
}
// 2. 在插件初始化时注册资源
async fn plugin_init(config: &StateConfig, instance: Option<&State>) -> PluginState {
// 获取资源管理器
let resource_manager = instance.unwrap().resource_manager();
let mut resource_manager = resource_manager.write().unwrap();
// 创建并注册缓存管理器
let cache_manager = CacheManager {
data: HashMap::new(),
};
resource_manager.resource_table.add(cache_manager);
// 返回插件状态
Arc::new(HashMap::new())
}
// 3. 在插件中使用共享资源
async fn plugin_operation(state: &State) {
// 获取资源管理器
let resource_manager = state.resource_manager();
let resource_manager = resource_manager.read().unwrap();
// 获取缓存管理器
let cache_manager = resource_manager.resource_table.get::<CacheManager>(0).unwrap();
// 使用缓存管理器
cache_manager.data.insert("key".to_string(), "value".to_string());
}
// 4. 在另一个插件中访问相同资源
async fn another_plugin_operation(state: &State) {
let resource_manager = state.resource_manager();
let resource_manager = resource_manager.read().unwrap();
let cache_manager = resource_manager.resource_table.get::<CacheManager>(0).unwrap();
let value = cache_manager.data.get("key").unwrap();
println!("获取到的值: {}", value);
}
这个案例展示了:
通过 GlobalResourceManager,不同插件可以安全地共享和访问全局资源,而不需要直接依赖其他插件。
虽然 State 和 GlobalResourceManager 都涉及状态管理,但它们在职责和使用场景上有明显区别:
管理范围不同
生命周期不同
访问方式不同
使用场景不同
线程安全性不同
扩展性不同
im-rs: ModuForge 使用 im-rs 进行基础数据定义,保证数据的不可变性。
tokio: 异步运行时,支持高并发的异步操作。
serde: 序列化和反序列化支持,用于数据的持久化和传输。
thiserror/anyhow: 错误处理框架,提供类型安全的错误管理。
zen: 规则引擎管理,解除业务硬编码耦合(如果使用)。
可扩展性: ModuForge 设计为高度可扩展,允许开发者根据需求自定义编辑器的功能和行为。这包括插件系统,使得添加新功能变得简单,任何功能都可以扩展。例如:历史记录,撤销,重做。
模块化: 整个框架被分解成多个独立的模块,每个模块负责编辑器的一个特定方面,如模型、状态管理、命令执行等。这种设计使得开发者可以根据项目需求选择性地引入所需模块。
不可变数据: 使用 im-rs 确保数据结构的不可变性,提供安全的并发访问和高效的结构共享。
事件驱动: 基于事件驱动架构,所有状态变更都通过事件系统进行,确保系统的响应性和可预测性。
命令模式: 使用命令模式来处理编辑操作。每个编辑操作都被封装成一个命令对象,这样可以方便地撤销或重做操作,同时也有助于实现复杂的编辑逻辑。
状态管理: 编辑器的状态被集中管理,所有对文档的修改都会触发状态的变化。这种设计有助于保持数据的一致性和可预测性。
ModuForge 框架特别适合用于大型树形编辑器的开发,以下是详细分析:
框架提供了完整的树形结构支持:
节点定义:
树操作API:
框架提供了完整的编辑功能:
节点操作:
事务支持:
框架提供了丰富的统计功能:
节点统计:
性能优化:
大型树形数据编辑:
复杂数据统计:
实时编辑和更新:
内存效率:
操作效率:
并发支持:
自定义节点类型:
插件系统:
ModuForge 框架非常适合用于大型树形编辑器的开发,特别是在以下场景:
框架的设计充分考虑了性能、可扩展性和易用性,能够很好地支持大型树形编辑器的开发需求。
ModuForge 是基于当前计价软件延伸出来的通用编辑器框架,因此它与具体的计价业务无关,它只是一个大型的、通用的编辑器框架。
计价软件内部团队使用请勿泄露。
本项目包含多个详细的分析和设计文档,涵盖架构分析、业务应用、设计模式等多个方面:
详细介绍了如何将ModuForge的Node模型精确映射到建筑预算业务
核心内容:
技术亮点:
深入分析ModuForge架构在不同业务场景中的适用性
业务场景分类:
实际应用示例:
传统的业务依赖管理器方案
设计特点:
核心组件:
推荐的轻量级业务依赖方案
设计优势:
技术实现:
客观分析ModuForge架构的优势与限制
历史管理和撤销重做功能的设计实现
新手入门:建议先阅读本README.md了解整体架构,再查看architecture_use_cases.md
了解适用场景
业务建模:如需将ModuForge应用到具体业务,重点参考node-budget-mapping.md
的映射方法
复杂依赖:如果业务间存在复杂依赖关系,优先考虑meta_based_dependency_design.md
的轻量级方案
架构决策:在项目技术选型时,参考architecture_limitations_analysis.md
的客观分析
功能扩展:需要添加历史管理功能时,参考simple_enhanced_history.md
的实现方案
这些文档共同构成了ModuForge项目的完整技术体系,为不同层次的读者提供了从概念理解到具体实现的全方位指导。