Skip to content

[Feat] 라이브 액티비티 기능 추가#99

Merged
pooreumjung merged 12 commits into
developfrom
feat/#49-live-activity
May 24, 2026
Merged

[Feat] 라이브 액티비티 기능 추가#99
pooreumjung merged 12 commits into
developfrom
feat/#49-live-activity

Conversation

@pooreumjung

@pooreumjung pooreumjung commented May 24, 2026

Copy link
Copy Markdown
Member

🧾 요약

  • 라이브 액티비티에서 코스 기반 진행률 계산에 필요한 코스 좌표, 전체 거리, 예상 소요 시간 조회 API를 추가
  • 서버 DB의 courses.polyline 데이터를 기반으로 좌표 배열을 응답하도록 구성
  • 활성 트래킹 세션 중복 생성을 DB 제약과 애플리케이션 예외 처리로 방지

🔗 이슈

✨ 변경 내용

  • GET /api/tracking/live-activity/courses/{courseId} API 추가
  • Course.polylineLineString으로 매핑하고, 응답 시 { latitude, longitude } 배열로 변환
  • 코스 polyline이 없거나 비어 있으면 422 TRK_422_1 에러 반환
  • 유저별 활성 트래킹 세션 중복 방지를 위한 partial unique index 추가
  • unique index 충돌 시 TRACKING_SESSION_ALREADY_IN_PROGRESS 예외로 변환
  • 트래킹 통계 조회 Redis Hash 로직 정리
  • 트래킹 세션 응답의 @JsonInclude(NON_NULL) 적용 범위를 hikingRecordId로 축소

✅ 확인

  • 빌드 OK (./gradlew compileJava)
  • 테스트 OK

Summary by CodeRabbit

  • New Features

    • New API endpoint to retrieve detailed course information for live activity tracking, including route coordinates, distance, and estimated time.
    • Added repository guidance document with comprehensive usage, architecture, and contribution guidelines in Korean.
  • Bug Fixes

    • Prevented duplicate concurrent active tracking sessions per user with database-level constraints.
    • Added error handling for missing course route data with clear user-facing error responses.

Review Change Stack

@pooreumjung pooreumjung self-assigned this May 24, 2026
@pooreumjung pooreumjung added the enhancement New feature or request label May 24, 2026
@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2b2f6647-4c20-4646-b3c8-4404a73b0d4f

📥 Commits

Reviewing files that changed from the base of the PR and between 97b4742 and a096dca.

📒 Files selected for processing (4)
  • CLAUDE.md
  • src/main/java/com/semosan/api/domain/tracking/controller/docs/TrackingControllerDocs.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionService.java
  • src/main/resources/db/migration/V16__add_tracking_session_active_unique_index.sql
✅ Files skipped from review due to trivial changes (1)
  • CLAUDE.md

📝 Walkthrough

Walkthrough

Adds a live-activity course API that returns polyline coordinates, persists Course polylines, enforces one active tracking session per user via migration/index, centralizes session-save error translation, refines session response JSON, simplifies Redis stats reads, and adds developer documentation.

Changes

Live Activity Course API and Session Robustness

Layer / File(s) Summary
Course polyline persistence model
src/main/java/com/semosan/api/domain/mountain/entity/Course.java, src/main/resources/db/migration/V16__add_tracking_session_active_unique_index.sql
Course entity adds a LineString polyline mapped as geography(LineString, 4326). Migration ranks existing active sessions, abandons duplicates, and creates a partial unique index uq_tracking_sessions_user_active to enforce a single active session per user.
Live activity DTO and status enums
src/main/java/com/semosan/api/common/status/ErrorStatus.java, src/main/java/com/semosan/api/common/status/SuccessStatus.java, src/main/java/com/semosan/api/domain/tracking/dto/response/LiveActivityCourseResponse.java
Added TRACKING_COURSE_POLYLINE_REQUIRED and TRACKING_LIVE_ACTIVITY_COURSE_SUCCESS enums. LiveActivityCourseResponse.from(Course) validates polyline presence and converts JTS Coordinates into CoordinateInfo records mapping y→latitude, x→longitude; throws TRACKING_COURSE_POLYLINE_REQUIRED if missing.
Live activity API endpoint
src/main/java/com/semosan/api/domain/tracking/controller/TrackingController.java, src/main/java/com/semosan/api/domain/tracking/controller/docs/TrackingControllerDocs.java, src/main/java/com/semosan/api/domain/tracking/service/TrackingService.java
Adds GET /api/tracking/live-activity/courses/{courseId} controller method and Swagger docs. Service getLiveActivityCourse(userId, courseId) validates active user, loads Course, maps to LiveActivityCourseResponse, or throws COURSE_NOT_FOUND.
Tracking session robustness improvements
src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionService.java, src/main/java/com/semosan/api/domain/tracking/dto/response/TrackingSessionResponse.java, src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionStatsService.java
TrackingSessionService.create() delegates to saveSession() which catches DataIntegrityViolationException and translates the specific active-session unique-index violation into TRACKING_SESSION_ALREADY_IN_PROGRESS. TrackingSessionResponse moves @JsonInclude(NON_NULL) to the hikingRecordId field. TrackingSessionStatsService.getStats() reads Redis hash entries directly.
Developer documentation
CLAUDE.md
Adds repository guidance in Korean covering Claude interaction rules, Gradle build/test/run commands, architecture and API conventions, auth/tracking flow, migration strategy, env vars, and PR/contribution conventions.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant TrackingController
  participant TrackingService
  participant UserReader
  participant CourseRepository

  Client->>TrackingController: GET /api/tracking/live-activity/courses/{courseId}
  TrackingController->>TrackingService: getLiveActivityCourse(userId, courseId)
  TrackingService->>UserReader: findActiveUserById(userId)
  UserReader-->>TrackingService: User (validated)
  TrackingService->>CourseRepository: findById(courseId)
  CourseRepository-->>TrackingService: Course (with polyline)
  TrackingService->>TrackingService: LiveActivityCourseResponse.from(course)
  Note over TrackingService: Validate polyline non-null/non-empty\nConvert LineString coordinates (y→lat, x→lon)
  TrackingService-->>TrackingController: LiveActivityCourseResponse
  TrackingController-->>Client: 200 OK (ApiResponse success)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • SEMOSAN/SEMOSAN_BE#83: Adds/uses Course polyline; related to this PR's polyline storage and live-activity endpoint.
  • SEMOSAN/SEMOSAN_BE#54: Overlaps with Redis hash handling and tracking-session stats changes.
  • SEMOSAN/SEMOSAN_BE#68: Related tracking endpoints and status enum changes; intersects with added live-activity endpoint and error codes.

Suggested reviewers

  • howooyeon

Poem

🐰 A polyline curled like a trail in the sun,
Coordinates hop out, the Live Activity’s begun.
Sessions stay single, the DB hums clear,
Docs whisper rules to each careful ear.
nibbles a carrot, ships the code

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feat/#49 live activity' is vague and generic. It includes a reference number and broad feature name without clearly conveying the primary technical change or implementation details. Use a more descriptive title that highlights the main change, such as 'Add live activity course endpoint with polyline coordinates' or 'Implement course polyline retrieval for live activity tracking'.
Linked Issues check ❓ Inconclusive The linked issue #49 contains only an empty template with no specific requirements, acceptance criteria, or implementation details. The PR appears to implement live activity features as described in the PR objectives, but lacks formal validation against defined requirements. The linked issue should be updated with specific acceptance criteria and requirements to enable proper validation that the implementation meets the stated objectives.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Out of Scope Changes check ✅ Passed All changes align with the live activity feature scope: new API endpoint for course polyline retrieval, database schema updates for LineString, error/success status enums, session uniqueness enforcement, and response DTO formatting adjustments.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#49-live-activity
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/#49-live-activity

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLAUDE.md`:
- Line 27: The fenced code blocks in CLAUDE.md are missing language identifiers
and trigger markdownlint MD040; update the two affected triple-backtick blocks
by adding "text" after the opening backticks so they become "```text" (i.e.,
replace the bare ``` used for the listing and for the branch-name examples),
ensuring both occurrences are updated to silence the lint warning and preserve
content formatting.

In
`@src/main/java/com/semosan/api/domain/tracking/controller/docs/TrackingControllerDocs.java`:
- Around line 47-68: The Swagger docs for getLiveActivityCourse in
TrackingControllerDocs are missing the 422 response for missing course polyline
(TRK_422_1); add an `@ApiResponse` entry with responseCode = "422", a descriptive
message (e.g., "코스 polyline 누락 - TRK_422_1"), and content = `@Content`(schema =
`@Schema`(implementation = ApiResponse.class)) alongside the existing 200 and 404
responses so the OpenAPI contract reflects the actual error case.

In
`@src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionService.java`:
- Around line 152-157: The saveSession method in TrackingSessionService
currently maps every DataIntegrityViolationException from
trackingSessionRepository.save(session) to
ErrorStatus.TRACKING_SESSION_ALREADY_IN_PROGRESS; change this to only map the
specific unique/constraint violation that indicates "active session already
exists" (inspect the exception's rootCause message/constraint/index name against
the actual migration constraint name) and throw
GeneralException(ErrorStatus.TRACKING_SESSION_ALREADY_IN_PROGRESS) only in that
case, otherwise rethrow the original DataIntegrityViolationException or convert
to a more appropriate ErrorStatus so FK/NOT NULL and other integrity errors are
not misclassified.

In
`@src/main/resources/db/migration/V16__add_tracking_session_active_unique_index.sql`:
- Around line 3-5: The partial unique index creation
uq_tracking_sessions_user_active on table tracking_sessions (WHERE status IN
('IN_PROGRESS','PAUSED')) can fail if existing duplicate active sessions exist,
so add a preceding Flyway backfill migration that finds and resolves duplicates
before this migration runs: create a new migration that (1) identifies duplicate
rows by user_id with status IN ('IN_PROGRESS','PAUSED'), (2) deterministically
keeps one row per user (e.g., by earliest/ latest created_at or a chosen
business rule) and either deletes or marks others as non-active, and (3)
verifies no remaining duplicates, then keep the current V16 migration to create
uq_tracking_sessions_user_active; ensure the new migration runs earlier than V16
and includes safe, idempotent operations and audit logging as needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 53d0ac48-849e-4373-be21-624741faf728

📥 Commits

Reviewing files that changed from the base of the PR and between 366a9e2 and 97b4742.

📒 Files selected for processing (12)
  • CLAUDE.md
  • src/main/java/com/semosan/api/common/status/ErrorStatus.java
  • src/main/java/com/semosan/api/common/status/SuccessStatus.java
  • src/main/java/com/semosan/api/domain/mountain/entity/Course.java
  • src/main/java/com/semosan/api/domain/tracking/controller/TrackingController.java
  • src/main/java/com/semosan/api/domain/tracking/controller/docs/TrackingControllerDocs.java
  • src/main/java/com/semosan/api/domain/tracking/dto/response/LiveActivityCourseResponse.java
  • src/main/java/com/semosan/api/domain/tracking/dto/response/TrackingSessionResponse.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingService.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionService.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionStatsService.java
  • src/main/resources/db/migration/V16__add_tracking_session_active_unique_index.sql

Comment thread CLAUDE.md Outdated
@pooreumjung
pooreumjung merged commit 65543c6 into develop May 24, 2026
@pooreumjung pooreumjung changed the title Feat/#49 live activity [Feat] 라이브 액티비티 기능 추가 May 25, 2026
@howooyeon
howooyeon deleted the feat/#49-live-activity branch May 29, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 라이브액티비티

1 participant