一个用 Rust 编写的高性能课程数据处理工具,用于替代原有的 Python + CLI 架构。
本工具需要以下数据已经准备好:
- repos 目录:包含所有课程的
.mdx和.json文件 - 培养方案数据:
hoa-majors/src/hoa_majors/data/plans/*.toml文件 - repos_list.txt(可选):用于过滤需要处理的课程
如果 repos 目录不存在,工具会提示错误并退出。您需要先运行 Python 脚本来下载这些数据。
- 高性能:避免了 N+1 查询问题,一次性加载所有培养方案数据
- 单一二进制:无需依赖外部 CLI 工具,可直接在 GitHub Actions 中运行
- 并发处理:使用 Rust 异步运行时高效处理大量课程数据
- 零配置:自动发现项目根目录,智能处理缺失文件
cargo build --release构建后的二进制文件位于 target/release/fuma
从项目根目录运行:
./fuma_rs/target/release/fumacd fuma_rs && cargo run --release如果您是首次使用,建议按以下顺序操作:
-
运行 Python 脚本获取数据(这部分保留原有流程):
cd scripts python main.py # 下载 repos 数据
-
运行 Rust 工具生成页面:
cd fuma_rs cargo run --release
- 加载培养方案:从
hoa-majors/src/hoa_majors/data/plans/*.toml读取所有培养方案 - 过滤课程:根据
repos_list.txt(如果存在)过滤可用课程 - 读取资源:从
repos/目录读取课程的.mdx和.json文件 - 生成页面:
- 为每个课程生成 MDX 页面,包含 YAML frontmatter
- 从
worktree.json生成文件树 JSX - 根据学期自动分类课程
- 生成学期索引、专业索引和年级索引
content/docs/
├── 2022/
│ ├── meta.json
│ ├── index.mdx
│ └── 010101/ # 专业代码
│ ├── meta.json
│ ├── index.mdx
│ ├── fresh-autumn/ # 大一秋季
│ │ ├── index.mdx
│ │ ├── COMP2001.mdx
│ │ └── ...
│ └── ...
└── ...
hoa-fuma/
├── fuma_rs/ # Rust 工具(本项目)
├── repos/ # 课程资源(由 Python 脚本生成)
│ ├── COMP2001.mdx
│ ├── COMP2001.json
│ └── ...
├── hoa-majors/ # 培养方案数据
│ └── src/hoa_majors/data/plans/
│ └── *.toml
├── content/docs/ # 输出目录
└── repos_list.txt # 可选的课程过滤列表
位于项目根目录,每行一个课程代码,用于过滤需要处理的课程。如果文件不存在,将处理所有课程。
示例:
COMP2001
COMP2003
MATH1001
tokio: 异步运行时serde: 序列化/反序列化toml: TOML 文件解析serde_json: JSON 处理thiserror: 错误处理walkdir: 目录遍历urlencoding: URL 编码chrono: 时间戳格式化
相比原有 Python + subprocess 架构的优化:
- 避免进程创建开销:不再为每个查询创建新进程
- 批量数据加载:一次性加载所有 TOML 文件到内存
- 内存中数据结构:使用 HashMap 快速查找,避免重复文件 I/O
- 编译型语言:Rust 的零成本抽象和编译优化
使用 thiserror 提供清晰的错误信息:
Io: 文件系统操作错误Toml: TOML 解析错误Json: JSON 解析错误MissingDataDir: 数据目录缺失
完整的 workflow 示例:
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Fetch course data (Python part)
run: |
cd scripts
python main.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build fuma
run: |
cd fuma_rs
cargo build --release
- name: Generate course pages
run: ./fuma_rs/target/release/fuma或者使用 cargo run:
- name: Generate pages
run: cd fuma_rs && cargo run --release- 使用 subprocess 调用
hoaCLI - 每个查询创建新进程
- N+1 查询问题
- 需要安装 Python 依赖
- 单一二进制,无外部依赖
- 一次性加载所有数据
- 批量处理,避免 N+1 问题
- 更快的执行速度
- 更少的内存占用
如果需要修改代码,请注意:
- 保持与原有 Python 输出的兼容性
- YAML frontmatter 格式必须匹配
- 文件树 JSX 结构必须保持一致
- 索引页面的 Card 链接格式必须正确