Skip to content

Commit 4f470be

Browse files
committed
refactor: sliding window counter service 리팩토링
1 parent ba74e80 commit 4f470be

File tree

1 file changed

+38
-42
lines changed

1 file changed

+38
-42
lines changed

src/main/java/com/systemdesign/slidingwindowcounter/service/SlidingWindowCounterService.java

+38-42
Original file line numberDiff line numberDiff line change
@@ -33,54 +33,51 @@ public Mono<SlidingWindowCounterProfileResponse> createSlidingWindowCounter() {
3333
// 현재 윈도우의 시작 시간 계산
3434
double startTimeCurrentWindow = calculateTimeRange(currentTimestamp);
3535

36-
// 이전 윈도우의 시작 시간 계산
37-
double startTimePreviousWindow = calculateTimeRange(currentTimestamp - SLIDING_WINDOW_COUNTER_DURATION * 1000);
38-
3936
//식별자 - 현재의 타임 스탬프와 UUID 조합
4037
String uniqueRequestIdentifier = String.valueOf(currentTimestamp) + ":" + UUID.randomUUID().toString();
4138

4239
return reactiveRedisTemplate.opsForZSet()
43-
.add(redisKey, uniqueRequestIdentifier, currentTimestamp)
44-
.flatMap(success -> {
45-
if (!success) {
46-
return Mono.empty();
47-
}
48-
49-
// 이전 윈도우의 요청 수를 가져옴
50-
Mono<Long> currentCountValue = reactiveRedisTemplate.opsForZSet()
51-
.count(redisKey, Range.closed(startTimeCurrentWindow, (double) currentTimestamp))
52-
.defaultIfEmpty(0L);
53-
54-
return currentCountValue.flatMap(previousCount -> {
55-
double overlapRate = calculateOverlapRate(currentTimestamp);
56-
57-
// 현재 요청을 포함한 최종 요청 수 계산
58-
long totalCount = Math.round(1 + (previousCount * overlapRate));
59-
log.info("Adjusted Sliding Window Counter count: {}", totalCount);
60-
61-
log.info("Sliding Window Counter count: {}", totalCount);
62-
log.debug("previousCountValue Sliding Window Counter count: {}", currentCountValue);
63-
log.debug("overlapRate Window Counter count: {}", overlapRate);
64-
if (totalCount >= SLIDING_WINDOW_COUNTER_MAX_REQUEST) {
65-
log.error("Rate limit exceeded. key: {}", redisKey);
66-
return Mono.<SlidingWindowCounterProfileResponse>error(
67-
new RateLimitExceededException(RateExceptionCode.COMMON_TOO_MANY_REQUESTS, totalCount)
68-
);
69-
} else {
70-
return Mono.just(
71-
SlidingWindowCounterProfileResponse.from(
72-
List.of(SlidingWindowCounterResponse.from(redisKey, totalCount))
73-
)
74-
);
75-
}
76-
});
77-
})
40+
.count(redisKey, Range.closed(startTimeCurrentWindow, (double) currentTimestamp))
41+
.defaultIfEmpty(0L)
42+
.flatMap(previousCount -> reactiveRedisTemplate.opsForZSet()
43+
.add(redisKey, uniqueRequestIdentifier, currentTimestamp)
44+
.flatMap(success -> {
45+
if (!success) {
46+
return Mono.empty();
47+
}
48+
49+
double overlapRate = calculateOverlapRate(currentTimestamp);
50+
51+
// 현재 요청을 포함한 최종 요청 수 계산
52+
long totalCount;
53+
if (previousCount == 0) {
54+
totalCount = 1;
55+
log.info("Init Sliding Window Counter count: {}", totalCount);
56+
} else {
57+
totalCount = Math.round(1 + (previousCount * overlapRate));
58+
log.info("Adjusted Sliding Window Counter count: {}", totalCount);
59+
}
60+
61+
log.info("Sliding Window Counter count: {}", totalCount);
62+
if (totalCount >= SLIDING_WINDOW_COUNTER_MAX_REQUEST) {
63+
log.error("Rate limit exceeded. key: {}", redisKey);
64+
return Mono.error(
65+
new RateLimitExceededException(RateExceptionCode.COMMON_TOO_MANY_REQUESTS, totalCount)
66+
);
67+
} else {
68+
return Mono.just(
69+
SlidingWindowCounterProfileResponse.from(
70+
List.of(SlidingWindowCounterResponse.from(redisKey, totalCount))
71+
)
72+
);
73+
}
74+
}))
7875
// 에러 로깅
7976
.doOnError(error -> {
8077
log.error("An error occurred: {}", error.getMessage());
8178
})
8279
.onErrorResume(error -> {
83-
// 에러가 발생했을 때 에러 처리
80+
// 에러가 발생하면 RateLimitExceededException을 반환
8481
return Mono.error(new RateLimitExceededException(RateExceptionCode.COMMON_TOO_MANY_REQUESTS, 0L));
8582
});
8683
}
@@ -91,8 +88,7 @@ public Flux<SlidingWindowCounterResponse> findAllSlidingWindowCounter() {
9188
log.info("Sliding Window Counter find all. key: {}", redisKey);
9289

9390
return reactiveRedisTemplate.opsForZSet().rangeByScore(redisKey,
94-
Range.closed(Double.MIN_VALUE, (double) currentTimestamp))
95-
//Range.closed(calculateTimeRange(currentTimestamp), (double) currentTimestamp))
91+
Range.closed(calculateTimeRange(currentTimestamp), (double) currentTimestamp))
9692
.map(value -> {
9793
String[] parts = value.toString().split(":");
9894
long timestamp = Long.parseLong(parts[0]);
@@ -112,7 +108,7 @@ private double calculateOverlapRate(long currentTimestamp) {
112108
// 겹치는 시간의 길이를 계산
113109
double overlapDuration = (startTimeCurrentWindow - startTimePreviousWindow) / 1000.0;
114110

115-
// 겹치는 시간 비율을 계산 (윈도우 지속 시간으로 나눔)
111+
// 겹치는 시간 비율을 계산
116112
double overlapRate = overlapDuration / SLIDING_WINDOW_COUNTER_DURATION;
117113

118114
return overlapRate;

0 commit comments

Comments
 (0)