Commit e551515b authored by Anastasios Poimenidis's avatar Anastasios Poimenidis
Browse files

feat: introduce locking in Service Order API PATCH operations

parent e5f08dc3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ public class ServiceOrderKafkaListener {
                    AlarmLogsConstants.KAFKA_SERVICE_ORDER_UPDATE_MESSAGE_ALARM_LOG + " %s",
                    serviceOrderItemUpdateState.getServiceOrderId());
        }
        serviceOrderService.updateServiceOrderAndServiceOrderItemFromIncomingMessage(
        serviceOrderService.updateServiceOrderFromIncomingMessage(
                serviceOrderItemUpdateState, cloudEventServiceOrderStateUpdate.getId());
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ public class ExecutedRulesAddServiceOrderNotes extends BasicRule {

        String messageNote = String.format("Executed rules: %s", rulesExecuted);

        serviceOrderService.addNoteToServiceOrder(serviceOrderId, messageNote);
        serviceOrderService.addNoteToPersistedServiceOrder(serviceOrderId, messageNote);

        logger.infof("Executed rule %s", this.getName());
    }
+62 −51
Original line number Diff line number Diff line
@@ -163,9 +163,20 @@ public class ServiceOrderService {
        }
    }

    @Transactional
    public Optional<ServiceOrder> getOptionalServiceOrderById(String id) {
        return this.getOptionalServiceOrder(id);
    public ServiceOrder getServiceOrderByIdWithLock(String id) {
        Optional<ServiceOrder> serviceOrder = this.getOptionalServiceOrderByIdWithLock(id);
        if (serviceOrder.isPresent()) {
            String foundMessage = String.format("Service Order with id %s was found", id);
            logger.info(foundMessage);
            return serviceOrder.get();
        } else {
            String notFoundMessage = String.format("Service Order with id %s not found", id);
            throw new ServiceNotFoundException(notFoundMessage);
        }
    }

    public Optional<ServiceOrder> getOptionalServiceOrderByIdWithLock(String id) {
        return serviceOrderRepository.findByIdWithLockWrite(id);
    }

    public Optional<ServiceOrder> getOptionalServiceOrder(String id) {
@@ -211,7 +222,7 @@ public class ServiceOrderService {
    @WithSpan("ServiceOrderService.deleteServiceOrder")
    @Transactional
    public void deleteServiceOrder(String id) {
        ServiceOrder serviceOrder = getById(id);
        ServiceOrder serviceOrder = this.getById(id);
        serviceOrderRepository.delete(serviceOrder);
    }

@@ -239,7 +250,7 @@ public class ServiceOrderService {
    public ServiceOrderResponse updateServiceOrder(
            String serviceOrderId, ServiceOrderDTO request, String httpMethod) {
        try {
            ServiceOrder oldServiceOrder = getById(serviceOrderId);
            ServiceOrder oldServiceOrder = this.getServiceOrderByIdWithLock(serviceOrderId);
            ServiceOrder newServiceOrder = serviceOrderMapper.serviceOrderRequestToEntity(request);

            logger.infof(
@@ -257,6 +268,51 @@ public class ServiceOrderService {
        }
    }

    /**
     * update the serviceOrderState of a service order item based on the respective ids provided.
     * since the update takes place within a transactional, the retrieved service order will be
     * persisted in the db
     *
     * @param
     * @return
     */
    @WithSpan("ServiceOrderService.updateServiceOrderFromIncomingMessage")
    @Transactional
    public void updateServiceOrderFromIncomingMessage(
            ServiceOrderItemUpdateState serviceOrderItemUpdateState, UUID messageID) {

        String serviceOrderId = serviceOrderItemUpdateState.getServiceOrderId().toString();
        String serviceOrderItemId = serviceOrderItemUpdateState.getServiceOrderItemId().toString();
        ServiceOrderStateType serviceOrderStateType =
                ServiceOrderStateType.getServiceOrderStateType(
                        serviceOrderItemUpdateState.getServiceOrderStatus().getAction());

        this.getOptionalServiceOrderByIdWithLock(serviceOrderId)
                .ifPresentOrElse(
                        serviceOrder -> {
                            updateServiceOrderItemStateById(
                                    serviceOrder, serviceOrderItemId, serviceOrderStateType);
                            updateServiceOrderState(serviceOrder, serviceOrderStateType);

                            String logMessage = "Update Service Order with id %s according to Kafka data  %s";
                            String messageNote =
                                    String.format(
                                            "Updating Service Order with id %s to state %s according to Kafka message id %s",
                                            serviceOrderId, serviceOrderStateType, messageID);
                            ServiceUtilsHelper.addServiceOrderNoteWithMessage(serviceOrder, messageNote);

                            String failureMessage = serviceOrderItemUpdateState.getFailureMessage();
                            if (StringUtils.isNotBlank(failureMessage)) {
                                String noteMessage =
                                        String.join("", "Service failed with failure message :", failureMessage);
                                ServiceUtilsHelper.addServiceOrderNoteWithMessage(serviceOrder, noteMessage);
                            }

                            logger.infof(logMessage, serviceOrderId, serviceOrderItemUpdateState);
                        },
                        () -> logger.warnf("Service Order with id %s was not found", serviceOrderId));
    }

    private void handleServiceOrderStates(
            String serviceOrderId, ServiceOrder oldServiceOrder, ServiceOrder newServiceOrder) {
        ServiceOrderStateType oldServiceOrderState = oldServiceOrder.getState();
@@ -280,7 +336,7 @@ public class ServiceOrderService {
    }

    @Transactional
    public void addNoteToServiceOrder(String serviceOrderId, String messageNote) {
    public void addNoteToPersistedServiceOrder(String serviceOrderId, String messageNote) {
        Optional<ServiceOrder> optionalServiceOrderById = getOptionalServiceOrder(serviceOrderId);

        optionalServiceOrderById.ifPresent(
@@ -336,51 +392,6 @@ public class ServiceOrderService {
        }
    }

    /**
     * update the serviceOrderState of a service order item based on the respective ids provided.
     * since the update takes place within a transactional, the retrieved service order will be
     * persisted in the db
     *
     * @param
     * @return
     */
    @WithSpan("ServiceOrderService.updateServiceOrderAndServiceOrderItemFromIncomingMessage")
    @Transactional
    public void updateServiceOrderAndServiceOrderItemFromIncomingMessage(
            ServiceOrderItemUpdateState serviceOrderItemUpdateState, UUID messageID) {

        String serviceOrderId = serviceOrderItemUpdateState.getServiceOrderId().toString();
        String serviceOrderItemId = serviceOrderItemUpdateState.getServiceOrderItemId().toString();
        ServiceOrderStateType serviceOrderStateType =
                ServiceOrderStateType.getServiceOrderStateType(
                        serviceOrderItemUpdateState.getServiceOrderStatus().getAction());

        getOptionalServiceOrderById(serviceOrderId)
                .ifPresentOrElse(
                        serviceOrder -> {
                            updateServiceOrderItemStateById(
                                    serviceOrder, serviceOrderItemId, serviceOrderStateType);
                            updateServiceOrderState(serviceOrder, serviceOrderStateType);

                            String logMessage = "Update Service Order with id %s according to Kafka data  %s";
                            String messageNote =
                                    String.format(
                                            "Updating Service Order with id %s to state %s according to Kafka message id %s",
                                            serviceOrderId, serviceOrderStateType, messageID);
                            ServiceUtilsHelper.addServiceOrderNoteWithMessage(serviceOrder, messageNote);

                            String failureMessage = serviceOrderItemUpdateState.getFailureMessage();
                            if (StringUtils.isNotBlank(failureMessage)) {
                                String noteMessage =
                                        String.join("", "Service failed with failure message :", failureMessage);
                                ServiceUtilsHelper.addServiceOrderNoteWithMessage(serviceOrder, noteMessage);
                            }

                            logger.infof(logMessage, serviceOrderId, serviceOrderItemUpdateState);
                        },
                        () -> logger.warnf("Service Order with id %s was not found", serviceOrderId));
    }

    public void addServiceOrderNoteWithRequestCode(
            ServiceOrder serviceOrder, String httpRequestCode) {
        String messageNote =
+1 −1
Original line number Diff line number Diff line
@@ -398,7 +398,7 @@ class ServiceOrderWithPackageManagerIntegrationTest {
                            .untilAsserted(
                                    () ->
                                            verify(serviceOrderService)
                                                    .updateServiceOrderAndServiceOrderItemFromIncomingMessage(
                                                    .updateServiceOrderFromIncomingMessage(
                                                            sonataServiceOrderWithCompletedStatus,
                                                            messageId // Note: use Mockito eq() and any() INSIDE verify(...)
                                                            ));
+2 −3
Original line number Diff line number Diff line
@@ -129,8 +129,7 @@ class ServiceOrderUpdateTest {

        // Verify that updateServiceOrder is called with the correct arguments
        verify(serviceOrderService, times(1))
                .updateServiceOrderAndServiceOrderItemFromIncomingMessage(
                        serviceOrderItemUpdateState, messageId);
                .updateServiceOrderFromIncomingMessage(serviceOrderItemUpdateState, messageId);

        // verify that the status update on service order has not been performed since there is one more
        // item in state ACKNOWLEDGED
@@ -193,7 +192,7 @@ class ServiceOrderUpdateTest {
                .pollInterval(200, java.util.concurrent.TimeUnit.MILLISECONDS)
                .untilAsserted(
                        () ->
                                serviceOrderService.updateServiceOrderAndServiceOrderItemFromIncomingMessage(
                                serviceOrderService.updateServiceOrderFromIncomingMessage(
                                        serviceOrderItemUpdateState, messageID));

        ServiceOrder serviceOrder =