Skip to content

refactor: 좋아요 알림 재발송 문제 해결 - #1440

Merged
KEEKE132 merged 9 commits into
devfrom
refactor/#1439-noti
Aug 6, 2026
Merged

refactor: 좋아요 알림 재발송 문제 해결#1440
KEEKE132 merged 9 commits into
devfrom
refactor/#1439-noti

Conversation

@KEEKE132

@KEEKE132 KEEKE132 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🚩 관련사항

Closes #1439

📢 전달사항

좋아요 알림이 발송된 뒤 좋아요를 취소하고 다시 눌러 같은 마일스톤에 재도달하면, 동일한 알림이 반복해서 발송되는 문제가 있었습니다.

이를 해결하기 위해 게시글과 마일스톤 조합을 영구적으로 기록하는 PostLikeMilestoneAchievement를 추가했습니다. (post_id, milestone_count) 조합에 유니크 제약조건을 이용해 방지합니다.

기존 마일스톤 정책은 그대로 유지했습니다.

  • 좋아요 5, 10, 50, 100, 500개
  • 좋아요 1,000개부터 1,000개 단위

기존 게시글은 마이그레이션 시점의 좋아요 수를 기준으로 이미 도달한 마일스톤을 BASELINED 상태로 기록합니다. 이 과정에서는 과거 알림을 발송하지 않습니다.

좋아요 저장을 우선하기 위해 알림 처리는 좋아요 트랜잭션 커밋 후 시작합니다. 이벤트 흐름은 아래 두 종류로 단순화했습니다.
PostLikeMilestoneReachedEvent
→ 마일스톤 이력 기록
→ 알림·알림 로그·처리 상태 저장
PostLikeMilestonePushEvent
→ DB 커밋 후 푸시 발송

본인 좋아요, 알림 설정 OFF, 차단 관계, 삭제된 게시글·게시판 또는 탈퇴한 작성자는 알림을 발송하지 않되 각각의 사유와 함께 저장합니다.

정상 알림은 Notification, NotificationLog, 마일스톤 처리 상태를 하나의 트랜잭션에서 저장합니다. 이 트랜잭션이 커밋된 뒤에만 푸시를 요청합니다.

📸 스크린샷

📃 진행사항

  • 좋아요 마일스톤 판정 정책 분리
  • 게시글별 마일스톤 소비 이력 및 유니크 제약 추가
  • 기존 게시글의 도달 마일스톤 기준선 처리
  • 마일스톤에서만 알림 이벤트가 발행되도록 변경
  • 알림 미발송 사유 및 처리 상태 기록
  • 알림·로그 커밋 이후 푸시 발송
  • 테스트 및 코드 포맷 검사

⚙️ 기타사항

서비스 규모에 맞춰 동시성은 일단 고려하지 않았습니다.

개발기간: 2026.08.01

Summary by CodeRabbit

  • 새로운 기능

    • 게시글 좋아요 수가 주요 마일스톤에 도달하면 작성자에게 알림과 푸시 알림을 제공합니다.
    • 기존 게시글의 좋아요 마일스톤을 기준선으로 반영해 과거 활동으로 인한 알림을 방지합니다.
    • 동일한 마일스톤에 대한 중복 알림을 방지합니다.
  • 개선 사항

    • 본인 좋아요, 알림 설정, 차단 및 게시글·작성자 상태에 따라 알림을 적절히 제한합니다.
    • 알림 처리 상태를 관리해 실패나 중복 상황에서도 안정적으로 동작합니다.

@KEEKE132 KEEKE132 self-assigned this Aug 1, 2026
@github-actions github-actions Bot added the D-3 label Aug 1, 2026
@github-actions
github-actions Bot requested a review from glucosei August 1, 2026 05:39
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

게시글 좋아요 처리를 마일스톤 도달 이벤트 방식으로 변경했습니다. 마일스톤 달성 이력과 기존 게시글 기준선 적재를 추가했습니다. 알림 조건을 검증한 뒤 상태를 기록하고, 커밋 후 푸시를 비동기로 전송합니다.

Changes

좋아요 마일스톤 알림

Layer / File(s) Summary
마일스톤 이벤트 발행과 정책
app-main/src/main/java/net/causw/app/main/domain/community/post/service/LikePostService.java, app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/policy/LikePostNotificationPolicy.java, app-main/src/main/java/net/causw/app/main/domain/notification/notification/event/PostLikeMilestoneReachedEvent.java, app-main/src/test/java/net/causw/app/main/domain/community/post/service/LikePostServiceTest.java, app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/policy/LikePostNotificationPolicyTest.java
좋아요 저장 후 좋아요 수가 마일스톤이면 PostLikeMilestoneReachedEvent를 발행합니다. 마일스톤이 아니면 이벤트를 발행하지 않습니다.
마일스톤 기록 저장과 기준선
app-main/src/main/java/net/causw/app/main/domain/notification/notification/entity/PostLikeMilestoneAchievement.java, app-main/src/main/java/net/causw/app/main/domain/notification/notification/enums/*, app-main/src/main/java/net/causw/app/main/domain/notification/notification/repository/PostLikeMilestoneAchievementRepository.java, app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievement{Reader,Recorder,Writer}.java, app-main/src/main/resources/db/migration/*, app-main/src/test/java/net/causw/app/main/domain/notification/notification/entity/*, app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievement*Test.java, app-main/src/test/java/net/causw/app/main/SchemaValidationTest.java
게시글과 마일스톤의 중복을 제한하는 엔티티와 저장소를 추가했습니다. PENDING, BASELINED, NOTIFICATION_CREATED, SUPPRESSED 상태를 저장합니다. 기존 게시글의 달성 마일스톤은 알림 없이 BASELINED 상태로 적재합니다.
알림 조건 검증과 처리
app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessor.java, app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestoneReachedListener.java, app-main/src/main/java/net/causw/app/main/domain/notification/notification/event/PostLikeMilestonePushEvent.java, app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessorTest.java, app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestoneReachedListenerTest.java
대상 게시글과 작성자 상태, 본인 좋아요, 알림 설정, 차단 여부를 확인합니다. 조건에 맞지 않으면 억제 사유를 기록합니다. 조건을 만족하면 알림과 로그를 저장하고 달성 상태를 변경합니다.
커밋 후 푸시 전송
app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestonePushListener.java, app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestonePushListenerTest.java
AFTER_COMMIT 비동기 리스너가 수신자를 조회하고 PostLikeMilestonePushEvent의 메시지와 데이터를 사용해 푸시를 전송합니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LikePostService
  participant PostLikeMilestoneReachedListener
  participant PostLikeMilestoneAchievementRecorder
  participant PostLikeMilestoneNotificationProcessor
  participant PostLikeMilestonePushListener
  LikePostService->>PostLikeMilestoneReachedListener: PostLikeMilestoneReachedEvent 발행
  PostLikeMilestoneReachedListener->>PostLikeMilestoneAchievementRecorder: 마일스톤 달성 기록 저장
  PostLikeMilestoneAchievementRecorder->>PostLikeMilestoneNotificationProcessor: 신규 기록 처리
  PostLikeMilestoneNotificationProcessor->>PostLikeMilestonePushListener: 커밋 후 PostLikeMilestonePushEvent 발행
  PostLikeMilestonePushListener->>PostLikeMilestonePushListener: 수신자 조회 및 푸시 전송
Loading

Suggested labels: D-0

Suggested reviewers: glucosei

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 좋아요 취소 후 동일 마일스톤 알림이 재발송되는 문제를 해결하는 핵심 변경을 명확하게 설명합니다.
Linked Issues check ✅ Passed [#1439] 영구 마일스톤 이력과 유니크 제약으로 좋아요 중복 알림을 방지하고 관련 알림 정책을 재구성했습니다.
Out of Scope Changes check ✅ Passed 마이그레이션, 이력 관리, 알림 처리 분리는 모두 중복 알림 방지와 정책 재구성에 직접 관련됩니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/#1439-noti

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@KEEKE132 KEEKE132 changed the title Refactor/#1439 noti refactor: 좋아요 알림 재발송 문제 해결 Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

Test Results Summary

181 files  181 suites   18s ⏱️
619 tests 619 ✅ 0 💤 0 ❌
639 runs  639 ✅ 0 💤 0 ❌

Results for commit a4c18a7.

♻️ This comment has been updated with latest results.

@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: 5

🧹 Nitpick comments (2)
app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessor.java (1)

67-92: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

선택: 메시지 생성 로직을 분리하면 가독성이 좋아집니다.

process는 검증, 메시지 조립, 영속화, 이벤트 발행을 모두 수행합니다. 메시지 조립을 작은 private 메서드나 별도 값 객체로 분리하면 흐름이 명확해집니다. 문구 변경 시 수정 지점도 한 곳으로 줄어듭니다.

현재 동작에는 문제가 없습니다. 후속 작업으로 검토해 주세요.

🤖 Prompt for 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.

In
`@app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessor.java`
around lines 67 - 92, Update the process flow in
PostLikeMilestoneNotificationProcessor by extracting the serviceTitle,
serviceBody, and pushTitle construction into a focused private helper or value
object, then reuse its results for persistence and event publication. Keep the
existing Korean messages and notification behavior unchanged while making
process primarily coordinate validation, persistence, and event publishing.
app-main/src/main/resources/db/migration/V20260801133019__CreatePostLikeMilestoneAchievementTable.sql (1)

27-84: 🚀 Performance & Scalability | 🔵 Trivial

운영 조언: 대량 백필의 실행 시간과 락 영향을 점검해 주세요.

INSERT ... SELECTtb_like_post 전체를 스캔합니다. 좋아요 데이터가 많으면 마이그레이션 시간이 길어지고 FK 대상 테이블에 잠금이 발생합니다. 배포 전에 운영 데이터 규모로 실행 시간을 측정해 주세요. 필요하면 백필을 별도 배치로 분리하고 마이그레이션은 DDL만 수행하는 방식을 검토해 주세요.

참고로 WITH RECURSIVE thousand_milestones는 MySQL 기본 cte_max_recursion_depth(1000)에 묶입니다. 좋아요 수가 1,000,000을 넘는 게시글이 생기면 재귀가 중단되고 마이그레이션이 실패합니다. 현재 데이터에서는 문제가 없어도 제한을 인지해 주세요.

🤖 Prompt for 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.

In
`@app-main/src/main/resources/db/migration/V20260801133019__CreatePostLikeMilestoneAchievementTable.sql`
around lines 27 - 84, The migration performs an unbounded full-table backfill
and its thousand_milestones CTE can exceed MySQL’s default recursion depth.
Measure this INSERT backfill against production-sized data and, if runtime or
locking is unacceptable, move it to a separate batch job while keeping the
migration DDL-only; also ensure thousand_milestones handles post like counts
above the cte_max_recursion_depth limit without migration failure.
🤖 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
`@app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementReader.java`:
- Around line 18-22: Update findById in PostLikeMilestoneAchievementReader to
replace IllegalStateException with the project’s BaseException and
notification-domain XxxErrorCode implementing BaseResponseCode. Add or reuse an
error-code entry for the missing milestone history and throw it with
achievementId, matching existing exception and ErrorCode naming conventions.

In
`@app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementRecorder.java`:
- Around line 25-32: Update PostLikeMilestoneAchievementRecorder.record to catch
post or liker lookup failures from PostReader.findById and
UserReader.findUserById, and create a suppressed achievement via
PostLikeMilestoneAchievement.suppress with the unavailable-target outcome
instead of propagating the exception. Preserve the existing savePendingIfAbsent
flow when both entities are found, and return the resulting achievement ID
consistently.

In
`@app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementWriter.java`:
- Around line 24-37: Update savePendingIfAbsent to absorb the unique-constraint
DataIntegrityViolationException raised by concurrent saveAndFlush calls,
returning Optional.empty() when another request has already recorded the same
post and milestone. Ensure the exception is handled at an appropriate separate
transaction boundary, accounting for the existing Propagation.REQUIRES_NEW
behavior so the caller’s transaction is not marked rollback-only.

In
`@app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessorTest.java`:
- Around line 147-232: PostLikeMilestoneNotificationProcessorTest에 누락된
TARGET_UNAVAILABLE 경계 테스트를 추가하세요. liker가 null인 이력은 TARGET_UNAVAILABLE로 억제되고
notificationWriter, notificationSettingReader, blockReader, eventPublisher와
상호작용하지 않는지 검증하며, 기존
givenInactiveWriter_whenProcess_thenSuppressAsTargetUnavailable를 isInactive()와
isDropped() 조건을 모두 검증하도록 파라미터화하세요.

In
`@app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestoneReachedListenerTest.java`:
- Around line 46-55: Update
givenConsumedAchievement_whenHandle_thenSkipNotificationProcessing to verify
that notificationProcessor has no interactions at all, replacing the
argument-specific never().process("achievementId") check with Mockito
verifyNoInteractions and adding the required static import.

---

Nitpick comments:
In
`@app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessor.java`:
- Around line 67-92: Update the process flow in
PostLikeMilestoneNotificationProcessor by extracting the serviceTitle,
serviceBody, and pushTitle construction into a focused private helper or value
object, then reuse its results for persistence and event publication. Keep the
existing Korean messages and notification behavior unchanged while making
process primarily coordinate validation, persistence, and event publishing.

In
`@app-main/src/main/resources/db/migration/V20260801133019__CreatePostLikeMilestoneAchievementTable.sql`:
- Around line 27-84: The migration performs an unbounded full-table backfill and
its thousand_milestones CTE can exceed MySQL’s default recursion depth. Measure
this INSERT backfill against production-sized data and, if runtime or locking is
unacceptable, move it to a separate batch job while keeping the migration
DDL-only; also ensure thousand_milestones handles post like counts above the
cte_max_recursion_depth limit without migration failure.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 724ab3f7-838d-4136-9970-f161df4f5adb

📥 Commits

Reviewing files that changed from the base of the PR and between c20cd1e and 1a70f07.

📒 Files selected for processing (27)
  • app-main/src/main/java/net/causw/app/main/domain/community/post/service/LikePostService.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/entity/PostLikeMilestoneAchievement.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/enums/PostLikeMilestoneAchievementStatus.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/enums/PostLikeMilestoneSuppressionReason.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/event/PostLikeMilestonePushEvent.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/event/PostLikeMilestoneReachedEvent.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/event/PostLikedEvent.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/repository/PostLikeMilestoneAchievementRepository.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementReader.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementRecorder.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementWriter.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessor.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/listener/LikePostNotificationListener.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestonePushListener.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestoneReachedListener.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/policy/LikePostNotificationPolicy.java
  • app-main/src/main/resources/db/migration/V20260801133019__CreatePostLikeMilestoneAchievementTable.sql
  • app-main/src/test/java/net/causw/app/main/SchemaValidationTest.java
  • app-main/src/test/java/net/causw/app/main/domain/community/post/service/LikePostServiceTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/entity/PostLikeMilestoneAchievementTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementRecorderTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementWriterTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessorTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/LikePostNotificationListenerTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestonePushListenerTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestoneReachedListenerTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/policy/LikePostNotificationPolicyTest.java
💤 Files with no reviewable changes (3)
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/event/PostLikedEvent.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/listener/LikePostNotificationListener.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/LikePostNotificationListenerTest.java

@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: 1

🤖 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
`@app-main/src/main/resources/db/migration/V20260801170000__BaselineEarlyPostLikeMilestones.sql`:
- Around line 21-39: Update the early_milestones CTE and baseline INSERT to
cover every fixed milestone defined by LikePostNotificationPolicy, not only 1–4,
and add each 1,000-unit milestone less than or equal to
post_like_counts.like_count. Reuse the policy’s milestone definitions, preserve
the existing BASELINED records and filtering by current like count, and ensure
each applicable milestone is inserted once per post.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b85f0d82-767e-4c22-9978-c9eb182a5d27

📥 Commits

Reviewing files that changed from the base of the PR and between 1a70f07 and a4c18a7.

📒 Files selected for processing (9)
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementReader.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/policy/LikePostNotificationPolicy.java
  • app-main/src/main/java/net/causw/app/main/shared/exception/errorcode/PostLikeMilestoneAchievementErrorCode.java
  • app-main/src/main/resources/db/migration/V20260801170000__BaselineEarlyPostLikeMilestones.sql
  • app-main/src/test/java/net/causw/app/main/domain/community/post/service/LikePostServiceTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementReaderTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessorTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestoneReachedListenerTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/policy/LikePostNotificationPolicyTest.java
🚧 Files skipped from review as they are similar to previous changes (5)
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/listener/PostLikeMilestoneReachedListenerTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/policy/LikePostNotificationPolicyTest.java
  • app-main/src/main/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneAchievementReader.java
  • app-main/src/test/java/net/causw/app/main/domain/community/post/service/LikePostServiceTest.java
  • app-main/src/test/java/net/causw/app/main/domain/notification/notification/service/implementation/PostLikeMilestoneNotificationProcessorTest.java

Comment on lines +21 to +39
early_milestones AS (
SELECT 1 AS milestone_count
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
)
SELECT
UUID(),
NOW(6),
NOW(6),
post_like_counts.post_id,
NULL,
early_milestones.milestone_count,
'BASELINED',
NULL,
NULL
FROM post_like_counts
INNER JOIN early_milestones
ON early_milestones.milestone_count <= post_like_counts.like_count;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

모든 기존 마일스톤을 기준선으로 기록해 주세요.

Line 21-26은 1~4만 BASELINED로 저장합니다. 따라서 이미 좋아요 5개, 10개, 50개 이상에 도달한 기존 게시글에는 해당 이력이 없습니다.

이 게시글이 좋아요 취소 후 기존 마일스톤에 다시 도달하면 새 이력이 생성됩니다. 이후 알림 처리도 다시 실행될 수 있습니다. 이는 중복 알림 방지 목표와 맞지 않습니다.

LikePostNotificationPolicy의 모든 고정 마일스톤과 현재 좋아요 수 이하의 1,000 단위 마일스톤을 기준선으로 삽입해 주세요.

수정 방향 예시
-early_milestones AS (
+policy_milestones AS (
     SELECT 1 AS milestone_count
     UNION ALL SELECT 2
     UNION ALL SELECT 3
     UNION ALL SELECT 4
+    UNION ALL SELECT 5
+    UNION ALL SELECT 10
+    UNION ALL SELECT 50
+    UNION ALL SELECT 100
+    UNION ALL SELECT 500
+    -- 현재 최대 좋아요 수 이하의 1,000 단위 마일스톤도 생성
 )
 ...
-INNER JOIN early_milestones
-    ON early_milestones.milestone_count <= post_like_counts.like_count;
+INNER JOIN policy_milestones
+    ON policy_milestones.milestone_count <= post_like_counts.like_count;
🤖 Prompt for 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.

In
`@app-main/src/main/resources/db/migration/V20260801170000__BaselineEarlyPostLikeMilestones.sql`
around lines 21 - 39, Update the early_milestones CTE and baseline INSERT to
cover every fixed milestone defined by LikePostNotificationPolicy, not only 1–4,
and add each 1,000-unit milestone less than or equal to
post_like_counts.like_count. Reuse the policy’s milestone definitions, preserve
the existing BASELINED records and filtering by current like count, and ensure
each applicable milestone is inserted once per post.

@glucosei glucosei left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, 수고하셨습니다!

@KEEKE132
KEEKE132 merged commit e861825 into dev Aug 6, 2026
10 checks passed
@KEEKE132
KEEKE132 deleted the refactor/#1439-noti branch August 6, 2026 12:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REFACTOR] 좋아요 중복 알림 방지

2 participants