Skip to content

Commit

Permalink
fix: 좌석 선 택 시 토큰 세션 아이디 기준으로 선점하도록
Browse files Browse the repository at this point in the history
  • Loading branch information
Hanna committed Jan 14, 2024
1 parent f1d23bc commit 59a928a
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 35 deletions.
2 changes: 1 addition & 1 deletion api/api-booking/http/booking.http
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,5 @@ GET http://localhost:8082/api/v1/bookings
Authorization: Bearer {{accessToken}}

### 내 예매 내역 상세 조회
GET http://localhost:8082/api/v1/bookings/1705163603493
GET http://localhost:8082/api/v1/bookings/{bookingId}
Authorization: Bearer {{accessToken}}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ public ResponseEntity<ApiResponse<BookingGetResponse>> getBooking(
@CurrentAccount Long memberId,
@PathVariable String id
) {
System.out.println("!!!!!!!!! memberId = " + memberId);
BookingGetResponse booking = bookingService.getBooking(id, memberId);
ApiResponse<BookingGetResponse> response = ApiResponse.ok(booking);
return ResponseEntity.ok().body(response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public class BookingService { //TODO: 테스트 코드 작성
public BookingCreateResponse createBooking(BookingCreateRequest request, Long memberId, String tokenSessionId) {
Member member = getMemberById(memberId);
EventTime time = getBookableTimeWithEvent(request.timeId());
List<EventSeat> seats = getBookableSeatsWithArea(request.timeId(), request.seatIds(), memberId);
List<EventSeat> seats = getBookableSeatsWithArea(request.timeId(), request.seatIds(), tokenSessionId);

ReceiptType receiptType = ReceiptType.fromDescription(request.receiptType());
validateDeliveryAddress(receiptType, request.deliveryAddress());
Expand Down Expand Up @@ -188,8 +188,8 @@ private EventTime getBookableTimeWithEvent(Long timeId) {
return time;
}

private List<EventSeat> getBookableSeatsWithArea(Long timeId, List<Long> seatIds, Long memberId) {
checkHeldSeats(seatIds, memberId);
private List<EventSeat> getBookableSeatsWithArea(Long timeId, List<Long> seatIds, String tokenSessionId) {
checkHeldSeats(seatIds, tokenSessionId);

List<EventSeat> seats = eventSeatRepository.findAllWithAreaByTimeIdAndSeatIds(timeId, seatIds);

Expand All @@ -204,10 +204,10 @@ private List<EventSeat> getBookableSeatsWithArea(Long timeId, List<Long> seatIds
return seats;
}

private void checkHeldSeats(List<Long> seatIds, Long memberId) {
private void checkHeldSeats(List<Long> seatIds, String sessionId) {
seatIds.forEach(seatId -> {
Long selectorId = seatLockManager.getSelectorId(seatId).orElse(null);
if (selectorId == null || !selectorId.equals(memberId)) {
String selectorId = seatLockManager.getSelectorId(seatId).orElse(null);
if (selectorId == null || !selectorId.equals(sessionId)) {
throw new BookingException(BookingErrorCode.UNBOOKABLE_SEAT_INCLUSION);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.pgms.apibooking.domain.seat.dto.request.SeatsGetRequest;
import com.pgms.apibooking.domain.seat.dto.response.AreaResponse;
import com.pgms.apibooking.domain.seat.service.SeatService;
import com.pgms.coredomain.response.ApiResponse;
import com.pgms.coresecurity.security.resolver.CurrentAccount;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand All @@ -38,15 +38,21 @@ public ResponseEntity<ApiResponse<List<AreaResponse>>> getSeats(@ModelAttribute

@Operation(summary = "좌석 선택")
@PostMapping("/{seatId}/select")
public ResponseEntity<Void> selectSeat(@PathVariable Long seatId, @CurrentAccount Long memberId) {
seatService.selectSeat(seatId, memberId);
public ResponseEntity<Void> selectSeat(
@PathVariable Long seatId,
@RequestAttribute("tokenSessionId") String tokenSessionId
) {
seatService.selectSeat(seatId, tokenSessionId);
return ResponseEntity.noContent().build();
}

@Operation(summary = "좌석 선택 해제")
@PostMapping("/{seatId}/deselect")
public ResponseEntity<Void> deselectSeat(@PathVariable Long seatId, @CurrentAccount Long memberId) {
seatService.deselectSeat(seatId, memberId);
public ResponseEntity<Void> deselectSeat(
@PathVariable Long seatId,
@RequestAttribute("tokenSessionId") String tokenSessionId
) {
seatService.deselectSeat(seatId, tokenSessionId);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@
public class SeatLockManager {

private final static String SEAT_LOCK_CACHE_KEY_PREFIX = "seatId:";
private final static String SEAT_LOCK_CACHE_VALUE_PREFIX = "memberId:";
private final static String SEAT_LOCK_CACHE_VALUE_PREFIX = "tokenSessionId:";

private final RedisOperator redisOperator;

public Optional<Long> getSelectorId(Long seatId) {
public Optional<String> getSelectorId(Long seatId) {
String key = generateSeatLockKey(seatId);
String value = redisOperator.get(key);
return Optional.ofNullable(value == null ? null : extractMemberId(value));
return Optional.ofNullable(value == null ? null : extractSessionId(value));
}

public void lockSeat(Long seatId, Long memberId, Integer expirationSeconds) {
public void lockSeat(Long seatId, String tokenSessionId, Integer expirationSeconds) {
String key = generateSeatLockKey(seatId);
String value = generateSeatLockValue(memberId);
String value = generateSeatLockValue(tokenSessionId);
redisOperator.setIfAbsent(key, value, expirationSeconds);
}

Expand All @@ -37,11 +37,11 @@ private String generateSeatLockKey(Long seatId) {
return SEAT_LOCK_CACHE_KEY_PREFIX + seatId;
}

private String generateSeatLockValue(Long memberId) {
return SEAT_LOCK_CACHE_VALUE_PREFIX + memberId;
private String generateSeatLockValue(String tokenSessionId) {
return SEAT_LOCK_CACHE_VALUE_PREFIX + tokenSessionId;
}

private Long extractMemberId(String value) {
return Long.parseLong(value.replace(SEAT_LOCK_CACHE_VALUE_PREFIX, ""));
private String extractSessionId(String value) {
return value.replace(SEAT_LOCK_CACHE_VALUE_PREFIX, "");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ public List<AreaResponse> getSeats(SeatsGetRequest request) {
.toList();
}

public void selectSeat(Long seatId, Long memberId) {
Long selectorId = seatLockManager.getSelectorId(seatId).orElse(null);
public void selectSeat(Long seatId, String tokenSessionId) {
String selectorId = seatLockManager.getSelectorId(seatId).orElse(null);

if (selectorId != null) {
if (selectorId.equals(memberId)) {
if (selectorId.equals(tokenSessionId)) {
return;
}
throw new BookingException(BookingErrorCode.SEAT_HELD_BY_ANOTHER_MEMBER);
Expand All @@ -52,18 +52,18 @@ public void selectSeat(Long seatId, Long memberId) {
}

seat.updateStatus(EventSeatStatus.HOLDING);
seatLockManager.lockSeat(seatId, memberId, SEAT_LOCK_CACHE_EXPIRE_SECONDS);
seatLockManager.lockSeat(seatId, tokenSessionId, SEAT_LOCK_CACHE_EXPIRE_SECONDS);
}

public void deselectSeat(Long seatId, Long memberId) {
Long selectorId = seatLockManager.getSelectorId(seatId).orElse(null);
public void deselectSeat(Long seatId, String tokenSessionId) {
String selectorId = seatLockManager.getSelectorId(seatId).orElse(null);

if (selectorId == null) {
updateSeatStatusToAvailable(seatId);
return;
}

if (!selectorId.equals(memberId)) {
if (!selectorId.equals(tokenSessionId)) {
throw new BookingException(BookingErrorCode.SEAT_HELD_BY_ANOTHER_MEMBER);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void setup() {
Optional.empty()
);

given(seatLockManager.getSelectorId(any(Long.class))).willReturn(Optional.of(member.getId()));
given(seatLockManager.getSelectorId(any(Long.class))).willReturn(Optional.of(SESSION_ID));
doNothing().when(bookingQueueManager).remove(any(Long.class), any(String.class));

// when
Expand Down Expand Up @@ -243,7 +243,7 @@ void setup() {
);

given(seatLockManager.getSelectorId(seat1.getId())).willReturn(Optional.empty());
given(seatLockManager.getSelectorId(seat2.getId())).willReturn(Optional.of(member.getId() + 1));
given(seatLockManager.getSelectorId(seat2.getId())).willReturn(Optional.of(SESSION_ID));

// when & then
assertThatThrownBy(() -> bookingService.createBooking(request, member.getId(), SESSION_ID))
Expand Down Expand Up @@ -295,7 +295,7 @@ void setup() {
Optional.empty()
);

given(seatLockManager.getSelectorId(seat.getId())).willReturn(Optional.of(member.getId()));
given(seatLockManager.getSelectorId(seat.getId())).willReturn(Optional.of(SESSION_ID));

// when & then
assertThatThrownBy(() -> bookingService.createBooking(request, member.getId(), SESSION_ID))
Expand Down Expand Up @@ -349,7 +349,7 @@ void setup() {
Optional.empty()
);

given(seatLockManager.getSelectorId(seat.getId())).willReturn(Optional.of(member.getId()));
given(seatLockManager.getSelectorId(seat.getId())).willReturn(Optional.of(SESSION_ID));

// when & then
assertThatThrownBy(() -> bookingService.createBooking(request, member.getId(), SESSION_ID))
Expand Down Expand Up @@ -401,7 +401,7 @@ void setup() {
Optional.empty()
);

given(seatLockManager.getSelectorId(seat.getId())).willReturn(Optional.of(member.getId()));
given(seatLockManager.getSelectorId(seat.getId())).willReturn(Optional.of(SESSION_ID));

// when & then
assertThatThrownBy(() -> bookingService.createBooking(request, member.getId(), SESSION_ID))
Expand Down Expand Up @@ -453,7 +453,7 @@ void setup() {
Optional.empty()
);

given(seatLockManager.getSelectorId(seat.getId())).willReturn(Optional.of(member.getId()));
given(seatLockManager.getSelectorId(seat.getId())).willReturn(Optional.of(SESSION_ID));

// when & then
assertThatThrownBy(() -> bookingService.createBooking(request, member.getId(), SESSION_ID))
Expand Down

0 comments on commit 59a928a

Please sign in to comment.