Skip to content

Commit ed75132

Browse files
sojunsikTheGreatKangokjunghyeonSalinatedCoffee
committed
develop -> main ( 강의, 수강신청 ) (#180)
* [fix] 대기열 인원 수 확인 로직 변경 테스트 반영 (#179) * feat: Redis 기반 동시성 제어 및 큐 기반 수강신청·취소 비동기 처리 구현 (#176) * test: 현재 동시성 문제가 발생하는지 확인하기 위한 테스트 추가 - 동시에 100명이 신청했을 경우 최대 수강 인원이 30명인 강좌에 몇명이 등록되는지 확인 - 수강신청 내역이 30개가 아닌 100개가 생성되고있음 - 강의 정보에 현재 수강인원이 제대로 갱신되고 있지 않음 - 30명이 채워져야하지만 11, 12명 등 이상한 값으로 채워지고 있음 # Conflicts: # backend/src/main/java/com/WEB4_5_GPT_BE/unihub/domain/enrollment/repository/EnrollmentRepository.java * feat: 수강신청 로그를 추가하여 수강인원이 제대로 증가하지 않는 문제점 파악 - 동시에 수강신청을 보내고 인원을 변경하기 때문에 해당 강좌의 현재수강신청 인원 수가 제대로 증가하지 않고 오히려 적게 나타나는 문제였음 ``` 수강 신청이 완료되었습니다. 학생: 25020004, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020010, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020002, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020005, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020006, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020003, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020001, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020009, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020008, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020007, 강좌: 0 현재 수강인원 변경이 완료되었습니다. 학생: 25020001, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020006, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020004, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020005, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020002, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020007, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020010, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020003, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020008, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020009, 강좌: 1 ``` * refactor : 변경된 회원 도메인에 맞게 테스트 코드 수정 * feat: Redisson을 통한 수강신청 동시성 제어 구현 - 코드별 주석으로 상세 설명 * feat: 동시성 테스트는 프로젝트 테스트에서 진행하지 않도록 @Profile("!test") 수정 - 현재 동시성 로직은 별도의 트랜잭션을 생성하기 때문에 test 코드 상에 transational 을 붙여줄 수 없음 - test 코드에서 @transational 을 붙이지 않으면 테스트 과정에서 수정된 데이터가 롤백되지 못해 다른 테스트에 영향을 줄 수 있음 - 또한 동시성 관련 테스트는 생성해야 하는 회원 데이터 등이 많아 테스트에 부하가 많이 걸림 - 프로젝트 테스트에서 동시성을 검증하지 않고 별도의 툴 (jmeter) 을 통해 외부에서 테스트 할 예정 * feat: 동시성 테스트용 데이터 (4학년 학생 100명 및 신청용 강좌) 생성 # Conflicts: # backend/src/main/java/com/WEB4_5_GPT_BE/unihub/global/init/InitDevData.java * feat: 동시성 문제 해결을 위해 redis의 원자성이 보장되는 AtomicLong 적용 및 Queue를 통한 수강신청 비동기 처리 구현 - Redis RAtomicLong 을 이용해 capacity 및 enrolled 카운터를 원자적으로 관리하고, 수강신청 시 increment하여 동시성 보장 - 수강신청 요청 시 DB 트랜잭션 대신에 Redis 카운터만 업데이트하여 빠른 응답을 제공 - EnrollmentCommand DTO 를 통해 수강신청 정보를 큐(RBlockingQueue<EnrollmentCommand>)에 저장 - EnrollmentCommandConsumer 가 큐에서 명령을 순차적으로 꺼내 EnrollmentCommandHandler 에게 위임 * feat: Redisson을 활용하여 강의 생성 시 강의 수강 인원 및 수용 인원 정보를 Redis에 저장하는 기능 추가 * docs: k6를 활용한 수강신청 동시성 테스트 (100명 동시 신청 시 30명 정상 등록 완료) 파일 추가 - local 테스트 * test: 변경된 로직에 맞게 테스트 코드 수정 * refactor: 잘못 적용되어있는 ConcurrencyGuard 제거 * feat: EnrollmentDuplicateChecker를 구현하여 중복 queue 삽입 (동일 학생이 연속으로 신청하는 경우 (따닥)) 방지 - k6 테스트 스크립트 추가 (한 학생이 동일강좌에 5번 동시에 신청) * docs : 주석 추가 * refactor: EnrollmentAlreadyQueuedException 예외처리를 공용으로 사용할 수 있도록 수정 * feat: 강의 취소의 경우에도 순차적으로 queue를 통해 처리될 수 있도록 수강 신청 로직과 동일하게 구현 * docs: 30명 동시 수강신청 및 동시 수강 취소 k6 테스트 스크립트 추가 * refactor : 수강신청 api 주석 수정 및 수강신청 queue 처리 후 flag를 제거하도록 추가 * refactor : 테스트용 대기열 설정 제거 * test : 테스트 코드 수정 * refactor: 패키지 이동 * feat: 강의 등록, 수정 시 redis에 저장된 Enrolled와 Capacity를 업데이트하도록 추가 * feat: 강의 삭제 시 redis에 저장된 Enrolled와 Capacity를 삭제하도록 구현 * feat: redis counter 관련 로직을 별도의 service로 분리 * feat: 프로젝트 재부팅 시 redis에 저장된 counter 값을 현재 강의 정보와 동기화 하도록 구현 * test: 변경된 로직에 맞게 테스트 코드 수정 * feat: initData 과정에서 강의 생성 시 counter를 redis에 저장하도록 추가 * refactor: 필요없는 주석 제거 * merge: [BUGFIX] 강의 생성시 대학 정보 획득 방식 변경 (#178) * fix: 강의 생성 및 수정 시 인증된 유저 정보도 가져오도록 변경 * fix: 강의 생성 및 수정 시 요청 본문 대신 인증된 유저 정보로부터 대학 정보를 가져오도록 변경 * test: 변경 사항을 테스트에 반영 * fix: 강의 요청 DTO에서 대학 이름을 필수에서 선택으로 변경 * [fix] 대기열 인원 수 확인 로직 변경 테스트 반영 (#179) * feat: Redis 기반 동시성 제어 및 큐 기반 수강신청·취소 비동기 처리 구현 (#176) * test: 현재 동시성 문제가 발생하는지 확인하기 위한 테스트 추가 - 동시에 100명이 신청했을 경우 최대 수강 인원이 30명인 강좌에 몇명이 등록되는지 확인 - 수강신청 내역이 30개가 아닌 100개가 생성되고있음 - 강의 정보에 현재 수강인원이 제대로 갱신되고 있지 않음 - 30명이 채워져야하지만 11, 12명 등 이상한 값으로 채워지고 있음 # Conflicts: # backend/src/main/java/com/WEB4_5_GPT_BE/unihub/domain/enrollment/repository/EnrollmentRepository.java * feat: 수강신청 로그를 추가하여 수강인원이 제대로 증가하지 않는 문제점 파악 - 동시에 수강신청을 보내고 인원을 변경하기 때문에 해당 강좌의 현재수강신청 인원 수가 제대로 증가하지 않고 오히려 적게 나타나는 문제였음 ``` 수강 신청이 완료되었습니다. 학생: 25020004, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020010, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020002, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020005, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020006, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020003, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020001, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020009, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020008, 강좌: 0 수강 신청이 완료되었습니다. 학생: 25020007, 강좌: 0 현재 수강인원 변경이 완료되었습니다. 학생: 25020001, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020006, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020004, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020005, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020002, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020007, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020010, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020003, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020008, 강좌: 1 현재 수강인원 변경이 완료되었습니다. 학생: 25020009, 강좌: 1 ``` * refactor : 변경된 회원 도메인에 맞게 테스트 코드 수정 * feat: Redisson을 통한 수강신청 동시성 제어 구현 - 코드별 주석으로 상세 설명 * feat: 동시성 테스트는 프로젝트 테스트에서 진행하지 않도록 @Profile("!test") 수정 - 현재 동시성 로직은 별도의 트랜잭션을 생성하기 때문에 test 코드 상에 transational 을 붙여줄 수 없음 - test 코드에서 @transational 을 붙이지 않으면 테스트 과정에서 수정된 데이터가 롤백되지 못해 다른 테스트에 영향을 줄 수 있음 - 또한 동시성 관련 테스트는 생성해야 하는 회원 데이터 등이 많아 테스트에 부하가 많이 걸림 - 프로젝트 테스트에서 동시성을 검증하지 않고 별도의 툴 (jmeter) 을 통해 외부에서 테스트 할 예정 * feat: 동시성 테스트용 데이터 (4학년 학생 100명 및 신청용 강좌) 생성 # Conflicts: # backend/src/main/java/com/WEB4_5_GPT_BE/unihub/global/init/InitDevData.java * feat: 동시성 문제 해결을 위해 redis의 원자성이 보장되는 AtomicLong 적용 및 Queue를 통한 수강신청 비동기 처리 구현 - Redis RAtomicLong 을 이용해 capacity 및 enrolled 카운터를 원자적으로 관리하고, 수강신청 시 increment하여 동시성 보장 - 수강신청 요청 시 DB 트랜잭션 대신에 Redis 카운터만 업데이트하여 빠른 응답을 제공 - EnrollmentCommand DTO 를 통해 수강신청 정보를 큐(RBlockingQueue<EnrollmentCommand>)에 저장 - EnrollmentCommandConsumer 가 큐에서 명령을 순차적으로 꺼내 EnrollmentCommandHandler 에게 위임 * feat: Redisson을 활용하여 강의 생성 시 강의 수강 인원 및 수용 인원 정보를 Redis에 저장하는 기능 추가 * docs: k6를 활용한 수강신청 동시성 테스트 (100명 동시 신청 시 30명 정상 등록 완료) 파일 추가 - local 테스트 * test: 변경된 로직에 맞게 테스트 코드 수정 * refactor: 잘못 적용되어있는 ConcurrencyGuard 제거 * feat: EnrollmentDuplicateChecker를 구현하여 중복 queue 삽입 (동일 학생이 연속으로 신청하는 경우 (따닥)) 방지 - k6 테스트 스크립트 추가 (한 학생이 동일강좌에 5번 동시에 신청) * docs : 주석 추가 * refactor: EnrollmentAlreadyQueuedException 예외처리를 공용으로 사용할 수 있도록 수정 * feat: 강의 취소의 경우에도 순차적으로 queue를 통해 처리될 수 있도록 수강 신청 로직과 동일하게 구현 * docs: 30명 동시 수강신청 및 동시 수강 취소 k6 테스트 스크립트 추가 * refactor : 수강신청 api 주석 수정 및 수강신청 queue 처리 후 flag를 제거하도록 추가 * refactor : 테스트용 대기열 설정 제거 * test : 테스트 코드 수정 * refactor: 패키지 이동 * feat: 강의 등록, 수정 시 redis에 저장된 Enrolled와 Capacity를 업데이트하도록 추가 * feat: 강의 삭제 시 redis에 저장된 Enrolled와 Capacity를 삭제하도록 구현 * feat: redis counter 관련 로직을 별도의 service로 분리 * feat: 프로젝트 재부팅 시 redis에 저장된 counter 값을 현재 강의 정보와 동기화 하도록 구현 * test: 변경된 로직에 맞게 테스트 코드 수정 * feat: initData 과정에서 강의 생성 시 counter를 redis에 저장하도록 추가 * refactor: 필요없는 주석 제거 * fix: 강의 생성 및 수정 시 인증된 유저 정보도 가져오도록 변경 * fix: 강의 생성 및 수정 시 요청 본문 대신 인증된 유저 정보로부터 대학 정보를 가져오도록 변경 * merge: Rebase 박주원/fix-177 onto develop * fix: 강의 요청 DTO에서 대학 이름을 필수에서 선택으로 변경 * test: 변경 사항을 테스트에 반영 --------- Co-authored-by: TheGreatKang <77500386+TheGreatKang@users.noreply.github.com> Co-authored-by: OJH <ok6737@naver.com> --------- Co-authored-by: TheGreatKang <77500386+TheGreatKang@users.noreply.github.com> Co-authored-by: OJH <ok6737@naver.com> Co-authored-by: SalinatedCoffee <74612242+SalinatedCoffee@users.noreply.github.com>
1 parent 8c3eab1 commit ed75132

1 file changed

Lines changed: 6 additions & 6 deletions

File tree

backend/src/main/java/com/WEB4_5_GPT_BE/unihub/domain/enrollment/service/EnrollmentQueueService.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package com.WEB4_5_GPT_BE.unihub.domain.enrollment.service;
22

3-
import com.WEB4_5_GPT_BE.unihub.domain.enrollment.dto.QueueStatusDto;
4-
import lombok.RequiredArgsConstructor;
5-
import lombok.extern.slf4j.Slf4j;
3+
import java.time.Duration;
4+
import java.util.List;
5+
66
import org.springframework.data.redis.core.Cursor;
77
import org.springframework.data.redis.core.ScanOptions;
88
import org.springframework.data.redis.core.StringRedisTemplate;
99
import org.springframework.stereotype.Service;
10-
11-
import java.time.Duration;
12-
import java.util.List;
10+
import com.WEB4_5_GPT_BE.unihub.domain.enrollment.dto.QueueStatusDto;
11+
import lombok.RequiredArgsConstructor;
12+
import lombok.extern.slf4j.Slf4j;
1313

1414
@Slf4j
1515
@Service

0 commit comments

Comments
 (0)