Skip to content

fix: 修正 combined_app 未執行啟動流程導致課程資料為空 - #257

Merged
l7wei merged 2 commits into
NTHU-SA:mainfrom
ChiuKuanHsun:fix/combined-app-lifespan
Aug 31, 2026
Merged

fix: 修正 combined_app 未執行啟動流程導致課程資料為空#257
l7wei merged 2 commits into
NTHU-SA:mainfrom
ChiuKuanHsun:fix/combined-app-lifespan

Conversation

@ChiuKuanHsun

@ChiuKuanHsun ChiuKuanHsun commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

combined_app 只複製了 fast_api_app 的路由,lifespan 卻直接指定為 mcp_app.lifespan,導致 create_app() 內宣告的啟動流程從未執行。其他 domain 都在請求當下才取資料所以不受影響,但 courses_service 僅在啟動時載入,因此課程相關端點在線上恆回傳空陣列。

Fixes

  • 修正 combined_app 未執行應用程式 lifespan,導致 /courses//courses/search/courses/lists/{list_name} 恆回傳空陣列(自 feat: add MCP interface, optimize OpenAPI spec and performance #227 引入)
  • 啟動報告的 / 改為 ASCII 標記,避免在非 UTF-8 主控台(如 Windows cp950)拋出 UnicodeEncodeError

Notes

  • 重現方式GET https://api.nthusa.tw/courses/ 回傳 []。本機執行 app 的 lifespan 後 courses_service.course_data 長度為 0,且啟動時的 Starting application... / pre-fetch 訊息完全沒有輸出。
  • 為什麼既有測試沒有發現:測試以 ASGITransport 呼叫 app,預設不會執行 lifespan;且課程相關測試僅斷言 status_code == 200,而空陣列同樣是 200。
  • 回歸測試驗證:將 lifespan 改回 mcp_app.lifespan 後,新增的 test_courses_endpoint_returns_data_after_startup 會以 assert [] 失敗;套用修正後通過。
  • 本機測試結果:682 passed,coverage 91.33%。blackisort --profile black 皆通過。

combined_app 只複製 fast_api_app 的路由,lifespan 卻直接指定為
mcp_app.lifespan,導致預抓資料與 service 初始化從未執行。其他 domain
在請求當下才取資料所以不受影響,但 courses_service 僅在啟動時載入,
使 /courses/、/courses/search、/courses/lists/{list_name} 恆回傳空陣列。

- 將 MCP 與應用程式兩個 lifespan 串接為 combined_lifespan
- 啟動報告改用 ASCII 標記,避免非 UTF-8 主控台的 UnicodeEncodeError
- 新增 tests/test_app_lifespan.py 涵蓋此回歸

此問題自 6dab59f (NTHU-SA#227) 引入。既有測試以 ASGITransport 呼叫 app,
預設不會執行 lifespan,且僅斷言狀態碼 200,因此空陣列無法被偵測。

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the exported FastAPI app’s startup behavior by ensuring the combined app (MCP routes + API routes) actually executes the application startup lifespan that prefetches data and initializes stateful services (notably courses_service, which only loads at startup). It also adjusts startup status output to be ASCII-only to avoid console encoding errors.

Changes:

  • Chain MCP lifespan and the existing application lifespan() via a new combined_lifespan, and attach it to combined_app.
  • Replace Unicode status marks ( / ) with ASCII markers ([OK] / [FAIL]) in startup reporting.
  • Add regression tests covering combined lifespan wiring and ASCII startup output.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/data_api/api/api.py Introduces combined_lifespan and attaches it to the served combined_app; updates startup status output to ASCII markers.
tests/test_app_lifespan.py Adds tests to guard against lifespan wiring regressions and validate ASCII-only startup reporting.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/test_app_lifespan.py Outdated
test_courses_endpoint_returns_data_after_startup 原本會執行真實的
prefetch 與 update_data,使測試同時依賴上游資料源;失敗時無法分辨是
lifespan 接線錯誤,還是 data.nthusa.tw 當下不可用。

改為 stub nthudata.get 與 MCP lifespan,讓真正的 update_data 對固定的
記憶體資料執行。app.router.lifespan_context 予以保留,因為那才是驗證
「實際被啟動的 app 是否掛上應用程式 lifespan」的部分,回歸偵測能力不變:
將 lifespan 改回 mcp_app.lifespan 後,測試仍以 assert [] 失敗。

一併解除 MCP session manager 每個 process 僅能啟動一次的限制,
後續在此檔案新增測試不需再繞開。執行時間 15.4s 降至 5.0s。
@sonarqubecloud

Copy link
Copy Markdown

@l7wei
l7wei self-requested a review August 31, 2026 02:39
@l7wei
l7wei merged commit e2930dd into NTHU-SA:main Aug 31, 2026
5 checks passed
@l7wei

l7wei commented Aug 31, 2026

Copy link
Copy Markdown
Member

Hi @ChiuKuanHsun ,
Thanks for your 1st PR for NTHU-Data-API, merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants