-
Notifications
You must be signed in to change notification settings - Fork 54
[#70] 배달 매칭 서비스 #69
base: rider_info_service
Are you sure you want to change the base?
[#70] 배달 매칭 서비스 #69
Changes from 9 commits
c359d94
5c6b1e8
f7fb9c1
44d1eb5
06a9543
c4d70b3
6de3866
6e5255d
ea62c9a
c0ee25a
82f0018
0fa1918
41da68f
6224def
c945f37
da0fdce
5d952ca
9b49198
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.delfood.dao.deliveery; | ||
|
||
import com.delfood.dto.OrderDTO.OrderStatus; | ||
import com.delfood.dto.address.Position; | ||
import com.delfood.dto.rider.DeliveryRiderDTO; | ||
import java.util.List; | ||
|
||
public interface DeliveryDao { | ||
|
||
void updateRiderInfo(DeliveryRiderDTO riderInfo); | ||
|
||
long deleteRiderInfo(String riderId); | ||
|
||
boolean hasRiderInfo(String riderId); | ||
|
||
void deleteNonUpdatedRiders(); | ||
|
||
DeliveryRiderDTO getRiderInfo(String riderId); | ||
|
||
List<DeliveryRiderDTO> toList(); | ||
|
||
long deleteAll(List<String> idList); | ||
|
||
OrderStatus getOrderStatus(Long orderId); | ||
|
||
void setOrderStatus(Long orderId, OrderStatus status); | ||
|
||
void deleteOrderStatus(Long orderId); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
package com.delfood.dao.deliveery; | ||
|
||
import com.delfood.dto.OrderDTO.OrderStatus; | ||
import com.delfood.dto.address.Position; | ||
import com.delfood.dto.rider.DeliveryRiderDTO; | ||
import com.delfood.service.OrderService; | ||
|
||
import java.time.LocalDateTime; | ||
import java.time.temporal.ChronoUnit; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.stream.Collectors; | ||
import javax.annotation.PostConstruct; | ||
import javax.annotation.concurrent.ThreadSafe; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository(value = "multiThreadDeliveryDao") | ||
yyy9942 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@ThreadSafe | ||
public class MultiThreadDeliveryDao implements DeliveryDao{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저장소가 로컬저장소이므로 |
||
private Map<String, DeliveryRiderDTO> riders; | ||
private Map<Long, OrderStatus> orders; | ||
|
||
@Value("rider.expire") | ||
private static Long expireTime; | ||
|
||
@Autowired | ||
private OrderService orderService; | ||
|
||
@PostConstruct | ||
public void init() { | ||
this.riders = new ConcurrentHashMap<String, DeliveryRiderDTO>(); | ||
this.orders = new ConcurrentHashMap<Long, OrderStatus>(); | ||
} | ||
|
||
/** | ||
* 내부 Map에 라이더 정보를 갱신한다. | ||
* 만약 Map 내부에 정보가 없다면 새롭게 정보를 추가한다. | ||
* 라이더 정보가 저장되면 라이더는 실시간으로 정보를 업데이트해야한다. | ||
* @param riderInfo 라이더 정보 | ||
*/ | ||
@Override | ||
public void updateRiderInfo(DeliveryRiderDTO riderInfo) { | ||
if (riders.containsKey(riderInfo.getId())) { | ||
riders.replace(riderInfo.getId(), riderInfo); | ||
yyy9942 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else { | ||
riders.put(riderInfo.getId(), riderInfo); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기 또한 두 단계가 atomic하지 않습니다
|
||
} | ||
} | ||
|
||
/** | ||
* 배달 대기를 제거한다. | ||
* @author jun | ||
* @param riderId 제거할 라이더의 아이디 | ||
*/ | ||
@Override | ||
public long deleteRiderInfo(String riderId) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 삭제성공여부를 리턴하는 것 같은데 boolean으로 리턴하는건 어떨까요? |
||
return riders.remove(riderId) == null ? 0 : 1; | ||
} | ||
|
||
/** | ||
* 해당 라이더가 저장소 내에 존재하는지 확인한다. | ||
* @author jun | ||
* @param riderId 라이더 아이디 | ||
* @return | ||
*/ | ||
@Override | ||
public boolean hasRiderInfo(String riderId) { | ||
return riders.containsKey(riderId); | ||
} | ||
|
||
/** | ||
* 리스트 형태로 라이더를 조회한다. | ||
* @author jun | ||
* @return | ||
*/ | ||
@Override | ||
public List<DeliveryRiderDTO> toList() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 메소드의 동작을 유추하기에는 getRiderList가 더 나을 것 같습니다 |
||
return riders.values().stream().collect(Collectors.toList()); | ||
} | ||
|
||
|
||
/** | ||
* 일정 시간동안 자신의 위치를 업데이트 하지 않는 라이더를 제거한다. | ||
* @author jun | ||
*/ | ||
@Override | ||
public void deleteNonUpdatedRiders() { | ||
riders.values().stream() | ||
.filter( | ||
e -> ChronoUnit.SECONDS.between(e.getUpdatedAt(), LocalDateTime.now()) > expireTime) | ||
.forEach(e -> riders.remove(e.getId())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이곳은 atomic하지 않지만, 특정 시점을 중심으로 데이터를 삭제해주는것이므로 문제가 없습니다. |
||
} | ||
|
||
/** | ||
* 라이더의 정보를 조회한다. | ||
* @author jun | ||
*/ | ||
@Override | ||
public DeliveryRiderDTO getRiderInfo(String riderId) { | ||
return riders.get(riderId); | ||
} | ||
|
||
/** | ||
* 리스트로 받은 아이디를 기반으로 라이더를 배달 매칭에서 제거한다. | ||
* @param idList 라이더의 아이디들 | ||
* @return 지워진 라이더 개수 | ||
*/ | ||
@Override | ||
public long deleteAll(List<String> idList) { | ||
long deleteCount = 0; | ||
for (String id : idList) { | ||
deleteCount += deleteRiderInfo(id); | ||
} | ||
return deleteCount; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여러 스레드가 접근하므로 유효한 삭제가 몇 개인지 세는것은 의미가 없을 것 같습니다. 삭제가 실패했더라도 처리해줄 수 있는게 없기 때문입니다 |
||
} | ||
|
||
/** | ||
* 주문의 상태를 조회한다. | ||
* 주문 정보가 내부 메모리에 없다면 DB에서 조회한 후 메모리에 저장한다. | ||
* @author jun | ||
* @param orderId 조회할 주문 아이디 | ||
*/ | ||
@Override | ||
public OrderStatus getOrderStatus(Long orderId) { | ||
OrderStatus status = orders.get(orderId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 때에는 order에 없지만 |
||
if (Objects.isNull(status)) { | ||
status = orderService.getOrderStatus(orderId); | ||
setOrderStatus(orderId, status); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 때는 order에 있으면 어떻게 될까요? 중복으로 put을 하게 되지 않을까요? |
||
return status; | ||
} | ||
|
||
return status; | ||
} | ||
|
||
/** | ||
* 주문 정보를 내부에 저장한다. | ||
* @author jun | ||
* @param orderId 저장할 주문 아이디 | ||
* @param status 주문의 상태 | ||
*/ | ||
@Override | ||
public void setOrderStatus(Long orderId, OrderStatus status) { | ||
if (orders.containsKey(orderId)) { | ||
orders.replace(orderId, status); | ||
} else { | ||
orders.put(orderId, status); | ||
} | ||
} | ||
|
||
/** | ||
* 주문 정보를 삭제한다. | ||
* @param orderId 삭제할 주문 정보 아이디 | ||
* @author jun | ||
*/ | ||
@Override | ||
public void deleteOrderStatus(Long orderId) { | ||
orders.remove(orderId); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.delfood.dto.rider; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NonNull; | ||
|
||
@Getter | ||
@Builder | ||
public class AcceptDeliveryRequestDTO { | ||
|
||
@NonNull | ||
private Long orderId; | ||
|
||
@NonNull | ||
private String riderId; | ||
|
||
@NonNull | ||
private RequestResult result; | ||
|
||
private LocalDateTime startedAt; | ||
|
||
|
||
@Builder | ||
public AcceptDeliveryRequestDTO(Long orderId, String riderId) { | ||
this.orderId = orderId; | ||
this.riderId = riderId; | ||
startedAt = LocalDateTime.now(); | ||
} | ||
|
||
public static enum RequestResult { | ||
SUCCESS, FAIL | ||
} | ||
} |
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.
모습을 보니 떠오른건데 type보다는 level이 어떨까요?
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.
level도 생각해보았는데 뭔가 접근의 계층이 있어야 할것같은 느낌이라서요. 제가 만든 로그인은 3가지의 전혀 다른 타입이라서 일단 타입으로 해두었습니다.