Sobes.tech
Senior

/** * == ФТ == * Сервис обработки заказа получает заказ для обработки через Rest API. * Обработка в следующем: * - Проверить наличие товара на складе (вызывается внешний сервис по REST/HTTP). Если товара нет, то обработка заказа прекращается. * - Сохранить заказ в БД заказов * - Запустить дальнейшую обработку заказа (Processing, вызывается внешний сервис по REST/HTTP) * - Инициировать уведомления о новом заказе (Notification, вызывается внешний сервис по REST/HTTP) * * == НОТ == * - обработка должна быть такой, что если сохранить в БД заказ не удалось, то запускать заказ в обработку (processing) и инициировать уведомление (notification) не надо * - использовать для корреляции логов идентификатор заказа * - поддержать метрики 1) количество принятых заказов 2) количество успешно обработанных заказов * - сервис должен обрабатывать до 100 заказов в секунду */ const MaxItems = 9999 // ... (остальной код не переводится)

sobes.tech AI

Answer from AI

To implement the order processing service with the specified requirements, you can use the following approach:

  • Check product availability: call an external REST service; if the product is not available, stop processing.

  • Save the order to the database: if saving fails, do not proceed with further processing and notifications.

  • Start further processing and notifications: call the respective REST services.

  • Log correlation: use the order ID as part of the logging context (e.g., via MDC in SLF4J).

  • Metrics: use counters for the number of received and successfully processed orders (e.g., Micrometer).

  • Performance: ensure asynchronous processing limited to 100 orders per second, for example, using a thread pool or reactive approach.

Example of simplified Java code using Spring Boot and RestTemplate:

@Service
public class OrderProcessingService {
    private final RestTemplate restTemplate;
    private final OrderRepository orderRepository;
    private final MeterRegistry meterRegistry;

    private final Counter acceptedOrders;
    private final Counter successfulOrders;

    public OrderProcessingService(RestTemplate restTemplate, OrderRepository orderRepository, MeterRegistry meterRegistry) {
        this.restTemplate = restTemplate;
        this.orderRepository = orderRepository;
        this.meterRegistry = meterRegistry;
        this.acceptedOrders = meterRegistry.counter("orders.accepted");
        this.successfulOrders = meterRegistry.counter("orders.successful");
    }

    public void processOrder(Order order) {
        MDC.put("orderId", order.getId());
        acceptedOrders.increment();

        // Check product availability
        Boolean inStock = restTemplate.getForObject("http://stock-service/api/stock/{productId}", Boolean.class, order.getProductId());
        if (inStock == null || !inStock) {
            // Product not available, stop processing
            MDC.clear();
            return;
        }

        try {
            orderRepository.save(order);
        } catch (Exception e) {
            // Failed to save order, do not proceed with processing and notification
            MDC.clear();
            return;
        }

        // Start further processing
        restTemplate.postForEntity("http://processing-service/api/process", order, Void.class);

        // Initiate notifications
        restTemplate.postForEntity("http://notification-service/api/notify", order, Void.class);

        successfulOrders.increment();
        MDC.clear();
    }
}

To ensure throughput of up to 100 orders per second, you can use:

  • Asynchronous processing with a queue and thread pool.
  • Reactive libraries (Spring WebFlux).
  • Rate limiting on incoming requests.

Thus, the service will correctly process orders, track metrics, and log with correlation by order ID.