cjw
|
eb0a4005e1
|
fix(db): celery 角色改用 NullPool——连接跨事件循环复用致任务全挂
celery_tasks 经 asyncio.run 每任务新建事件循环,而 asyncpg 连接绑定
创建它的循环。db_manager 引擎只连一次(is_connected 短路),QueuePool
把上一循环的连接缓存着流入新循环:任务报
"got Future attached to a different loop" 全部 failed,连接销毁时再报
"Event loop is closed"(ForkPoolWorker 日志连续复现)。
celery_tasks 对 redis 已有同因处理(每任务 reconnect()),DB 侧漏了。
改法:connect(role="celery") 用 NullPool——连接不缓存,每次 checkout
在当前循环新建、用完即关。web 入口(单循环 uvicorn)QueuePool 不变。
已实测:同进程三个连续 asyncio.run 循环共享引擎,全部查询成功。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-26 23:43:54 +08:00 |
|
cjw
|
73de137779
|
fix(processing): process_file_core 缺 timeout_seconds 参数——解析必挂 NameError
process_file_core 内 4 处引用 timeout_seconds(run_occ / 网格 / 型腔 /
设计分析的步骤超时),但该变量定义在外层 process_file_with_storage
(按文件大小计算超时处)。拆方法重构时漏传,解析第一步
run_occ("parse_stp") 即 NameError,任务标 failed,页面报
"name 'timeout_seconds' is not defined"。
修复:核心方法显式接收 timeout_seconds 参数(默认 300 兜底),
调用方传入。pyflakes 全仓库 F821 扫描确认无同类未定义名。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-26 23:27:32 +08:00 |
|
cjw
|
aaaac95b53
|
fix(init_db): await 优先级漏括号——启动迁移自诞生起从未执行成功(事故根因)
has_alembic = await conn.execute(...).scalar() 因 await 优先级低于
属性访问,实际解析为 await (conn.execute(...).scalar())——在协程对象
上调 .scalar() 必抛 AttributeError('coroutine' object has no attribute
'scalar')。启动迁移每次容器启动都在第一行炸掉,再被 except 吞成一行
日志(4a5dc61 已改为 logger.exception)。两行均改为
(await conn.execute(...)).scalar()。
已于生产库实测:主库路径(has_alembic=True→upgrade no-op)与临时
历史库路径(stamp+upgrade)全部跑通,临时库已删除。
至此 2026-09-26 事故根因链闭合:启动迁移从未生效 → prod schema 长期
落后于模型 → 新镜像上线即上传 500(缺 product_id)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-26 23:17:33 +08:00 |
|
cjw
|
4a5dc61a02
|
fix(init_db): 启动迁移失败不再静默——logger.exception 带 traceback + schema 覆盖校验
2026-09-26 事故复盘:AUTO_MIGRATE=true 但启动迁移在 stamp 之前就抛异常,
except 里 logger.error(f"{e}") 丢掉了 traceback,docker logs 只剩一句
"数据库初始化失败",prod 缺 stp_files.product_id 等列导致上传全挂,
无从定位。两个修复:
- 初始化异常改用 logger.exception,完整 traceback 落日志
- 新增启动期 _verify_schema_coverage:模型声明的 32 张表全部列必须真实
存在于 DB,缺失即 error 点名(只查缺不查多,遗留列不报);迁移后自动
执行,只读、自身异常不影响启动
已对生产库实跑验证:32 张表全部通过。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-26 23:11:30 +08:00 |
|
cjw
|
f1d6a78f8a
|
fix(auth): 登录 500——asyncpg 拒绝 aware datetime 写入 naive TIMESTAMP 列
批次5(64dc85b)datetime 弃用清零把 utcnow() 换成 aware 的
now(timezone.utc),而 users.last_login 列是 TIMESTAMP WITHOUT TIME
ZONE(sa.DateTime()),asyncpg 编码时抛 DataError → 未捕获 →
Starlette 纯文本 500。症状:密码错误正常 401,密码正确反而 500
(错误密码在 commit 前已 return)。
已在生产库实测确认(事务回滚零写入):aware 写入 REJECTED、
naive ACCEPTED、过去 1 小时 last_login 零记录。
- auth_service: last_login 改存 naive UTC(.replace(tzinfo=None)),
JWT exp 不受影响仍用 aware
- experience_feedback_service: expires_at 同为 naive 列,提交/查询
两处 aware now 一并修掉(线上尚无此表,属前瞻性修复)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-26 22:29:17 +08:00 |
|
cjw
|
505f3591ab
|
D17 批 2:算法接缝(OCC payload 通道 + hints 透传到分模评分)—— 闭环通
让批 1 沉淀的老师傅经验 hints 真接入分模方案生成:
processing_service 拉同指纹 hints 装进 OCC worker payload,
planner 透传到 candidate_generator(axis 优先级加成)和
scheme_scorer(score_breakdown 新字段 + total_score 加成),
写入即消费闭环通。
变更内容:
- src/moldinsight/core/parting_candidate_generator.py
generate_candidates(..., hints=None):_build_axis_metrics 末尾按 hints
加成(priority_score += weight × 20 上限;sample_count ≥ 2 + weight ≥ 0.5
→ method 标签升级 "human_experience_primary")
- src/moldinsight/core/parting_scheme_scorer.py
score_schemes(schemes, *, hints=None) keyword-only:_score_scheme 新增
human_hint_bonus 字段(weight × 12 上限;sample_count < 2 时 ×0.5 折半
防信号不足过度影响);_compute_human_hint_bonus 静态方法解析 axis
(parting.axis → axis → Z);bonus 纳入 total_score
- src/moldinsight/core/multi_scheme_planner.py
generate_plan(..., hints=None):透传 hints 到 candidate_generator 与
scheme_scorer;global_summary.applied_hints 注入返回供前端 ResultView
渲染经验角标
- src/moldinsight/services/processing_service.py
_step_generate_cavity 加 db_session 形参;调用
experience_feedback_service.resolve_for_process_params 拿同指纹 hints,
装进 run_occ payload 顶层 experience_hints;解析失败回退空 list
不阻塞主流程(旧任务不因 receives 闭包退化)
- src/moldinsight/core/occ_worker.py
_op_generate_cavity:payload.get("experience_hints") or {} 透传给
planner.generate_plan(..., hints=...);普通 dict 跨进程 pickle 安全
(满足 occ_worker.py:7-8 硬规则)
- tests/test_experience_feedback_algorithm.py(new)11 例:
- candidate_generator 3 例(无 hints 默认 / hints 加成 / sample_count < 2 不升级)
- scheme_scorer 4 例(无 hints 无 bonus / bonus 加成 / sample_count 折半 /
weight=0 不加成)
- multi_scheme_planner 2 例 OCC-gated(透传 / applied_hints 默认空)
- processing_service 2 例 OCC-gated(payload 含 experience_hints /
解析失败回退空 list)
设计取舍:
- keyword-only hints:避免与位置参数混淆
- weight 仅正向上有效:max(0, (adopted-rejected)/total),老师傅拒绝
的不扣分老算法,只让采纳的加分
- signal-noise 控制:sample_count < 2 时 bonus ×0.5,但 priority_score
仍加成(候选方向仍偏向,避免完全无信号)
- graceful degradation:hints 解析失败回退空 list,主流程继续
- docs/STATUS.md 顶部加 2026-09-23 批 2 日志条目
- docs/TECH_DEBT.md D17 追加批 2 已完成描述 + 缩减剩余工作(仅剩批 3 / 4)
测试基线:192 passed, 13 skipped(净增 7 通过 + 4 OCC-gated skip)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-23 16:21:33 +08:00 |
|
cjw
|
2c9ba9d6b3
|
D17 批 1:Human-in-Loop 老师傅经验反馈(数据 + 权限 + 写入 API)
新增 experience_feedback 表(32 表迁移,alembic head b7d1f4a92c3e),
老师傅对系统推荐方案给出"采纳 / 调整 / 拒绝"反馈,按"产品指纹 +
工艺参数"为键跨任务匹配,下次同指纹产品分析自动消费。
变更内容:
- src/moldinsight/models/experience_feedback.py(new)ORM:Base 单点来源、
跨模块裸 FK(user_id / processing_task_id / stp_file_id)、不建 ORM
relationship;fingerprint JSON 列存跨任务匹配键
- src/moldinsight/models/__init__.py 导出 ExperienceFeedback
- migrations/versions/b7d1f4a92c3e_add_experience_feedback.py(new)32 表
迁移;fingerprint 列 PG 下加 GIN 索引(jsonb_path_query 支持)
- src/shared/database/init_db.py 加 3 个权限码(view_experience_feedback /
feedback_experience_hint / manage_experience_feedback)+ 新角色
process_engineer;admin 角色 permissions 同步补齐;init_permissions /
init_roles 改为按 code 比对(新增保留已有 id,避免 FK 引用失效)——
修复既有 DB 启动期漏掉新权限的幂等 bug
- src/moldinsight/services/experience_feedback_service.py(new)service:
compute_fingerprint 分桶(bbox_aspect / volume_bucket / face_bucket /
undercut_class / material_family / is_foam)/ record_feedback(D9 边界:
service.flush + 路由 commit;D17 衰减:同 stp_file_id 整体续期 90 天 TTL,
无 celery beat 依赖)/ list_hints_for_task / resolve_for_process_params
- src/moldinsight/api/experience_feedback_router.py(new)路由:Pydantic
模型写在路由文件内(项目硬规则);POST /api/tasks/{task_id}/experience-feedback
+ GET /api/tasks/{task_id}/experience-hints;归属 TaskQueryService.ensure_task_access
+ User.has_permission 全仓首次调用点
- src/moldinsight/api/__init__.py ROUTE_MODULES 注册新路由
- tests/test_model_ownership.py EXPECTED_TABLES 加 experience_feedback
(31→32)
- tests/test_experience_feedback_fingerprint.py(new)分桶参数化覆盖
bbox / volume / face / undercut / material / is_foam 各边界值
- tests/test_experience_feedback_router.py(new)API 契约 9 例
(401/403/422/200 路径 + 衰减续期 + 任务归属校验 + ORM 注册收口)
- docs/STATUS.md 顶部加 2026-09-23 批 1 日志条目
- docs/TECH_DEBT.md D17 加批 1 已完成描述 + 剩余工作清单
- docs/API_CONTRACT.md §3.2 加 D17 端点表格
测试基线:185 passed, 9 skipped(净增 59 测试)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-23 16:11:17 +08:00 |
|
cjw
|
64dc85bd14
|
批次5:inventory服务下沉收口 + Pydantic v2 / datetime弃用清零
- inventory业务层下沉(薄路由+service orchestration模式):
- customer/supplier/warehouse -> master_data_service
- material_routes(价格历史/趋势/供应商关联)-> material_service
- product_routes(CRUD/BOM/from-task跨模块桥接)-> product_service
- dashboard_routes(首页统计/低库存预警)-> dashboard_service
- inventory侧新增service回归覆盖(dashboard 2 / master_data 10 /
material 10 / product 14),含跨模块桥接测试种子
- Pydantic v2弃用清零:全仓14处 class Config 全部迁移到
model_config = ConfigDict(from_attributes=True)(含 shared auth)
- datetime.utcnow() 弃用清零:auth_service 3处统一改 datetime.now(timezone.utc)
- 同步文档:STATUS / ROADMAP / TECH_DEBT(D12清偿)/ AGENTS 代码地图
测试基线:126 passed, 4 skipped(无deprecation warning)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-22 16:13:45 +08:00 |
|
cjw
|
c51e6b793a
|
x
|
2026-09-18 18:21:01 +08:00 |
|
cjw
|
e728dcd226
|
批次4后续专项完成:D11清偿 + OCC方案B实施 + 部署参数 + D2诚实标注 + CI门禁
① D11 HTML 报告 RustFS 单源化(TECH_DEBT P2 清偿):可视化产物写任务临时目录后
裸传报告键 html/reports/{filename}(文件名寻址),/html StaticFiles 挂载删除,
新增 html_report_router 根路径代理(报告键→遗留 JSON 包装→本地卷兜底→404,
防穿越);URL 形状 /html/{filename} 不变,持久化引用零迁移;celery 摘除
html_data 卷,镜像不再烤入陈旧报告;顺带删除 get_stp_file_with_data 死数据块
② OCC 方案 B(D10 清偿):run_occ(op_name, payload) 契约 + 常驻工作进程池
(occ_process_pool + occ_worker 操作注册表),超时/崩溃 terminate 换新补位、
任务级超时 recover 整体重建,残留线程泄漏根治;TopoDS 不跨进程(generate_cavity
分模 + 方案 STEP 持久化全在子进程内,返回 export_manifest);删除内存形状缓存链、
CADExporter.export_mold_results、shape_loader(→ stp_materializer)
③ OCC 方案 A 部署参数:CELERY_CONCURRENCY / CELERY_MAX_TASKS_PER_CHILD 进
Dockerfile.celery + compose + .env.example
④ D2 诚实标注:铝价响应带 source: "simulated",前端按来源渲染标注(原硬编码
"上海期货交易所"属虚假声明),死代码 getAluminumPrice 删除
⑤ CI 门禁:.gitea/workflows/ci.yml 三 job(pytest / 前端构建含 vue-tsc /
openapi 漂移检测)
接口变更三件套随批完成(openapi 76→77 paths + gen:api + 前端构建通过;方案 B
接口面零变化)。测试基线 143 passed, 0 skipped(新增 16 项)。文档六处同步。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-18 17:22:01 +08:00 |
|
cjw
|
0e6b3b1811
|
后端设计治理:批次 0-4 全部完成(安全/部署/一致性/结构/架构)
按 ROADMAP §3.1 治理批次推进的后端设计审查整改:
- 批次 0(安全):/api/status/{task_id} 补 JWT 鉴权与任务归属校验;
pythonocc_available 真实探测;bcrypt 超 72 字节显式拒绝;
SECRET_KEY/RUSTFS_* 惰性校验,代码侧弱默认移除
- 批次 1(部署正确性):主处理链路改走 RustFS(分派入参 stp_file_id 化,
worker 按 object_key 下载);AUTO_MIGRATE 开关 + 迁移目录 alembic/→migrations/
修复包遮蔽(自动迁移此前从未真正生效);OCC 镜像改 conda 原生执行 +
基础镜像 tag 锁定;compose 关键项改 ${VAR:?} 强制显式配置
- 批次 2(任务一致性):删除 Redis 进程内存回退,PG 为任务状态单一事实源;
批量元数据入库(processing_tasks.batch_id,迁移 a3f8c2d91e47);
型腔失败任务标 failed 不再静默 completed;事务边界收口
(数据本体写 flush-only、失败先回滚再置 failed、进度更新保留即时 commit)
- 批次 3(API 与代码结构):592 行 advanced_router 拆为 design/cost/machining/
export 四子路由,请求体全量 Pydantic 化;ROUTE_MODULES + route_registry
(/api/health 呈现 degraded,DEBUG fail fast);纯计算端点统一 to_thread;
StorageIntegrationService 按职责三拆;MAX_FILE_SIZE 接线生效、
celery 复用 Settings.redis_url;管理员重置密码改 JSON body(端到端断裂修复);
openapi.json 重导出(76 paths)+ 前端 gen:api
- 批次 4(架构演进):共享 ORM 按模块拆分(shared/models/base.py + identity.py、
moldinsight/models/、inventory/models/,删除三条无使用方的跨模块
relationship,跨模块桥接收敛为裸 FK 硬规则,无兼容 facade);
OCC executor 重建补 cancel_futures=True(消除旧队列被慢恢复线程
并行消化的数据竞争);OCC 吞吐方案设计先行
(docs/topics/performance/OCC_THROUGHPUT.md);顺手清偿 D15
(vite.config.ts 未用参数致 npm run build 失败)
测试基线:125 passed, 2 skipped(pytest + sqlite+aiosqlite;归属边界、
路由契约、配置治理、鉴权回归等随批新增)
文档同步:STATUS / TECH_DEBT / ROADMAP / ARCHITECTURE / API_CONTRACT /
OPERATIONS / AGENTS
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-09-17 16:15:49 +08:00 |
|
cjw
|
4537faf2c4
|
优化
|
2026-09-16 17:55:04 +08:00 |
|
cjw
|
5e531ffe1e
|
文档目录结构简洁化
|
2026-09-01 18:05:18 +08:00 |
|
cjw
|
bee439cf34
|
x
|
2026-08-31 18:01:34 +08:00 |
|
cjw
|
a330757946
|
xx
|
2026-07-30 11:01:00 +08:00 |
|
cjw
|
853c478657
|
xxx
|
2026-07-30 10:30:50 +08:00 |
|
cjw
|
cf6d708566
|
xxx
|
2026-07-27 15:54:25 +08:00 |
|
cjw
|
00ca81287e
|
feat(db): 引入 Alembic 取代裸 DDL 迁移
- alembic init + env.py 接 settings/models metadata(asyncpg->psycopg2 同步 URL)
- 补 3 个 CheckConstraint 到 models(原只在裸 DDL)
- 离线生成初始迁移(31 表+约束+95 索引,全 sa.* 通用类型)
- init_db 用 _run_alembic_migrations(自动基线+upgrade head)替换 create_tables+ensure_schema_updates(删 92 行裸 DDL)
- 删破坏性 migrate_db.py(drop_all)
- 既有 DB 首次启动自动 stamp 基线,无需手动
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-20 11:04:23 +08:00 |
|
cjw
|
66ba6e00f5
|
refactor(moldinsight): 引入可插拔注册表(MoldGenerator + FeatureDetector)
- 新增 MoldGeneratorRegistry:multi_scheme_planner 消除 if-else,按 mold_type 选生成器
- 新增 FeatureDetectorRegistry:geometry_analyzer._detect_features 消除 6 个检测器硬编码
- 新增模具类型/特征检测器只需 register 一行
- 移除 OCC ThreadPoolExecutor(注册表本身串行执行)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-20 11:03:16 +08:00 |
|
cjw
|
f3d2951dc3
|
x
|
2026-07-20 10:16:27 +08:00 |
|
cjw
|
8493f0df03
|
init
|
2026-07-13 17:44:50 +08:00 |
|
cjw
|
975fa1ffac
|
init
|
2026-07-13 17:44:37 +08:00 |
|
cjw
|
6b3188e693
|
x
|
2026-06-23 09:38:31 +08:00 |
|
cjw
|
f6d8829071
|
x
|
2026-06-16 11:15:03 +08:00 |
|
cjw
|
f71a48d3b8
|
x
|
2026-06-12 13:55:38 +08:00 |
|
cjw
|
fdbde938f9
|
x
|
2026-06-09 16:19:15 +08:00 |
|
cjw
|
4151e4963b
|
x
|
2026-06-09 15:44:17 +08:00 |
|
cjw
|
fa2178fbd8
|
x
|
2026-06-09 13:44:53 +08:00 |
|
cjw
|
8cca6f9d32
|
x
|
2026-06-02 09:55:06 +08:00 |
|
cjw
|
b22431d3cb
|
x
|
2026-06-01 10:44:08 +08:00 |
|
cjw
|
77bdf56adf
|
重写独立dockerfile
|
2026-05-29 18:19:30 +08:00 |
|
cjw
|
823a387118
|
后端模块拆分
|
2026-05-29 18:10:08 +08:00 |
|
cjw
|
5bb9bc84ea
|
前端重构 Vite
|
2026-05-29 17:30:26 +08:00 |
|
cjw
|
3443763fbf
|
x
|
2026-05-29 09:47:21 +08:00 |
|
cjw
|
44902207c9
|
增加celery任务队列,任务持久化(服务重启不丢)、支持多 Worker 水平扩展、失败自动重试
|
2026-05-28 17:59:39 +08:00 |
|
cjw
|
6ad22e4466
|
优化整体任务性能
|
2026-05-28 17:41:02 +08:00 |
|
cjw
|
2ffe8ecbb3
|
x
|
2026-05-27 16:15:01 +08:00 |
|
cjw
|
9882d3becc
|
导出step文件合并为整体,方便后续修改
|
2026-05-27 14:57:03 +08:00 |
|
cjw
|
26613676f8
|
x
|
2026-05-25 18:35:33 +08:00 |
|
cjw
|
63bee26ab8
|
x
|
2026-05-25 10:16:05 +08:00 |
|
cjw
|
08d5a45c80
|
x
|
2026-05-18 16:45:17 +08:00 |
|
cjw
|
224330598a
|
x
|
2026-05-14 16:56:18 +08:00 |
|
cjw
|
fd1f43f278
|
x
|
2026-05-12 10:23:58 +08:00 |
|
cjw
|
74bbca90e3
|
x
|
2026-05-11 18:05:27 +08:00 |
|
cjw
|
c9672d9685
|
fix: 恢复 init_db.py 等全部缺失文件 + LLM 集成
|
2026-05-11 15:35:54 +08:00 |
|
cjw
|
4667346669
|
x
|
2026-05-11 14:46:20 +08:00 |
|
cjw
|
eaf37b9a03
|
x
|
2026-05-11 14:15:39 +08:00 |
|
cjw
|
a68b9ca57f
|
x
|
2026-05-11 11:35:15 +08:00 |
|
cjw
|
5e1d475a22
|
x
|
2026-05-11 09:34:50 +08:00 |
|
cjw
|
5d2ca3f782
|
x
|
2026-05-07 16:51:21 +08:00 |
|