履歴書生成器のリファクタリングとエラーメッセージの一元化#270
Conversation
📝 WalkthroughWalkthroughThis PR consolidates error message handling through externalized localization, refactors resume data normalization into reusable helpers, tightens module boundaries, and expands test coverage to validate actual database state transitions during task execution and retry flows. ChangesBackend Refactoring: Error Handling, Resume Normalization, and Tests
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
Note Docstrings generation - SKIPPED |
Docstrings generation was requested by @yusuke0610. * #270 (comment) The following files were modified: * `backend/app/main.py` * `backend/app/routers/github_link.py` * `backend/app/routers/internal.py` * `backend/app/services/markdown/generators/resume_generator.py` * `backend/app/services/pdf/generators/resume_generator.py` * `backend/app/services/shared/resume_format.py` * `backend/tests/test_worker/_helpers.py` * `backend/tests/test_worker/test_execute_task.py` * `backend/tests/test_worker/test_github_link.py`
Summary
.claude/rules/backend/architecture.mdを現状木に同期(削除済みモジュール参照を一掃、routers/blogパッケージ・単一TaskType・shared/resume_format.py・休眠 LLM スタックを反映)。dispatch_serviceの docstring を単一タスク前提へ修正し、汎用抽象を「拡張ポイントとして意図的に保持」と明記。github_collectorの未使用 re-export facade(__all__の private 別名・デッド_detect_from_root_files・未使用DEPENDENCY_TO_FRAMEWORKimport)をトリムし、公開 API を実体(RepoData/collect_repos/GitHubUserNotFoundError)だけに縮小。messages.jsonへ寄せ、internal.pyの{exc}補間(info leak)を停止。resume_generatorのプレゼンテーション非依存な入力正規化をshared/resume_format.pyへ抽出(jscpd の resume clone 0 件化)。/run/retryの 409/404 競合パスと、run_github_link成功時のフェーズC書き戻し内容を assert するテストを追加。test_execute_taskの内部 mock 結合を DB state assert へ置換。Applied Changes
High
routers/blog.py・routers/career_analysis.py、models|schemas|repositories/career_analysis.py、services/career_analysis/一式、services/intelligence/{llm_summarizer,llm_advice_service,position_scorer}.py/position_weights.json、tasks/handlers/{blog_summarize,career_analysis}.py。core/env_keys.py、routers/blog/(accounts/score/sync)パッケージ、services/shared/resume_format.py、単一TaskType(GITHUB_LINK のみ)、markdown/pdf の generators/templates/utils 構成。Medium
AsyncTaskCacheService/_AsyncTaskRecord/TaskType引数は新規タスク追加の拡張ポイントとして意図的に汎用化。インライン化しない」へ修正(元レポート Findings/Medium)。__all__を 13 → 3 件(RepoData/collect_repos/GitHubUserNotFoundError)に縮小。再エクスポート理由をコメント明記。_detect_from_root_files(collect_reposから未呼び出し)を削除。DEPENDENCY_TO_FRAMEWORKimport を除去(skill_extractorはrepo_analyzerから直接 import しており、本モジュール経由参照は 0 件を grep 確認)。from ...github_collector import *の利用者 0 件、private 別名の外部参照 0 件。collect_reposが実際に使う関数のみ import に残置。messages.jsonにerror.task.unknown_task_type/error.task.execution_failed/error.github_link.not_retryable/error.validation.invalid_inputを追加。get_error(...)参照に置換。internal.py:102のdetail=f"...: {exc}"を{exc}補間なしの定型文へ変更(例外詳細は直前のlogger.exceptionのみに残す)。これに伴い未使用化したexcept Exception as exc:をexcept Exception:へ。Low
response_mapperpassthrough は元レポートで「現状維持で可」と判断済み)。Test Changes
Removed
Added
TestRetryEndpointsに追加:test_retry_returns_404_when_no_cache— キャッシュ未作成で 404。test_retry_returns_409_when_not_dead_letter(parametrize: completed / processing / pending / retrying)— dead_letter 以外は 409、かつ状態が変化しないことを assert(ガード1:is_retryable_terminal()False)。test_retry_returns_409_on_concurrent_reset_race—is_retryable_terminalは通過するがtry_reset_to_pendingが並列競合で False を返す TOCTOU ガード(ガード2)で 409。test_completed_persists_mapped_result_content— フェーズC でmap_pipeline_resultの出力がcache.resultへそのまま永続化され、status="completed"・前回の error/warning がクリアされることを内容まで assert(既存test_status_transitions_to_completedはresult is not None止まりだった)。Changed (内部 mock → DB state 寄せ)
test_execute_task_marks_dead_letter_on_errorを、_mark_dead_letterの patch +call_argsassert(実装詳細結合)から、実 DB セッションでの結果 state assert(cache.status == "dead_letter"、error_messageに例外文字列、completed_at設定)へ置換(元レポート Test Review)。keep_open_session(worker のdb.close()を no-op 化するプロキシ)をパッケージ共有ヘルパとして追加。Duplication Resolved
resume_generatorのプレゼンテーション非依存な入力正規化を以下の 3 関数として抽出(元レポート Duplication/Medium):normalize_clients(experience)— 旧スキーマ後方互換(clients不在時にprojectsを無名取引先 1 件へ畳む)。md:旧61-63 / pdf:旧191-193 の 7 行 clone を解消。normalize_team(project)— 旧スキーマ後方互換(team不在時にscaleから{"total":..., "members":[]})。md/pdf 両方の重複を解消。group_stacks_by_category(stacks)—technology_stacksの category 別グルーピング(挿入順保持)。format_period・エスケープは各ジェネレータに残置(元レポートの「意図的に共通化しない」判断を尊重)。make dupe-checkでresume_generator関連 clone は 0 件(実行前後で resume clone が消えたことを jscpd レポートで確認)。Structure Changes
shared/resume_format.pyへの関数追加のみ。Skipped
Validation
make lint-backend: pass(All checks passed!)。github_collector/ resume 系の import 並びは ruff--fixでプロジェクト規約(per-symbol import)に整形済み。make test-backend: pass(420 passed, 2 warnings / 28.6s)。warning 2 件は既存・本変更と無関係(reportlab のast.NameConstantDeprecationWarning、test_github_link.py:346の event loop warning)。make dupe-check: 全 44 clones(resume clone は 0 件化。残りは元レポートで「Allowed Duplication」分類済みの SQLAlchemy boilerplate / テストスキャフォールド / schema field 列)。~/.cache/nix/fetcher-locks/*.lock書き込み拒否で落ちるため、nix 実行はdangerouslyDisableSandbox: trueで実施(CLAUDE.md の既知例外)。Follow-ups
resume_generator自体の単体テストが未整備(カバレッジ 6% / 12%)。normalize_clients/normalize_team/group_stacks_by_categoryの旧スキーマ後方互換フォールバック分岐は今回も未カバーのまま(抽出前から存在するギャップ)。次回どちらかのジェネレータを触る際に、shared 化した 3 関数のユニットテスト(新旧スキーマ両入力)を追加するのが望ましい。action文字列は既存実装に倣い inline リテラルのまま(messageのみ SSoT 化)。actionも SSoT へ寄せるかは別途方針判断。Summary by CodeRabbit
Bug Fixes
Documentation