死代码移除: - whiteboard_hub.py: 移除未引用的 reset_hub 单例重置函数 - tunnel_service.py: 移除未引用的 is_port_allowed (逻辑已在 sftp_server 内联) - tunnel_session_dao.py: 移除未引用的 get_active_by_port - pdf_job_dao.py: 移除未用 datetime 导入 - pdf_converter.py: 移除未用 shutil 导入 - pdf_service.py: 移除未用 PdfSubmitResponse 导入 + _do_convert 内未用 hashlib 导入 - upload_html.py: 移除未用 escape 导入 (JS 侧自有 escapeHtml) - pdf_controller.py: 移除 _resolve_cookie 内未用 cfg 局部变量 提前失败/分层修复: - database.py init_db_schema: 建表后用 inspector 校验既有表列与模型一致, 缺列即抛 RuntimeError (fail-fast on schema drift), 避免运行期才暴露 - whiteboard_dao.get_or_create: 仅 IntegrityError 才回滚重读, 其他异常向上抛 (原 except Exception 会掩盖 schema/连接等真实故障) - pdf_service.admin_delete/_safe_delete_file: 改用 PdfJobDAO.delete / UploadedFileDAO.delete, 不再直接操作 job_dao.db / file_dao.db (修复分层契约: DAO 头注释声明 service 不直接操作 session) - PdfJobDAO 新增 delete(job) 方法 日志补全 (8 处 silent catch): - whiteboard_hub.py disconnect/close_board 关闭 ws: logger.debug - whiteboard_controller _safe_send/_safe_close: logger.debug - sftp_server _close_tunnel_dao/读用户名: logger.debug - sftp_server validate_public_key: logger.warning (auth 路径, 避免静默失败) 文档: - 新增 docs/routes.md, docs/configuration.md, docs/error-handling.md - README.md 精简为简介/结构/外部依赖/apache2 配置/Ubuntu 安装/docs 链接
30 lines
2.6 KiB
Markdown
30 lines
2.6 KiB
Markdown
# 错误处理与日志约定
|
||
|
||
zTools2 采用 Spring 风格分层架构,错误处理分三层:DAO fail-fast(抛异常),Service 捕获后转换业务异常并记日志,Controller 捕获后转 HTTP 状态码。
|
||
|
||
## DAO 层(app/dao/)
|
||
|
||
- **唯一发 SQL 的层**:所有写操作(create/update/delete)均在该层 commit,service 不直接操作 session。
|
||
- `get_or_create`(whiteboard_dao.py):仅 `IntegrityError`(并发下另一事务已插入违反唯一约束)才回滚重读;其他异常向上抛,避免掩盖 schema/连接等真实故障。
|
||
- `delete`(pdf_job_dao.py / uploaded_file_dao.py):硬删 DB 行并 commit;不存在返回 False。
|
||
- schema 漂移检测:`init_db_schema`(database.py)建表后用 inspector 检查既有表的列是否与模型声明齐全,缺列即抛 `RuntimeError`(fail-fast),避免运行期才以晦涩的 `OperationalError` 暴露。
|
||
|
||
## Service 层(app/services/)
|
||
|
||
- **PdfService**:`submit` 校验扩展名/大小,超限清理已落盘文件后抛 `HTTPException`;后台转换 `_convert_async` 捕获 `TimeoutError` / 通用异常,经 `_mark_failed` 落库 + `logger.warning`。`admin_delete` 磁盘删除失败仅 `logger.warning`,仍清 DB 行保证列表不再显示。
|
||
- **UploadService / ChunkUploadService**:流式落盘出错清理临时文件后 `raise`(向上传播);分片会话被放弃由后台 reaper 每 60s 清理。
|
||
- **WhiteboardHub**:`disconnect` / `close_board` 关闭 websocket 出错 `logger.debug`(尽力关闭,可能已关闭);`broadcast` 单连接发送失败立即 disconnect,不影响其他连接;reaper 循环异常 `logger.warning` 后继续。
|
||
- **TunnelService**:`register` / `close` / `reap_orphans` 均记 `logger.info`;SSH 连接断开时清理会话失败 `logger.warning`。
|
||
- **sftp_server**:`validate_public_key` 校验异常 `logger.warning`(auth 路径,避免静默失败);`_close_tunnel_dao` / 读会话用户名失败 `logger.debug`(尽力清理)。
|
||
|
||
## Controller 层(app/controllers/)
|
||
|
||
- **pdf_controller**:`_resolve_cookie` 解析用户 cookie,无则生成新值挂 request.state 供响应 set_cookie。
|
||
- **whiteboard_controller**:`_safe_send` / `_safe_close` 发送/关闭 WS 失败 `logger.debug`(best-effort);WS 主循环异常 `logger.warning` 后正常关闭连接。
|
||
- 所有管理 API(`/api/admin/*`)经 `require_docs_auth` Basic Auth 守卫(常量时间比较)。
|
||
|
||
## 日志位置
|
||
|
||
- `logs/app.log`(HTTP)、`logs/sftp.log`(SFTP);pidfile:`app.pid`、`sftp.pid`。
|
||
- 日志器命名:`zikai.pdf` / `zikai.whiteboard` / `zikai.tunnel` / `sftp`,便于按模块过滤。
|