Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.nowait.applicationuser.security.exception.ResourceNotFoundException;
import com.nowait.applicationuser.security.exception.UnauthorizedException;
import com.nowait.applicationuser.waiting.exception.WorkInProgressException;
import com.nowait.common.exception.ErrorMessage;
import com.nowait.common.exception.ErrorResponse;
import com.nowait.discord.service.DiscordAlarmService;
Expand Down Expand Up @@ -292,6 +293,15 @@ public ErrorResponse handleReservationAddUnauthorizedException(
return new ErrorResponse(e.getMessage(), RESERVATION_ADD_UNAUTHORIZED.getCode());
}

@ResponseStatus(CONFLICT)
@ExceptionHandler(WorkInProgressException.class)
public ErrorResponse handleWorkInProgressException(
WorkInProgressException e, WebRequest request) {
alarm(e, request);
log.error("handleWorkInProgressException", e);
return new ErrorResponse(e.getMessage(), WORK_IN_PROGRESS.getCode());
}

// 공통 에러 Map 생성
private static Map<String, String> getErrors(MethodArgumentNotValidException e) {
return e.getBindingResult()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.nowait.applicationuser.waiting.controller;

import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
Expand All @@ -12,6 +14,7 @@

import com.nowait.applicationuser.waiting.dto.CancelWaitingRequest;
import com.nowait.applicationuser.waiting.dto.CancelWaitingResponse;
import com.nowait.applicationuser.waiting.dto.GetMyWaitingInfoResponse;
import com.nowait.applicationuser.waiting.dto.GetWaitingSizeResponse;
import com.nowait.applicationuser.waiting.dto.RegisterWaitingRequest;
import com.nowait.applicationuser.waiting.dto.RegisterWaitingResponse;
Expand All @@ -34,6 +37,24 @@ public class WaitingController {
/**
* 대기열 리팩토링용 API
*/
@GetMapping()
@Operation(summary = "대기열 리팩토링용 API", description = "전체 대기 목록 조회")
public ResponseEntity<?> getMyWaitingInfo(
@AuthenticationPrincipal CustomOAuth2User customOAuth2User
) {
List<GetMyWaitingInfoResponse> response = waitingService.getMyWaitingInfo(
customOAuth2User
);

return ResponseEntity
.ok()
.body(
ApiUtils.success(
response
)
);
}

@PostMapping("/{publicCode}")
@Operation(summary = "대기열 리팩토링용 API", description = "대기열 리팩토링용 API")
public ResponseEntity<?> registerWaiting(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.nowait.applicationuser.waiting.dto;

import java.time.LocalDateTime;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class GetMyWaitingInfoResponse {
private String reservationId;
private Long storeId;
private String storeName;
private String departmentName;
private Integer rank;
private Integer teamsAhead;
private Integer partySize;
private String status;
private LocalDateTime registeredAt;
private String location;
private String profileImageUrl;
private String bannerImageUrl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.nowait.applicationuser.waiting.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class IdempotencyResponse {
private String state;
private Object response;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.nowait.applicationuser.waiting.exception;

import com.nowait.common.exception.ErrorMessage;

public class WorkInProgressException extends RuntimeException {
public WorkInProgressException() { super(ErrorMessage.WORK_IN_PROGRESS.getMessage()); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
import org.springframework.stereotype.Repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nowait.applicationuser.waiting.dto.CancelWaitingResponse;
import com.nowait.applicationuser.waiting.dto.RegisterWaitingResponse;
import com.nowait.applicationuser.waiting.dto.IdempotencyResponse;
import com.nowait.applicationuser.waiting.dto.WaitingCancelIdempotencyValue;
import com.nowait.applicationuser.waiting.dto.WaitingIdempotencyValue;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Repository
@RequiredArgsConstructor
@Slf4j
public class WaitingIdempotencyRepository {

private final RedisTemplate<String, String> redisTemplate;
Expand All @@ -24,64 +25,61 @@ public class WaitingIdempotencyRepository {
private static final Duration TTL = Duration.ofMinutes(10);

// 멱등키 조회 메서드
public Optional<WaitingIdempotencyValue> findByKey(String key) {
public Optional<WaitingIdempotencyValue> findByRegisterKey(String key) {
String idempotencyValue = redisTemplate.opsForValue().get(key);

if (idempotencyValue == null) {
return Optional.empty();
}

try {
return Optional.of(
objectMapper.readValue(idempotencyValue, WaitingIdempotencyValue.class)
);
log.info("Idempotency value found in Redis for key {}: {}", key, idempotencyValue);
return Optional.of(objectMapper.readValue(idempotencyValue, WaitingIdempotencyValue.class));
} catch (Exception e) {
throw new IllegalArgumentException("Failed to deserialize value from Redis", e);
}
}

// 멱등키 조회 메서드
public Optional<WaitingCancelIdempotencyValue> findByCancelKey(String key) {
public WaitingCancelIdempotencyValue findByCancelKey(String key) {
String idempotencyValue = redisTemplate.opsForValue().get(key);

if (idempotencyValue == null) {
return Optional.empty();
return null;
}

try {
return Optional.of(
objectMapper.readValue(idempotencyValue, WaitingCancelIdempotencyValue.class)
);
log.info("Idempotency value found in Redis for key {}: {}", key, idempotencyValue);
return objectMapper.readValue(idempotencyValue, WaitingCancelIdempotencyValue.class);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to deserialize value from Redis", e);
}
}


// 멱등키 저장 메서드 - 대기 등록
public void saveIdempotencyValue(String key, RegisterWaitingResponse response) {
WaitingIdempotencyValue waitingIdempotencyValue = new WaitingIdempotencyValue(
// 멱등키 저장 메서드
public void saveIdempotencyResponse(String key, Object response) {
IdempotencyResponse idempotencyResponse = new IdempotencyResponse(
"COMPLETED",
response
);

try {
String jsonValue = objectMapper.writeValueAsString(waitingIdempotencyValue);
String jsonValue = objectMapper.writeValueAsString(idempotencyResponse);
redisTemplate.opsForValue().set(key, jsonValue, TTL);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to serialize value for Redis", e);
}
}

// 멱등키 저장 메서드 - 대기 취소
public void saveCancelIdempotencyValue(String key, CancelWaitingResponse response) {
WaitingCancelIdempotencyValue waitingIdempotencyValue = new WaitingCancelIdempotencyValue(
"COMPLETED",
response
public void saveIdempotencyInProgress(String key) {
IdempotencyResponse idempotencyResponse = new IdempotencyResponse(
"IN-PROGRESS",
null
);

try {
String jsonValue = objectMapper.writeValueAsString(waitingIdempotencyValue);
String jsonValue = objectMapper.writeValueAsString(idempotencyResponse);
redisTemplate.opsForValue().set(key, jsonValue, TTL);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to serialize value for Redis", e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.nowait.applicationuser.waiting.service;

import java.util.Optional;

import org.springframework.stereotype.Service;

import com.nowait.applicationuser.waiting.dto.WaitingCancelIdempotencyValue;
import com.nowait.applicationuser.waiting.dto.WaitingIdempotencyValue;
import com.nowait.applicationuser.waiting.redis.WaitingIdempotencyRepository;

import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@RequiredArgsConstructor
@Slf4j
public class IdempotencyService {

private final WaitingIdempotencyRepository waitingIdempotencyRepository;

// 멱등키 검증 메서드
// TODO : 공통 멱등키 검증 메서드로 리팩토링 필요!!!!!!!!!
public Optional<WaitingIdempotencyValue> validateIdempotency(HttpServletRequest httpServletRequest) {
String idempotentKey = httpServletRequest.getHeader("Idempotency-Key");

return waitingIdempotencyRepository.findByRegisterKey(idempotentKey);
}

public WaitingCancelIdempotencyValue validateIdempotencyCancel(HttpServletRequest httpServletRequest) {
String idempotentKey = httpServletRequest.getHeader("Idempotency-Key");

return waitingIdempotencyRepository.findByCancelKey(idempotentKey);
}

// 멱등키 응답 저장 메서드
public void saveIdempotencyResponse(String idempotentKey, Object response) {
if (idempotentKey != null && !idempotentKey.isBlank()) {
waitingIdempotencyRepository.saveIdempotencyResponse(idempotentKey, response);
}
}

// 멱등키 PROCESSING 상태로 최초 저장
public void saveIdempotencyKeyInProgress(String idempotentKey) {
if (idempotentKey != null && !idempotentKey.isBlank()) {
log.info("Saving idempotency key in progress: {}", idempotentKey);
waitingIdempotencyRepository.saveIdempotencyInProgress(idempotentKey);
}
}

}
Loading