-
Notifications
You must be signed in to change notification settings - Fork 2
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
[#8] 주문 기능을 구현한다. #18
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
b802375
feat 주문하기
KATEKEITH 54a09dd
test 주문하기
KATEKEITH 4101580
fix redission lock을 spring AOP로 Custom Annotation 처리
KATEKEITH d7da9d5
fix 동시성 이슈를 처리
KATEKEITH c05f596
test 주문 생성 테스트 삭제
KATEKEITH 24cd812
fix LockModeType OPTIMISTIC으로 변경
KATEKEITH 5f05a3f
fix Stock domain object 제거로 인한StockRepository 삭제
KATEKEITH 4b869ff
Merge branch 'develop' into feature/8
KATEKEITH c62748a
fix application.yml 원복
KATEKEITH cdfb276
fix docker-compose.yml 삭제
KATEKEITH f598f64
Merge branch 'feature/8' of https://github.com/f-lab-edu/goodchoice i…
KATEKEITH File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
56 changes: 56 additions & 0 deletions
56
src/main/java/com/flab/goodchoice/global/config/RedisConfig.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,56 @@ | ||
package com.flab.goodchoice.global.config; | ||
|
||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.data.redis.cache.RedisCacheConfiguration; | ||
import org.springframework.data.redis.cache.RedisCacheManager; | ||
import org.springframework.data.redis.connection.RedisConnectionFactory; | ||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; | ||
import org.springframework.data.redis.core.RedisTemplate; | ||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; | ||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; | ||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; | ||
import org.springframework.data.redis.serializer.RedisSerializationContext; | ||
import org.springframework.data.redis.serializer.StringRedisSerializer; | ||
|
||
@Configuration | ||
@EnableRedisRepositories | ||
public class RedisConfig { | ||
|
||
@Value("${spring.redis.host}") | ||
private String host; | ||
|
||
@Value("${spring.redis.port}") | ||
private int port; | ||
|
||
@Bean | ||
public RedisConnectionFactory redisConnectionFactory() { | ||
return new LettuceConnectionFactory(host, port); | ||
} | ||
|
||
@Bean | ||
public RedisTemplate<String, String> redisTemplate() { | ||
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); | ||
redisTemplate.setConnectionFactory(redisConnectionFactory()); | ||
redisTemplate.setKeySerializer(new StringRedisSerializer()); | ||
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(String.class)); | ||
return redisTemplate; | ||
} | ||
|
||
@Bean | ||
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) { | ||
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() | ||
.serializeKeysWith(RedisSerializationContext | ||
.SerializationPair.fromSerializer(new StringRedisSerializer())) | ||
.serializeValuesWith(RedisSerializationContext | ||
.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); | ||
|
||
return RedisCacheManager | ||
.RedisCacheManagerBuilder | ||
.fromConnectionFactory(redisConnectionFactory) | ||
.cacheDefaults(redisCacheConfiguration) | ||
.build(); | ||
} | ||
|
||
} |
38 changes: 38 additions & 0 deletions
38
src/main/java/com/flab/goodchoice/global/config/aop/DistributedLock.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,38 @@ | ||
package com.flab.goodchoice.global.config.aop; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
/** | ||
* Redisson Distributed Lock annotation | ||
*/ | ||
@Target(ElementType.METHOD) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface DistributedLock { | ||
|
||
/** | ||
* 락의 이름 | ||
*/ | ||
String key(); | ||
|
||
/** | ||
* 락의 시간 단위 | ||
*/ | ||
TimeUnit timeUnit() default TimeUnit.SECONDS; | ||
|
||
/** | ||
* 락을 기다리는 시간 (default - 5s) | ||
* 락 획득을 위해 waitTime 만큼 대기한다 | ||
*/ | ||
long waitTime() default 5L; | ||
|
||
/** | ||
* 락 임대 시간 (default - 3s) | ||
* 락을 획득한 이후 leaseTime 이 지나면 락을 해제한다 | ||
*/ | ||
long leaseTime() default 3L; | ||
|
||
} |
22 changes: 22 additions & 0 deletions
22
src/main/java/com/flab/goodchoice/global/config/aop/RedissonCallTransaction.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,22 @@ | ||
package com.flab.goodchoice.global.config.aop; | ||
|
||
import org.aspectj.lang.ProceedingJoinPoint; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.transaction.annotation.Propagation; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Component | ||
public class RedissonCallTransaction { | ||
|
||
/** | ||
* 부모트랜잭션의 유무와 관계없이 동시성에 대한 처리는 별도의 트랜잭션으로 동작하기 위함 | ||
* @param joinPoint | ||
* @return | ||
* @throws Throwable | ||
*/ | ||
@Transactional(propagation = Propagation.REQUIRES_NEW) | ||
public Object proceed(final ProceedingJoinPoint joinPoint) throws Throwable { | ||
return joinPoint.proceed(); | ||
} | ||
|
||
} |
30 changes: 30 additions & 0 deletions
30
src/main/java/com/flab/goodchoice/global/config/aop/RedissonConfig.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,30 @@ | ||
package com.flab.goodchoice.global.config.aop; | ||
|
||
import org.redisson.Redisson; | ||
import org.redisson.api.RedissonClient; | ||
import org.redisson.config.Config; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class RedissonConfig { | ||
|
||
@Value("${spring.redis.host}") | ||
private String redisHost; | ||
|
||
@Value("${spring.redis.port}") | ||
private int redisPort; | ||
|
||
private static final String REDISSON_HOST_PREFIX = "redis://"; | ||
|
||
@Bean | ||
public RedissonClient redissonClient() { | ||
RedissonClient redisson = null; | ||
Config config = new Config(); | ||
config.useSingleServer().setAddress(REDISSON_HOST_PREFIX + redisHost + ":" + redisPort); | ||
redisson = Redisson.create(config); | ||
return redisson; | ||
} | ||
|
||
} |
71 changes: 71 additions & 0 deletions
71
src/main/java/com/flab/goodchoice/global/config/aop/RedissonLockAop.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,71 @@ | ||
package com.flab.goodchoice.global.config.aop; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.aspectj.lang.ProceedingJoinPoint; | ||
import org.aspectj.lang.annotation.Around; | ||
import org.aspectj.lang.annotation.Aspect; | ||
import org.aspectj.lang.reflect.MethodSignature; | ||
import org.redisson.api.RLock; | ||
import org.redisson.api.RedissonClient; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.lang.reflect.Method; | ||
|
||
@Slf4j | ||
@Aspect | ||
@Component | ||
@RequiredArgsConstructor | ||
public class RedissonLockAop { | ||
|
||
private final RedissonClient redissonClient; | ||
|
||
private final RedissonCallTransaction redissonCallTransaction; | ||
|
||
@Around("@annotation(com.flab.goodchoice.global.config.aop.DistributedLock)") | ||
public Object lock(final ProceedingJoinPoint joinPoint) throws Throwable { | ||
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | ||
Method method = signature.getMethod(); | ||
DistributedLock distributedLock = method.getAnnotation(DistributedLock.class); | ||
|
||
String key = this.createKey(signature.getParameterNames(), joinPoint.getArgs(), distributedLock.key()); | ||
RLock rLock = redissonClient.getLock(key); | ||
try { | ||
boolean isPossible = rLock.tryLock(distributedLock.waitTime(), distributedLock.leaseTime(), distributedLock.timeUnit()); | ||
if (!isPossible) { | ||
return false; | ||
} | ||
|
||
log.info("Redisson Lock Key : {}", key); | ||
return redissonCallTransaction.proceed(joinPoint); | ||
} catch (InterruptedException e) { | ||
throw new InterruptedException(); | ||
} finally { | ||
try { | ||
rLock.unlock(); // (4) | ||
} catch (IllegalMonitorStateException e) { | ||
log.info("Redisson Lock Already UnLock {} {}"); | ||
} | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Redisson Key Create | ||
* @param parameterNames | ||
* @param args | ||
* @param key | ||
* @return | ||
*/ | ||
private String createKey(String[] parameterNames, Object[] args, String key) { | ||
String resultKey = key; | ||
for (int i = 0; i < parameterNames.length; i++) { | ||
if (parameterNames[i].equals(key)) { | ||
resultKey += args[i]; | ||
break; | ||
} | ||
} | ||
return resultKey; | ||
} | ||
|
||
} |
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
3 changes: 3 additions & 0 deletions
3
src/main/java/com/flab/goodchoice/item/domain/ItemEntryService.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
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
55 changes: 55 additions & 0 deletions
55
src/main/java/com/flab/goodchoice/item/domain/StockHistory.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 com.flab.goodchoice.item.domain; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.RequiredArgsConstructor; | ||
import org.hibernate.annotations.CreationTimestamp; | ||
import org.hibernate.annotations.UpdateTimestamp; | ||
|
||
import javax.persistence.*; | ||
import java.time.ZonedDateTime; | ||
|
||
@Getter | ||
@Entity | ||
@NoArgsConstructor | ||
public class StockHistory { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.AUTO) | ||
@Column(name = "id", nullable = false) | ||
private Long id; | ||
|
||
private String itemToken; | ||
|
||
private Long userId; | ||
|
||
private String orderToken; | ||
|
||
private Long itemPrice; | ||
|
||
@Enumerated(EnumType.STRING) | ||
private Status status; | ||
|
||
@CreationTimestamp | ||
private ZonedDateTime createdAt; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public enum Status { | ||
PLUS("재고사용량 증가"), | ||
MINUS("재고사용량 감소"); | ||
|
||
private final String description; | ||
} | ||
|
||
@Builder | ||
public StockHistory(String itemToken, Long userId, String orderToken, Long itemPrice) { | ||
this.itemToken = itemToken; | ||
this.userId = userId; | ||
this.orderToken = orderToken; | ||
this.itemPrice = itemPrice; | ||
this.status = Status.PLUS; | ||
this.createdAt = ZonedDateTime.now(); | ||
} | ||
|
||
} |
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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
나중에 ExceptionHandler를 통해서 응답에 메세지도 신경써주시면 좋을 것 같아요
실제 API를 제공한다고 했을때 사용자 또는 클라(FE, iOS, AOS) 쪽에서 메세지에 대한 핸들링이 필요 할 수 있으니 깐요