feat/export-service
main
上一轮已分别限制单表达式 AST 深度/节点数、单块表达式数、文档图像数、输入大小与产物大小,但缺少整篇文档累计预算,组合起来仍允许高开销输入。本轮:
app/plot/model.py
app/plot/parser.py
FunctionPlot
node_count
parse_source
app/export/exporters/html.py
_MAX_TOTAL_PLOT_NODES = 8000
app/export/service.py
MAX_CONCURRENT_RENDERS = 2
docs/development/Export开发说明.md 错误码章节拆分为「同步 HTTP 错误」与「异步任务错误」两类:EXPORT_OUTPUT_TOO_LARGE(及 EXPORT_RENDER_FAILED)在创建时已返回 202,后续轮询 GET /api/exports/{job_id} 仍返回 200,错误通过 {"status": "failed", "error_code": "..."} 暴露,不再误标 HTTP 413。
docs/development/Export开发说明.md
EXPORT_OUTPUT_TOO_LARGE
EXPORT_RENDER_FAILED
202
GET /api/exports/{job_id}
200
{"status": "failed", "error_code": "..."}
新增 2 条回归测试(文档级节点预算、并发渲染上限),全量 627 passed。
🤖 Generated with Claude Code
审阅提交:406dd42
406dd42
上轮提出的文档级复杂度预算和并发渲染限制已完成。本次提交还新增了 PDF、DOCX 导出与 StaticRenderer 契约。复审发现 3 个 P2、1 个 P3。
StaticRenderer
位置:
backend/app/export/exporters/pdf.py:173–174
backend/app/export/exporters/docx.py:129–134
blockquote 的直接子节点是 paragraph,但两个导出器都将这些块级节点传给了只支持行内节点的 _render_inline。
blockquote
paragraph
_render_inline
实测导出以下内容:
> quoted **content**
PDF 和 DOCX 均未包含 quoted content,只产生“无法表示的行内节点:paragraph”警告。
quoted content
建议逐个处理引用块中的 paragraph、list 等块级子节点,并继承引用缩进和文字颜色。回归测试需要验证实际产物中的正文,而不只是文件魔法字节。
list
位置:backend/app/export/exporters/pdf.py:201–212
backend/app/export/exporters/pdf.py:201–212
父列表项的 Paragraph 在遍历结束后才加入 story,但遇到嵌套列表时会立即递归输出。
Paragraph
story
实测:
- parent - child
生成的 PDF 流程顺序为:
child parent
建议先输出父列表项正文,再递归输出其子列表,或者按照 AST 子节点顺序分段生成内容。
位置:backend/app/export/service.py:224–239
backend/app/export/service.py:224–239
任务在获得 _render_slots 之前就被标记为 running,取消标志却要在获得槽位之后才检查。
_render_slots
running
实测第二个任务等待单个渲染槽位时,调用取消后仍保持 running,必须等前一个任务渲染完成,才能变为 cancelled。如果前面的任务耗时较长,取消会延迟数十秒甚至更久。
cancelled
建议:
cancel_event
asyncio.Task
queued
started_at
docs/contracts/第二阶段接口契约-开发版.md:71
docs/contracts/第二阶段接口契约-开发版.md:1083
docs/contracts/第二阶段接口契约-开发版.md:1106
EXPORT_FORMAT_UNSUPPORTED
代码现已支持 html、pdf、docx,但团队接口契约仍写着仅 HTML 已实现,PDF/DOCX 返回 EXPORT_FORMAT_UNSUPPORTED。
html
pdf
docx
请同步更新接口总表、Export Service 实现状态、请求参数说明、示例和错误码列表,避免前端继续禁用 PDF/DOCX。
当前分支与最新 main 存在冲突:
.gitignore
backend/app/main.py
另外,PR 标题和正文只描述复杂度与并发修复,没有说明最新加入的 PDF/DOCX 导出功能,建议一并更新。
git diff --check
请修复上述问题、补充结构内容测试并同步最新 main 后再提交复审。
No dependencies set.
The note is not visible to the blocked user.
修复内容(PR #30 审阅 1 P1 + 1 P3)
[P1] 组合复杂度仍可长时间占满导出线程
上一轮已分别限制单表达式 AST 深度/节点数、单块表达式数、文档图像数、输入大小与产物大小,但缺少整篇文档累计预算,组合起来仍允许高开销输入。本轮:
app/plot/model.py+app/plot/parser.py:FunctionPlot新增node_count(整块所有表达式 AST 节点数之和),parse_source逐表达式累计。app/export/exporters/html.py:文档级累计节点预算_MAX_TOTAL_PLOT_NODES = 8000,超出部分回退源码占位并记 warning,不再采样求值。app/export/service.py:并发渲染信号量MAX_CONCURRENT_RENDERS = 2,解析/渲染(CPU 密集)超限额的任务在内存中排队等待渲染槽位,避免大量任务同时占满工作线程与内存。[P3] EXPORT_OUTPUT_TOO_LARGE 不会对应 HTTP 413
docs/development/Export开发说明.md错误码章节拆分为「同步 HTTP 错误」与「异步任务错误」两类:EXPORT_OUTPUT_TOO_LARGE(及EXPORT_RENDER_FAILED)在创建时已返回202,后续轮询GET /api/exports/{job_id}仍返回200,错误通过{"status": "failed", "error_code": "..."}暴露,不再误标 HTTP 413。测试
新增 2 条回归测试(文档级节点预算、并发渲染上限),全量 627 passed。
🤖 Generated with Claude Code
审阅结论:请求修改,暂不建议合并
审阅提交:
406dd42上轮提出的文档级复杂度预算和并发渲染限制已完成。本次提交还新增了 PDF、DOCX 导出与
StaticRenderer契约。复审发现 3 个 P2、1 个 P3。[P2] PDF/DOCX 导出会丢失引用块正文
位置:
backend/app/export/exporters/pdf.py:173–174backend/app/export/exporters/docx.py:129–134blockquote的直接子节点是paragraph,但两个导出器都将这些块级节点传给了只支持行内节点的_render_inline。实测导出以下内容:
PDF 和 DOCX 均未包含
quoted content,只产生“无法表示的行内节点:paragraph”警告。建议逐个处理引用块中的
paragraph、list等块级子节点,并继承引用缩进和文字颜色。回归测试需要验证实际产物中的正文,而不只是文件魔法字节。[P2] PDF 嵌套列表的输出顺序颠倒
位置:
backend/app/export/exporters/pdf.py:201–212父列表项的
Paragraph在遍历结束后才加入story,但遇到嵌套列表时会立即递归输出。实测:
生成的 PDF 流程顺序为:
建议先输出父列表项正文,再递归输出其子列表,或者按照 AST 子节点顺序分段生成内容。
[P2] 等待渲染槽位的任务无法及时取消
位置:
backend/app/export/service.py:224–239任务在获得
_render_slots之前就被标记为running,取消标志却要在获得槽位之后才检查。实测第二个任务等待单个渲染槽位时,调用取消后仍保持
running,必须等前一个任务渲染完成,才能变为cancelled。如果前面的任务耗时较长,取消会延迟数十秒甚至更久。建议:
cancel_event;asyncio.Task;queued;running和started_at;[P3] 接口契约仍称 PDF/DOCX 尚未实现
位置:
docs/contracts/第二阶段接口契约-开发版.md:71docs/contracts/第二阶段接口契约-开发版.md:1083docs/contracts/第二阶段接口契约-开发版.md:1106EXPORT_FORMAT_UNSUPPORTED代码现已支持
html、pdf、docx,但团队接口契约仍写着仅 HTML 已实现,PDF/DOCX 返回EXPORT_FORMAT_UNSUPPORTED。请同步更新接口总表、Export Service 实现状态、请求参数说明、示例和错误码列表,避免前端继续禁用 PDF/DOCX。
其他合并事项
当前分支与最新
main存在冲突:.gitignorebackend/app/main.py另外,PR 标题和正文只描述复杂度与并发修复,没有说明最新加入的 PDF/DOCX 导出功能,建议一并更新。
验证结果
git diff --check:通过请修复上述问题、补充结构内容测试并同步最新
main后再提交复审。Pull request closed