-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] #143 kafka 도입 비동기 이벤트 기반 추천알림 로직 개발 #144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 1 commit
08c8253
ef4f42a
928bb00
edc783b
3a8a73f
10a813f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -167,4 +167,5 @@ public void reject(String rejectReason){ | |
| this.rejectReason = rejectReason; | ||
|
|
||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -85,6 +85,7 @@ public enum ErrorStatus implements BaseErrorCode { | |
| AMATEUR_TICKET_NOT_FOUND(HttpStatus.NOT_FOUND, "AMATEURTICKET4000", "존재하지 않는 소극장 공연 티켓입니다."), | ||
| AMATEUR_TICKET_STOCK(HttpStatus.BAD_REQUEST, "AMATEURTICKET4001", "주문 수량은 최소 1개 이상이어야 합니다."), | ||
| AMATEUR_SHOW_MISMATCH(HttpStatus.NOT_FOUND, "AMATEURTICKET4002", "회차와 티켓에 해당하는 공연이 일치하지 않습니다."), | ||
|
|
||
| // PHOTOALBUM ERROR | ||
| PHOTOALBUM_NOT_FOUND(HttpStatus.NOT_FOUND, "PHOTOALBUM4000", "존재하지 않는 사진첩입니다."), | ||
|
|
||
|
|
@@ -108,6 +109,7 @@ public enum ErrorStatus implements BaseErrorCode { | |
|
|
||
| //NOTICE ERROR | ||
| MEMBERNOTICE_NOT_FOUND(HttpStatus.NOT_FOUND, "MEMBERNOTICE4001", "존재하지 않는 알림입니다."), | ||
| NOTICE_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTICE4001", "존재하지 않는 알림입니다."), | ||
|
Comment on lines
110
to
+112
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n src/main/java/cc/backend/apiPayLoad/code/status/ErrorStatus.java | sed -n '100,120p'Repository: SeeATheater/CC_Backend Length of output: 1396 🏁 Script executed: # Search for usages of these constants
rg "MEMBERNOTICE_NOT_FOUND|NOTICE_NOT_FOUND" -B 2 -A 2Repository: SeeATheater/CC_Backend Length of output: 1303 🏁 Script executed: # Check for any comments or documentation about notice vs membernotice
rg -i "notice" src/main/java/cc/backend/apiPayLoad/code/status/ErrorStatus.java -B 1 -A 1 | head -50Repository: SeeATheater/CC_Backend Length of output: 270 🏁 Script executed: # Search for all usages of NOTICE_NOT_FOUND more broadly
rg "NOTICE_NOT_FOUND" -r "Found in: $FILE"Repository: SeeATheater/CC_Backend Length of output: 498 🏁 Script executed: # Check for Notice service/repository files
fd -t f "Notice" src/main/java --type fRepository: SeeATheater/CC_Backend Length of output: 953 🏁 Script executed: # Look at the structure to find notice-related classes
fd -t d "notice" src/main/javaRepository: SeeATheater/CC_Backend Length of output: 98 🏁 Script executed: # Check NoticeService for how it handles not found cases
cat -n src/main/java/cc/backend/notice/service/NoticeService.javaRepository: SeeATheater/CC_Backend Length of output: 933 🏁 Script executed: # Check NoticeServiceImpl for how it handles not found cases
cat -n src/main/java/cc/backend/notice/service/NoticeServiceImpl.javaRepository: SeeATheater/CC_Backend Length of output: 12662 🏁 Script executed: # Check if there's a controller that might retrieve Notice directly
rg "noticeRepository\.findById|getNotice|Notice.*not.*found" -i -A 2 -B 2Repository: SeeATheater/CC_Backend Length of output: 10769 🏁 Script executed: # Check MemberNoticeController to understand the API patterns
head -100 src/main/java/cc/backend/notice/controller/MemberNoticeController.javaRepository: SeeATheater/CC_Backend Length of output: 2516 Remove unused
🤖 Prompt for AI Agents |
||
| // INQUIRY ERROR | ||
| INQUIRY_NOT_FOUND(HttpStatus.NOT_FOUND, "INQUIRY4000", "존재하지 않는 문의글입니다."), | ||
| FORBIDDEN_INQUIRY_ACCESS(HttpStatus.NOT_FOUND, "INQUIRY4001", "로그인한 멤버가 작성하지 않는 문의글입니다."), | ||
|
|
||
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,25 +18,29 @@ public class MemberNotice extends BaseEntity { | |
| @Column(nullable = false, columnDefinition = "bigint") | ||
| private Long id; | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) | ||
| @JoinColumn(name = "notice_id") | ||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "notice_id", nullable = false) | ||
| private Notice notice; | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) | ||
| @JoinColumn(name = "member_id") | ||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "member_id", nullable = false) | ||
| private Member member; | ||
|
Comment on lines
+21
to
27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Find migrations touching member_notice schema
fd -t f \( -e sql -e yml -e yaml \) | xargs rg -l "member_notice|notice_id|member_id" 2>/dev/null | head -20Repository: SeeATheater/CC_Backend Length of output: 775 🏁 Script executed: #!/bin/bash
# Find migration files and schema management
echo "=== Searching for SQL migration files ==="
find . -type f \( -name "*.sql" -o -name "V*.sql" -o -name "U*.sql" \) 2>/dev/null | head -20
echo "=== Checking for Flyway/Liquibase directories ==="
find . -type d \( -name "db" -o -name "migration" -o -name "migrations" -o -name "liquibase" -o -name "flyway" \) 2>/dev/null
echo "=== Searching for application configuration files ==="
find . -type f \( -name "application*.yml" -o -name "application*.yaml" -o -name "application*.properties" \) 2>/dev/null | head -10Repository: SeeATheater/CC_Backend Length of output: 331 🏁 Script executed: #!/bin/bash
# Check application configuration for DDL auto settings
echo "=== application.yml ==="
cat ./src/main/resources/application.yml
echo -e "\n=== application-dev.yml ==="
cat ./src/main/resources/application-dev.yml
echo -e "\n=== application-prod.yml ==="
cat ./src/main/resources/application-prod.ymlRepository: SeeATheater/CC_Backend Length of output: 2606 🏁 Script executed: #!/bin/bash
# Read the full MemberNotice.java entity
echo "=== MemberNotice.java entity ==="
cat -n ./src/main/java/cc/backend/notice/entity/MemberNotice.java
# Check if there are other entities with similar join columns to compare patterns
echo -e "\n=== Check similar entities for patterns ==="
rg -A 5 "@JoinColumn.*nullable" ./src/main/java/cc/backend --type java | head -40Repository: SeeATheater/CC_Backend Length of output: 4699 🏁 Script executed: #!/bin/bash
# Check for data cleanup or migration utilities
echo "=== Searching for data migration/cleanup utilities ==="
find ./src -type f -name "*Migration*" -o -name "*Cleanup*" -o -name "*Backfill*" 2>/dev/null
echo -e "\n=== Searching for `@Sql` or schema initialization scripts ==="
rg -l "schema|INSERT|UPDATE.*member_notice|UPDATE.*notice_id" ./src --type java -i | head -10
echo -e "\n=== Checking MemberNotice repository/service for data handling ==="
find ./src -path "*notice*" -name "*Repository.java" -o -path "*notice*" -name "*Service.java" 2>/dev/null | head -10Repository: SeeATheater/CC_Backend Length of output: 1243 🏁 Script executed: #!/bin/bash
# Check MemberNoticeService for data handling
echo "=== MemberNoticeService.java ==="
wc -l ./src/main/java/cc/backend/notice/service/MemberNoticeService.java
cat ./src/main/java/cc/backend/notice/service/MemberNoticeService.java
echo -e "\n=== MemberNoticeRepository.java ==="
cat ./src/main/java/cc/backend/notice/repository/MemberNoticeRepository.javaRepository: SeeATheater/CC_Backend Length of output: 5433 Verify database has no NULL rows in notice_id or member_id columns before deploying. With 🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Notice와 연결 안된 MemberNotice row는 존재하지 않으므로 문제 없음 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| private Boolean isRead = false; | ||
| private String personalMsg; | ||
|
|
||
| private boolean isRead = false; | ||
|
|
||
| @Builder | ||
| public MemberNotice( Notice notice, Member member) { | ||
| this.isRead = false ; | ||
| public MemberNotice(Notice notice, Member member, String personalMsg, boolean isRead) { | ||
| this.notice = notice; | ||
| this.member = member; | ||
| this.personalMsg = personalMsg; | ||
| this.isRead = isRead; | ||
| } | ||
|
|
||
| public MemberNotice updateIsRead(){ | ||
| public void updateIsRead(){ | ||
| this.isRead = true ; | ||
| return this; | ||
| } | ||
|
|
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| package cc.backend.notice.entity.enums; | ||
|
|
||
| public enum NoticeType { | ||
| AMATEURSHOW, HOT, COMMENT, REPLY, TICKET, REMIND, AD | ||
| AMATEURSHOW, HOT, COMMENT, REPLY, TICKET, REMIND, RECOMMEND | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle backward compatibility for renamed enum value. Renaming 🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AD 쓰는 코드 없어서 backward compatibility 안챙겨도됨 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: Length of output: 33
✏️ Learnings added
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| package cc.backend.event.entity; | ||
| package cc.backend.notice.event.entity; | ||
|
|
||
| import lombok.Getter; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package cc.backend.notice.event.entity; | ||
|
|
||
| import lombok.AllArgsConstructor; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| import java.io.Serializable; | ||
| import java.util.List; | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| public class NewShowEvent { | ||
| private Long amateurShowId; // 공연 ID | ||
| private Long performerId; // 공연 등록자 ID | ||
| private List<Long> likerIds; // 좋아요한 유저 ID 리스트 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| package cc.backend.event.entity; | ||
| package cc.backend.notice.event.entity; | ||
|
|
||
| import lombok.Getter; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 159
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 7794
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 48
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 506
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 4923
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 6786
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 587
🏁 Script executed:
rg -l "notifyNewShow" src/main/java/Repository: SeeATheater/CC_Backend
Length of output: 275
🏁 Script executed:
rg -B5 -A15 "void notifyNewShow|notifyNewShow\(" src/main/java/cc/backend/notice/Repository: SeeATheater/CC_Backend
Length of output: 3433
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 9890
Move Kafka publish to after-commit to prevent orphaned events.
enrollShowis transactional. CallingmemberRecommendationProducer.recommendByHashtag()inside it emits Kafka events before the DB commit (viakafkaTemplate.send()at line 115). If the transaction rolls back, consumers see events referencing non‑existent records. Move this side effect to an after‑commit hook (e.g.,@TransactionalEventListener(AFTER_COMMIT)orTransactionSynchronization) so Kafka stays consistent with the DB.Note:
notifyNewShow()performs only database operations (Notice/MemberNotice inserts), so it has no direct Kafka issue, but can remain in the same after-commit block if needed.✅ Example after-commit hook using TransactionSynchronization
📝 Committable suggestion
🤖 Prompt for AI Agents