10 releases
Uses new Rust 2024
new 0.3.9 | Jun 13, 2025 |
---|---|
0.3.8 | Jun 6, 2025 |
0.3.7 | May 19, 2025 |
0.3.6 | Apr 9, 2025 |
0.2.4 | Apr 7, 2025 |
#296 in Database interfaces
262 downloads per month
Used in 5 crates
170KB
4K
SLoC
Moduforge
Moduforge是一个不含任何业务绑定的 计价编辑器默认实现,它可以通过扩展进行定制和扩展。 它的无业务绑定本质意味着它没有固定的业务约束,提供了完全的设计自由。可以根据业务需求进行定制。 设计思想是,通过扩展的方式与业务解耦,让编辑器可以支持任何业务,并且可以支持任何业务需求。
Moduforge是如何工作的?
-
工作方式: 定义基础节点和标记和约束,然后定义扩展添加行为。
-
model: 基础数据的定义,包括节点(Node),标记(Mark),约束(Schema)等。
-
state: 状态管理,主要负责状态的更新,插件的调度。
-
transform: 事务的实现,类似java 的DB事务。保证操作的原子性,保证数据的一致性。可以扩展最小的操作单元。
-
core: 组合model,state,transform 进一步实现编辑器的核心功能,添加并收集扩展.
-
项目目录结构
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 # 状态模块依赖配置
│
├── macros/ # 宏定义模块
│ ├── src/
│ │ ├── lib.rs # 宏定义入口
│ │ ├── command.rs # 命令宏
│ │ ├── extension.rs # 扩展宏
│ │ ├── mark.rs # 标记宏
│ │ ├── node.rs # 节点宏
│ │ └── plugin.rs # 插件宏
│ └── Cargo.toml # 宏模块依赖配置
│
├── tests/ # 测试模块
│ ├── src/
│ │ ├── lib.rs # 测试入口
│ │ ├── base.rs # 基础测试
│ │ ├── commands.rs # 命令测试
│ │ ├── content_test.rs # 内容测试
│ │ ├── ext.rs # 扩展测试
│ │ ├── middleware.rs # 中间件测试
│ │ ├── plugins.rs # 插件测试
│ │ ├── snapshot_test.rs # 快照测试
│ │ └── zip_test.rs # ZIP 测试
│ └── Cargo.toml # 测试模块依赖配置
│
├── Cargo.toml # 工作空间配置文件
├── Cargo.lock # 依赖锁定文件
├── rustfmt.toml # Rust 代码格式化配置
├── release.toml # 发布配置
└── .gitignore # Git 忽略文件配置
核心组件详解
State 状态管理
State 是编辑器的核心状态管理组件,负责维护编辑器的整体状态。它包含以下关键特性:
- 配置管理: 通过
Configuration
结构体管理编辑器的配置信息,包括插件列表、文档结构定义等 - 插件状态: 通过
fields_instances
管理所有插件的状态数据 - 文档管理: 通过
node_pool
管理文档的节点池 - 版本控制: 通过
version
字段追踪状态变更 - 资源管理: 通过
resource_manager
管理全局资源
State 提供了以下主要功能:
- 创建和初始化新的编辑器状态
- 管理插件状态
- 处理事务和状态更新
- 重新配置状态以适应新的需求
GlobalResourceManager 全局资源管理器
GlobalResourceManager 是编辑器运行时的全局资源管理器,负责管理所有注册的资源和状态。它包含以下关键特性:
- 资源表管理: 通过
ResourceTable
管理所有注册的资源 - Gotham状态管理: 通过
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 的区别
虽然 State 和 GlobalResourceManager 都涉及状态管理,但它们在职责和使用场景上有明显区别:
-
管理范围不同
- State 管理编辑器的整体状态,包括文档内容、插件状态、配置等
- GlobalResourceManager 专注于管理运行时资源和全局共享状态
-
生命周期不同
- State 的生命周期与编辑器实例绑定,随编辑器的创建而创建,销毁而销毁
- GlobalResourceManager 的生命周期更灵活,可以在不同 State 实例间共享
-
访问方式不同
- State 通过事务(Transaction)进行状态更新,保证操作的原子性和一致性
- GlobalResourceManager 提供直接的资源访问接口,适合快速读写共享资源
-
使用场景不同
- State 用于管理编辑器的核心状态,如文档内容、插件配置等
- GlobalResourceManager 用于管理跨插件共享的资源,如缓存、配置等
-
线程安全性不同
- State 的状态更新是单线程的,通过事务保证一致性
- GlobalResourceManager 是线程安全的,可以在多线程环境下安全访问
-
扩展性不同
- State 的状态结构相对固定,主要围绕文档和插件
- GlobalResourceManager 可以动态注册和管理任意类型的资源,扩展性更强
Moduforge使用了哪些技术框架?
-
im: Moduforge编辑器使用im-rs进行基础数据定义,保证数据的不可变。
-
zen: Moduforge编辑器使用zen进行规则引擎管理,解除业务硬编码耦合。
Moduforge 框架设计思路
-
可扩展性: Moduforge设计为高度可扩展,允许开发者根据需求自定义编辑器的功能和行为。这包括插件系统,使得添加新功能变得简单,任何功能都可以扩展.例如:历史记录,撤销,重做。
-
模块化: 整个框架被分解成多个独立的模块,每个模块负责编辑器的一个特定方面,如模型、状态管理、命令执行等。这种设计使得开发者可以根据项目需求选择性地引入所需模块。
-
命令模式: 使用命令模式来处理编辑操作。每个编辑操作都被封装成一个命令对象,这样可以方便地撤销或重做操作,同时也有助于实现复杂的编辑逻辑。
-
状态管理: 编辑器的状态被集中管理,所有对文档的修改都会触发状态的变化。这种设计有助于保持数据的一致性和可预测性。
大型树形编辑器适用性分析
Moduforge 框架特别适合用于大型树形编辑器的开发,以下是详细分析:
1. 树形结构支持
框架提供了完整的树形结构支持:
-
节点定义:
- 每个节点都有唯一的ID
- 支持节点类型(type)
- 支持节点属性(attrs)
- 支持子节点列表(content)
- 支持节点标记(marks)
-
树操作API:
- 获取子节点列表
- 递归获取所有子节点(深度优先)
- 获取父节点
- 获取节点深度
- 获取节点路径
- 检查叶子节点
- 获取兄弟节点
- 获取子树大小
2. 编辑功能支持
框架提供了完整的编辑功能:
-
节点操作:
- 添加节点
- 替换节点
- 移动节点
- 删除节点
- 递归删除子树
-
事务支持:
- 所有操作都在事务中执行
- 支持操作的原子性
- 支持撤销/重做
- 支持补丁记录
3. 统计功能支持
框架提供了丰富的统计功能:
-
节点统计:
- 获取节点总数
- 获取子树大小
- 获取节点深度
- 支持自定义过滤和查找
-
性能优化:
- 使用不可变数据结构(im-rs)
- 使用 Arc 进行引用计数
- 支持并发访问(Send + Sync)
4. 特别适合的场景
-
大型树形数据编辑:
- 支持深度嵌套的树结构
- 高效的节点查找和遍历
- 支持大规模数据操作
-
复杂数据统计:
- 支持自定义统计规则
- 支持节点过滤和查找
- 支持子树统计
-
实时编辑和更新:
- 支持事务性操作
- 支持撤销/重做
- 支持增量更新
5. 性能考虑
-
内存效率:
- 使用不可变数据结构
- 使用引用计数
- 支持共享节点
-
操作效率:
- 高效的节点查找
- 优化的树遍历
- 批量操作支持
-
并发支持:
- 线程安全设计
- 支持并发访问
- 支持资源管理
6. 扩展性
-
自定义节点类型:
- 支持自定义节点属性
- 支持自定义节点标记
- 支持自定义节点内容
-
插件系统:
- 支持自定义编辑操作
- 支持自定义统计规则
- 支持自定义验证规则
结论
Moduforge 框架非常适合用于大型树形编辑器的开发,特别是在以下场景:
- 需要处理大量树形数据的编辑器
- 需要复杂编辑操作的应用
- 需要实时统计和更新的系统
- 需要高性能和并发支持的应用
- 需要高度可定制的编辑器
框架的设计充分考虑了性能、可扩展性和易用性,能够很好地支持大型树形编辑器的开发需求。
关于Moduforge
Moduforge,是基于当前计价软件延伸出来的,因此它与 计价 的业务无关,它只是 个大型的 的编辑器。
License
计价软件内部团队使用请勿泄露。
📚 相关文档
本项目包含多个详细的分析和设计文档,涵盖架构分析、业务应用、设计模式等多个方面:
🎋 业务模型映射
Node模型到建筑预算的精确映射
详细介绍了如何将ModuForge的Node模型精确映射到建筑预算业务
-
核心内容:
- ModuForge Node模型与建筑预算业务的详细映射关系
- 预算项目层级结构的完整定义(预算文档→工程项目→单位工程→分部工程→分项工程→清单项目)
- NodeSpec业务类型规范的具体实现代码
- Mark标记系统在业务状态管理中的应用
- 实际业务查询和统计功能的代码示例
-
技术亮点:
- 层级结构天然支持工程预算的组织方式
- 属性系统完美匹配造价数据(数量、单价、金额等)
- 标记系统支持业务状态管理(已计算、已锁定、已套定额等)
- 提供完整的业务分析器实现代码
🚀 架构应用场景
架构适用业务场景分析
深入分析ModuForge架构在不同业务场景中的适用性
-
业务场景分类:
- 业务流程编排:工作流引擎、数据处理管道(ETL)
- 计算编排:计价引擎系统、风控决策引擎
- 内容管理:协同编辑器、内容发布系统
- 规则引擎:业务规则引擎、A/B测试框架
- 智能计算:推荐系统、机器学习Pipeline
-
实际应用示例:
- 保险计价引擎、出行计费系统
- 在线文档协作、代码协同编辑
- 大数据处理平台、实时数据流处理
- 风控系统、推荐算法平台
🔗 业务依赖设计
A业务依赖B业务的可插拔架构设计
传统的业务依赖管理器方案
-
设计特点:
- 通过专门的BusinessDependencyManager管理业务间依赖关系
- 支持依赖类型分类(计算依赖、数据依赖、事件依赖)
- 实现完整的依赖检查和执行顺序管理
- 提供拓扑排序确保依赖执行顺序正确
-
核心组件:
- BusinessDependencyManager:统一依赖管理
- BusinessDependency:依赖关系描述
- 完整的A业务和B业务插件实现示例
基于Transaction Meta的业务依赖解耦设计
推荐的轻量级业务依赖方案
-
设计优势:
- 利用Transaction的meta字段传递业务依赖信息
- 更轻量级,无需额外的依赖管理器组件
- 完全基于现有事务系统实现
- 支持业务降级和容错处理
-
技术实现:
- Meta字段结构化设计(业务类型、状态、依赖关系)
- 业务执行上下文传递
- 依赖满足检查和等待机制
- 完整的插件实现代码示例
📈 架构分析
架构限制性分析
客观分析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项目的完整技术体系,为不同层次的读者提供了从概念理解到具体实现的全方位指导。
lib.rs
:
ModuForge-RS 数据模型模块
该模块定义了框架中使用的核心数据模型,包括:
- 节点系统
- 标记系统
- 属性系统
- 模式定义
- 内容匹配
- ID 生成
- 错误处理
主要组件:
node
: 节点定义,表示文档中的基本元素mark
: 标记定义,用于文档的格式化attrs
: 属性定义,存储节点和标记的属性mark_type
: 标记类型定义,定义不同类型的标记node_type
: 节点类型定义,定义不同类型的节点schema
: 模式定义,定义文档结构规则content
: 内容匹配定义,处理内容验证和匹配error
: 错误类型和处理id_generator
: ID 生成器,生成唯一标识符node_pool
: 节点池,管理节点实例types
: 通用类型定义
Dependencies
~11–20MB
~270K SLoC