-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34 from softeerbootcamp4th/feature/33-feat-fcfs
[feat] 선착순 이벤트 잔여 구현방안: Redis SortedSet + synchronized, DB Entity 기반 (#33)
- Loading branch information
Showing
21 changed files
with
644 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
src/main/java/hyundai/softeer/orange/event/fcfs/dto/ResponseFcfsResultDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package hyundai.softeer.orange.event.fcfs.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@NoArgsConstructor | ||
@Builder | ||
@AllArgsConstructor | ||
@Getter | ||
public class ResponseFcfsResultDto { | ||
|
||
// 선착순 이벤트 정답 여부 | ||
private boolean answerResult; | ||
|
||
// 선착순 이벤트 당첨 여부, answerResult가 false라면 무조건 false를 반환 | ||
private boolean isWinner; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
src/main/java/hyundai/softeer/orange/event/fcfs/repository/FcfsEventRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,22 @@ | ||
package hyundai.softeer.orange.event.fcfs.repository; | ||
|
||
import hyundai.softeer.orange.event.fcfs.entity.FcfsEvent; | ||
import jakarta.persistence.LockModeType; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Lock; | ||
import org.springframework.data.jpa.repository.Query; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
@Repository | ||
public interface FcfsEventRepository extends JpaRepository<FcfsEvent, Long> { | ||
|
||
List<FcfsEvent> findByStartTimeBetween(LocalDateTime startTime, LocalDateTime endTime); | ||
|
||
@Lock(LockModeType.PESSIMISTIC_WRITE) | ||
@Query("select e from FcfsEvent e left join fetch e.infos where e.id = :id") | ||
Optional<FcfsEvent> findByIdWithLock(Long id); | ||
} |
55 changes: 55 additions & 0 deletions
55
src/main/java/hyundai/softeer/orange/event/fcfs/service/DbFcfsService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package hyundai.softeer.orange.event.fcfs.service; | ||
|
||
import hyundai.softeer.orange.common.ErrorCode; | ||
import hyundai.softeer.orange.event.fcfs.entity.FcfsEvent; | ||
import hyundai.softeer.orange.event.fcfs.entity.FcfsEventWinningInfo; | ||
import hyundai.softeer.orange.event.fcfs.exception.FcfsEventException; | ||
import hyundai.softeer.orange.event.fcfs.repository.FcfsEventRepository; | ||
import hyundai.softeer.orange.event.fcfs.repository.FcfsEventWinningInfoRepository; | ||
import hyundai.softeer.orange.eventuser.entity.EventUser; | ||
import hyundai.softeer.orange.eventuser.repository.EventUserRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Slf4j | ||
@RequiredArgsConstructor | ||
@Service | ||
public class DbFcfsService implements FcfsService{ | ||
|
||
private final FcfsEventRepository fcfsEventRepository; | ||
private final EventUserRepository eventUserRepository; | ||
private final FcfsEventWinningInfoRepository fcfsEventWinningInfoRepository; | ||
|
||
@Override | ||
@Transactional | ||
public boolean participate(Long eventSequence, String userId){ | ||
FcfsEvent fcfsEvent = fcfsEventRepository.findByIdWithLock(eventSequence) | ||
.orElseThrow(() -> new FcfsEventException(ErrorCode.EVENT_NOT_FOUND)); | ||
EventUser eventUser = eventUserRepository.findByUserId(userId) | ||
.orElseThrow(() -> new FcfsEventException(ErrorCode.EVENT_USER_NOT_FOUND)); | ||
// 이미 마감된 이벤트인지 확인 | ||
if(fcfsEvent.getInfos().size() >= fcfsEvent.getParticipantCount()){ | ||
return false; | ||
} | ||
validateParticipate(fcfsEvent, eventUser); | ||
|
||
fcfsEventWinningInfoRepository.save(FcfsEventWinningInfo.of(fcfsEvent, eventUser)); | ||
return true; | ||
} | ||
|
||
private void validateParticipate(FcfsEvent fcfsEvent, EventUser eventUser){ | ||
// 잘못된 이벤트 참여 시간인지 검증 | ||
if(LocalDateTime.now().isBefore(fcfsEvent.getStartTime()) || LocalDateTime.now().isAfter(fcfsEvent.getEndTime())){ | ||
throw new FcfsEventException(ErrorCode.INVALID_EVENT_TIME); | ||
} | ||
|
||
// 이미 당첨된 사용자인지 확인 | ||
if(fcfsEvent.getInfos().stream().anyMatch(info -> info.getEventUser().equals(eventUser))){ | ||
throw new FcfsEventException(ErrorCode.ALREADY_WINNER); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/hyundai/softeer/orange/event/fcfs/service/FcfsAnswerService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package hyundai.softeer.orange.event.fcfs.service; | ||
|
||
import hyundai.softeer.orange.common.ErrorCode; | ||
import hyundai.softeer.orange.event.fcfs.exception.FcfsEventException; | ||
import hyundai.softeer.orange.event.fcfs.util.FcfsUtil; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.data.redis.core.StringRedisTemplate; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Slf4j | ||
@RequiredArgsConstructor | ||
@Service | ||
public class FcfsAnswerService { | ||
|
||
private final StringRedisTemplate stringRedisTemplate; | ||
|
||
public boolean judgeAnswer(Long eventSequence, String answer) { | ||
String correctAnswer = stringRedisTemplate.opsForValue().get(FcfsUtil.answerFormatting(eventSequence.toString())); | ||
if (correctAnswer == null) { | ||
throw new FcfsEventException(ErrorCode.FCFS_EVENT_NOT_FOUND); | ||
} | ||
return correctAnswer.equals(answer); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.