feat: /api/collect 트리거 + 이력 조회 (#4) #29

Merged
xhh merged 1 commit from issue-4-collect-api into main 2026-04-22 03:02:08 +09:00
Owner

요약

운영 대시보드(#22) 용 수동 수집 트리거 + 이력 조회 API. 이번 PR 은 5개 엔드포인트. daily/backfill 은 APScheduler #5 와 통합.

엔드포인트

  • 조회: GET /logs (원본), GET /history (일자×수집기 집계)
  • 트리거: POST /single, POST /insider, POST /margin-debt

공통 응답 TriggerResponse (duration_ms, success_count, failed_count, results[]).

구현 포인트

  • 외부 호출 함수는 _run_* 로 분리 → monkeypatch 로 테스트 가능
  • _wrap_trigger 가 예외를 failed 로 구조화 (500 대신 200 응답)
  • history 는 SQLAlchemy case() + func.sum() 집계, UTC 기준 경계

테스트 (11 case)

logs(empty/filters/days), history(empty/aggregation/filter), triggers(4 case + 예외 처리).

로컬 uv run pytest41 passed (누적 +11).

Closes #4

## 요약 운영 대시보드(#22) 용 수동 수집 트리거 + 이력 조회 API. 이번 PR 은 5개 엔드포인트. daily/backfill 은 APScheduler #5 와 통합. ## 엔드포인트 - **조회**: GET /logs (원본), GET /history (일자×수집기 집계) - **트리거**: POST /single, POST /insider, POST /margin-debt 공통 응답 TriggerResponse (duration_ms, success_count, failed_count, results[]). ## 구현 포인트 - 외부 호출 함수는 `_run_*` 로 분리 → monkeypatch 로 테스트 가능 - `_wrap_trigger` 가 예외를 failed 로 구조화 (500 대신 200 응답) - history 는 SQLAlchemy `case()` + `func.sum()` 집계, UTC 기준 경계 ## 테스트 (11 case) logs(empty/filters/days), history(empty/aggregation/filter), triggers(4 case + 예외 처리). 로컬 `uv run pytest` → **41 passed** (누적 +11). Closes #4
/api/collect 트리거 + 로그/이력 조회 엔드포인트 (#4)
All checks were successful
Tests (PR) / pytest (pull_request) Successful in 24s
ca93d31fa0
운영 대시보드(#22) 의 "수동 수집 트리거 + 수집 이력 타임라인" 섹션을 위한 API. 이번 PR 범위는 5개 엔드포인트 (daily/backfill 은 시간 소모가 커서 APScheduler #5 와 통합 예정).

## 엔드포인트

### 조회 (read)
- GET /api/collect/logs   — 원본 CollectionLog (days/limit/collection_type/status 필터)
- GET /api/collect/history — 일자×수집기 집계 (UI 타임라인 heatmap 용)

### 트리거 (write)
- POST /api/collect/single?symbols=SPY,QQQ
- POST /api/collect/insider?ticker=AMD&days=90
- POST /api/collect/margin-debt

## 공통 응답 TriggerResponse
started_at / finished_at / duration_ms / success_count / failed_count / results[{symbol, status, records, error}].

## 구현 포인트
- 실제 외부 호출(FRED/yfinance/SEC/FINRA) 로직은 라우터 내 `_run_single_symbols` / `_run_insider` / `_run_margin_debt` 함수로 감싸 monkeypatch 로 테스트 가능.
- `_wrap_trigger` 가 예외를 failed 로 변환해 항상 구조화된 응답 반환 (500 대신).
- history 쿼리는 SQLAlchemy `case()` + `func.sum()` 으로 일자×type 집계. 로컬 timezone 혼선 방지를 위해 `since = datetime.utcnow().date()` 로 UTC 기준 경계 사용 (CollectionLog.started_at 이 utcnow 로 기록되기 때문).

## 테스트 (11 case)
- logs: empty, type/status 필터, days cutoff
- history: empty, 일자×type 집계, collection_type 필터
- triggers: single(성공), single(빈 symbols → 400), insider(uppercase 변환), margin-debt, 예외 → failed 로 변환

외부 호출은 모두 monkeypatch 로 스텁. 네트워크 없이 실행.

로컬 uv run pytest -> **41 passed** (smoke 3 + watchlist 10 + reports 11 + coverage 6 + collect 11).

Closes #4

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
xhh merged commit 8eb8792184 into main 2026-04-22 03:02:08 +09:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
xhh/financial-data-platform!29
No description provided.