12/8

졸용·2025년 12월 8일

TIL

목록 보기
130/144

🔹 배송 담당자 배정 기능 구현

비교적 간단한 roundRobin 방식으로 먼저 구현을 해보았다.

package chill_logistics.delivery_server.application;

import chill_logistics.delivery_server.application.dto.command.AssignedDeliveryPersonV1;
import chill_logistics.delivery_server.infrastructure.user.UserClient;
import chill_logistics.delivery_server.infrastructure.user.dto.UserForDeliveryResponseV1;
import chill_logistics.delivery_server.presentation.ErrorCode;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import lib.web.error.BusinessException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class DeliveryPersonAssignmentService {

    private static final String ROLE_HUB_DELIVERY_PERSON = "HUB_DELIVERY_PERSON";
    private static final String ROLE_FIRM_DELIVERY_PERSON = "FIRM_DELIVERY_PERSON";

    private final UserClient userClient;

    // 역할별 라운드 로빈 인덱스 저장 (멀티스레드 환경 대응)
    private final Map<String, AtomicLong> roundRobinIndex = new ConcurrentHashMap<>();

    // 허브 배송 담당자 배정
    public AssignedDeliveryPersonV1 assignHubDeliveryPerson() {
        return assignByRole(ROLE_HUB_DELIVERY_PERSON);
    }

    // 업체 배송 담당자 배정
    public AssignedDeliveryPersonV1 assignFirmDeliveryPerson() {
        return assignByRole(ROLE_FIRM_DELIVERY_PERSON);
    }

    private AssignedDeliveryPersonV1 assignByRole(String role) {

        // user-server에서 role 별 유저 목록 조회
        List<UserForDeliveryResponseV1> deliveryCandidates = userClient.getUsersByRole(role);

        if (deliveryCandidates == null || deliveryCandidates.isEmpty()) {
            throw new BusinessException(ErrorCode.DELIVERT_PERSON_NOT_FOUND);
        }

        // 해당 role에 대한 라운드 로빈 인덱스 가져오고, 없으면 생성
        AtomicLong counter = roundRobinIndex.computeIfAbsent(role, key -> new AtomicLong(0L));

        // 현재 인덱스를 가져오고 증가시키는 연산
        long index = counter.incrementAndGet();

        // 후보자 수로 나머지 연산하려 실제 선택 위치 계산
        int selectedIndex = (int) (index % deliveryCandidates.size());

        // 최종 선택된 담당자
        UserForDeliveryResponseV1 chosen = deliveryCandidates.get(selectedIndex);

        return new AssignedDeliveryPersonV1(
            chosen.userId(),
            chosen.userName()
        );
    }
}
profile
꾸준한 공부만이 답이다

0개의 댓글