-
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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,39 +3,32 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.dto.AmateurShowResponseDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.dto.AmateurUpdateRequestDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.entity.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.entity.enums.ApprovalStatus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.repository.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.converter.AmateurConverter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.dto.AmateurEnrollRequestDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.dto.AmateurEnrollResponseDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.amateurShow.repository.specification.AmateurShowSpecification; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.apiPayLoad.code.status.ErrorStatus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.apiPayLoad.exception.GeneralException; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.board.entity.enums.BoardType; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.event.entity.NewShowEvent; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.image.DTO.ImageRequestDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.image.DTO.ImageResponseDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.image.FilePath; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.image.entity.Image; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.image.repository.ImageRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.image.service.ImageService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.member.entity.Member; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.member.enumerate.Role; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.member.repository.MemberRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.memberLike.entity.MemberLike; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.memberLike.repository.MemberLikeRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.ticket.dto.response.ReserveListResponseDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.notice.event.entity.NewShowEvent; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.notice.kafka.NewShowEvent.MemberRecommendationProducer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cc.backend.notice.service.NoticeService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.domain.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.context.ApplicationEventPublisher; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.jpa.domain.Specification; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.transaction.annotation.Transactional; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.text.Collator; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.LocalDate; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.LocalDateTime; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.format.DateTimeFormatter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.stream.Collectors; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -54,7 +47,8 @@ public class AmateurServiceImpl implements AmateurService { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final MemberLikeRepository memberLikeRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final ImageService imageService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final ImageRepository imageRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final ApplicationEventPublisher eventPublisher; //이벤트 생성 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final NoticeService noticeService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final MemberRecommendationProducer memberRecommendationProducer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 소극장 공연 등록 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Transactional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -93,16 +87,22 @@ public AmateurEnrollResponseDTO.AmateurEnrollResult enrollShow(Long memberId, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageService.saveImageWithImageUrl(memberId, fullImageRequestDTO, Optional.ofNullable(dto.getImageUrl())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 좋아요한 멤버리스트 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<MemberLike> memberLikers = memberLikeRepository.findByPerformerId(memberId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 좋아요한 멤버가 한 명 이상일 때만 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(!memberLikers.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<Member> likers = memberLikers.stream() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(MemberLike::getLiker) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .collect(Collectors.toList()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //좋아요한 멤버 추출 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<Long> likerIds = memberLikeRepository.findByPerformerId(memberId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .stream() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(l -> l.getLiker().getId()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .toList(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eventPublisher.publishEvent(new NewShowEvent(newAmateurShow.getId(), memberId, likers)); //공연등록 이벤트 생성 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 좋아요 알림: 좋아요한 멤버들만 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!likerIds.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| noticeService.notifyNewShow( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new NewShowEvent(newAmateurShow.getId(), memberId, likerIds) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 추천: 해시태그 기반 추천 → 모든 회원 대상 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| memberRecommendationProducer.recommendByHashtag( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new NewShowEvent(newAmateurShow.getId(), memberId, null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //좋아요한 멤버 추출 | |
| List<Long> likerIds = memberLikeRepository.findByPerformerId(memberId) | |
| .stream() | |
| .map(l -> l.getLiker().getId()) | |
| .toList(); | |
| eventPublisher.publishEvent(new NewShowEvent(newAmateurShow.getId(), memberId, likers)); //공연등록 이벤트 생성 | |
| // 좋아요 알림: 좋아요한 멤버들만 | |
| if (!likerIds.isEmpty()) { | |
| noticeService.notifyNewShow( | |
| new NewShowEvent(newAmateurShow.getId(), memberId, likerIds) | |
| ); | |
| } | |
| // 추천: 해시태그 기반 추천 → 모든 회원 대상 | |
| memberRecommendationProducer.recommendByHashtag( | |
| new NewShowEvent(newAmateurShow.getId(), memberId, null) | |
| ); | |
| //좋아요한 멤버 추출 | |
| List<Long> likerIds = memberLikeRepository.findByPerformerId(memberId) | |
| .stream() | |
| .map(l -> l.getLiker().getId()) | |
| .toList(); | |
| TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { | |
| `@Override` | |
| public void afterCommit() { | |
| if (!likerIds.isEmpty()) { | |
| noticeService.notifyNewShow( | |
| new NewShowEvent(newAmateurShow.getId(), memberId, likerIds) | |
| ); | |
| } | |
| memberRecommendationProducer.recommendByHashtag( | |
| new NewShowEvent(newAmateurShow.getId(), memberId, null) | |
| ); | |
| } | |
| }); |
🤖 Prompt for AI Agents
In
`@src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurServiceImpl.java`
around lines 90 - 105, enrollShow is transactional so calling
memberRecommendationProducer.recommendByHashtag(...) emits Kafka events before
the DB commit; move that publish to an after‑commit hook to avoid orphaned
events. Replace the direct call to
memberRecommendationProducer.recommendByHashtag(new NewShowEvent(...)) inside
enrollShow with either (a) publish the NewShowEvent via a Spring application
event and handle it in a method annotated with `@TransactionalEventListener`(phase
= AFTER_COMMIT), or (b) register a TransactionSynchronization.afterCommit that
invokes memberRecommendationProducer.recommendByHashtag(...) with the same
NewShowEvent; keep notifyNewShow(...) as-is or also call it after-commit if you
prefer both side effects to run only after commit.
| 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: 188
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 123
🏁 Script executed:
Repository: SeeATheater/CC_Backend
Length of output: 5816
Add readiness gating for Kafka and define Kafka healthcheck.
depends_ononly enforces start order, not readiness. Without a Kafka healthcheck, the suggestedcondition: service_healthycannot work. The Kafka service (lines 55–83) lacks a healthcheck entirely, and app-blue/app-green (lines 29–32, 50–52) depend on Kafka without gating on readiness. This risks startup failures if the app attempts connections before Kafka is ready.Define a Kafka healthcheck first, then gate the app services on it:
✅ Suggested adjustment
Add to Kafka service:
kafka: image: confluentinc/cp-kafka:latest container_name: kafka ports: - "9092:9092" - "29092:29092" environment: ... + healthcheck: + test: ["CMD-SHELL", "kafka-broker-api-versions.sh --bootstrap-server=localhost:9092 || exit 1"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s volumes: - kafka_data:/var/lib/kafka/data restart: unless-stoppedThen update app services:
Apply to both app-blue and app-green.
📝 Committable suggestion
🤖 Prompt for AI Agents