-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* fix: 회원가입 및 비밀번호 조회시에 로그인 필요 없도록 인증코드도 추가 * feat: 주차장 batch로 insert 구현 * feat: 주차장 데이터 비동기로 읽어오도록 변경 * feat: 커낵션 타임 아웃, 리드 타임 아웃 및 실패시 재시도 로직 추가 * feat: 헬스 체크 추가 * feat: 서킷 브레이커 패턴 구현 * feat: 헬스 체크 구현 및 api 패키지로 이동 * feat: 서킷 브레이커 어노테이션 적용 * refactor: 테스트용 log 삭제 * test: thread sleep 대신 future get 사용 * fix: 테스트시 flyway 안돌도록 수정 * refactor: ExecutorService Bean으로 사용하도록 변경 * refactor: synchronized 키워드 대신 AtomicInteger 사용하도록 변경 - close 대신 open 이라는 네이밍으로 변경 * refactor: HealthCheckResponse 패키지 이동 * refactor: HealthCheckResponse 패키지 이동 * fix: 좌표계 지정 * refactor: 생성, 수정일 직접 넣도록 수정 * refactor: 운영 시간 표현 방식 변경
- Loading branch information
Showing
55 changed files
with
1,157 additions
and
263 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
76 changes: 76 additions & 0 deletions
76
app-scheduler/src/main/java/com/parkingcomestrue/external/api/ApiCounter.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,76 @@ | ||
package com.parkingcomestrue.external.api; | ||
|
||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
public class ApiCounter { | ||
|
||
private final int MIN_TOTAL_COUNT; | ||
|
||
private AtomicInteger totalCount; | ||
private AtomicInteger errorCount; | ||
private boolean isOpened; | ||
|
||
public ApiCounter() { | ||
this.MIN_TOTAL_COUNT = 10; | ||
this.totalCount = new AtomicInteger(0); | ||
this.errorCount = new AtomicInteger(0); | ||
this.isOpened = false; | ||
} | ||
|
||
public ApiCounter(int minTotalCount) { | ||
this.MIN_TOTAL_COUNT = minTotalCount; | ||
this.totalCount = new AtomicInteger(0); | ||
this.errorCount = new AtomicInteger(0); | ||
this.isOpened = false; | ||
} | ||
|
||
public void countUp() { | ||
while (true) { | ||
int expected = getTotalCount(); | ||
int newValue = expected + 1; | ||
if (totalCount.compareAndSet(expected, newValue)) { | ||
return; | ||
} | ||
} | ||
} | ||
|
||
public void errorCountUp() { | ||
countUp(); | ||
while (true) { | ||
int expected = getErrorCount(); | ||
int newValue = expected + 1; | ||
if (errorCount.compareAndSet(expected, newValue)) { | ||
return; | ||
} | ||
} | ||
} | ||
|
||
public void reset() { | ||
totalCount = new AtomicInteger(0); | ||
errorCount = new AtomicInteger(0); | ||
isOpened = false; | ||
} | ||
|
||
public boolean isOpened() { | ||
return isOpened; | ||
} | ||
|
||
public void open() { | ||
isOpened = true; | ||
} | ||
|
||
public boolean isErrorRateOverThan(double errorRate) { | ||
int currentTotalCount = getTotalCount(); | ||
int currentErrorCount = getErrorCount(); | ||
if (currentTotalCount < MIN_TOTAL_COUNT) { | ||
return false; | ||
} | ||
double currentErrorRate = (double) currentErrorCount / currentTotalCount; | ||
return currentErrorRate >= errorRate; | ||
} | ||
|
||
public int getTotalCount() { | ||
return totalCount.get(); | ||
} | ||
public int getErrorCount() { return errorCount.get(); } | ||
} |
19 changes: 19 additions & 0 deletions
19
app-scheduler/src/main/java/com/parkingcomestrue/external/api/AsyncApiExecutorConfig.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 com.parkingcomestrue.external.api; | ||
|
||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class AsyncApiExecutorConfig { | ||
|
||
@Bean | ||
public ExecutorService executorService() { | ||
return Executors.newFixedThreadPool(100, (Runnable r) -> { | ||
Thread thread = new Thread(r); | ||
thread.setDaemon(true); | ||
return thread; | ||
}); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
app-scheduler/src/main/java/com/parkingcomestrue/external/api/CircuitBreaker.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,17 @@ | ||
package com.parkingcomestrue.external.api; | ||
|
||
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; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.METHOD) | ||
public @interface CircuitBreaker { | ||
|
||
int minTotalCount() default 10; | ||
double errorRate() default 0.2; | ||
long resetTime() default 30; | ||
TimeUnit timeUnit() default TimeUnit.MINUTES; | ||
} |
53 changes: 53 additions & 0 deletions
53
app-scheduler/src/main/java/com/parkingcomestrue/external/api/CircuitBreakerAspect.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,53 @@ | ||
package com.parkingcomestrue.external.api; | ||
|
||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.aspectj.lang.ProceedingJoinPoint; | ||
import org.aspectj.lang.annotation.Around; | ||
import org.aspectj.lang.annotation.Aspect; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Slf4j | ||
@Aspect | ||
@Component | ||
public class CircuitBreakerAspect { | ||
|
||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10); | ||
private final Map<Object, ApiCounter> map = new ConcurrentHashMap<>(); | ||
|
||
@Around("@annotation(annotation)") | ||
public Object around(ProceedingJoinPoint proceedingJoinPoint, CircuitBreaker annotation) { | ||
ApiCounter apiCounter = getApiCounter(proceedingJoinPoint, annotation.minTotalCount()); | ||
if (apiCounter.isOpened()) { | ||
log.warn("현재 해당 {} API는 오류로 인해 중지되었습니다.", proceedingJoinPoint.getTarget()); | ||
return null; | ||
} | ||
try { | ||
Object result = proceedingJoinPoint.proceed(); | ||
apiCounter.countUp(); | ||
return result; | ||
} catch (Throwable e) { | ||
handleError(annotation, apiCounter); | ||
return null; | ||
} | ||
} | ||
|
||
private ApiCounter getApiCounter(ProceedingJoinPoint proceedingJoinPoint, int minTotalCount) { | ||
Object target = proceedingJoinPoint.getTarget(); | ||
if (!map.containsKey(target)) { | ||
map.put(target, new ApiCounter(minTotalCount)); | ||
} | ||
return map.get(target); | ||
} | ||
|
||
private void handleError(CircuitBreaker annotation, ApiCounter apiCounter) { | ||
apiCounter.errorCountUp(); | ||
if (apiCounter.isErrorRateOverThan(annotation.errorRate())) { | ||
apiCounter.open(); | ||
scheduler.schedule(apiCounter::reset, annotation.resetTime(), annotation.timeUnit()); | ||
} | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
app-scheduler/src/main/java/com/parkingcomestrue/external/api/HealthCheckResponse.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,15 @@ | ||
package com.parkingcomestrue.external.api; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class HealthCheckResponse { | ||
|
||
boolean isHealthy; | ||
int totalSize; | ||
|
||
public HealthCheckResponse(boolean isHealthy, int totalSize) { | ||
this.isHealthy = isHealthy; | ||
this.totalSize = totalSize; | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
app-scheduler/src/main/java/com/parkingcomestrue/external/api/HealthChecker.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,6 @@ | ||
package com.parkingcomestrue.external.api; | ||
|
||
public interface HealthChecker { | ||
|
||
HealthCheckResponse check(); | ||
} |
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
2 changes: 1 addition & 1 deletion
2
...al/coordinate/CoordinateErrorHandler.java → ...pi/coordinate/CoordinateErrorHandler.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
2 changes: 1 addition & 1 deletion
2
...al/coordinate/dto/CoordinateResponse.java → ...pi/coordinate/dto/CoordinateResponse.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
16 changes: 16 additions & 0 deletions
16
...heduler/src/main/java/com/parkingcomestrue/external/api/parkingapi/ParkingApiService.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,16 @@ | ||
package com.parkingcomestrue.external.api.parkingapi; | ||
|
||
import com.parkingcomestrue.common.domain.parking.Parking; | ||
import com.parkingcomestrue.external.api.HealthChecker; | ||
import java.util.List; | ||
|
||
public interface ParkingApiService extends HealthChecker { | ||
|
||
default boolean offerCurrentParking() { | ||
return false; | ||
} | ||
|
||
List<Parking> read(int pageNumber, int size); | ||
|
||
int getReadSize(); | ||
} |
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
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.