From 7b6ab50231f5ab39d1476531031437f81328115e Mon Sep 17 00:00:00 2001 From: mpriyank Date: Tue, 6 Sep 2022 18:29:34 +0100 Subject: Handle partial failure - Removing the transaction boundaries as it was getting rollbacked on partial failures - Handled adding the elements in batch and if it fails try them individually - Refactored code a bit and when there is partial failure we try one more time in sequence and even if there are failures we collect the failures Issue-ID: CPS-1232 Issue-ID: CPS-1126 Change-Id: I7824c9f37f80cbaeedd5dc06d598ca0e3a69c59b Signed-off-by: mpriyank --- .../api/impl/NetworkCmProxyDataServiceImpl.java | 12 ++++----- .../api/models/CmHandleRegistrationResponse.java | 29 ++++++++++++++++++++++ ...rkCmProxyDataServiceImplRegistrationSpec.groovy | 24 ++++++++---------- 3 files changed, 45 insertions(+), 20 deletions(-) (limited to 'cps-ncmp-service/src') diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index 209ade9559..0eb275cf0e 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -59,7 +59,7 @@ import org.onap.cps.ncmp.api.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.exceptions.AlreadyDefinedException; +import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.exceptions.DataValidationException; @@ -365,12 +365,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService try { lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds); - } catch (final AlreadyDefinedException alreadyDefinedException) { - return List.of(CmHandleRegistrationResponse.createFailureResponse( - String.join(",", cmHandleIds), RegistrationError.CM_HANDLE_ALREADY_EXIST)); + } catch (final AlreadyDefinedExceptionBatch alreadyDefinedExceptionBatch) { + return CmHandleRegistrationResponse.createFailureResponses( + alreadyDefinedExceptionBatch.getAlreadyDefinedCmHandleIds(), + RegistrationError.CM_HANDLE_ALREADY_EXIST); } catch (final Exception exception) { - return List.of(CmHandleRegistrationResponse.createFailureResponse(String.join(",", cmHandleIds), - exception)); + return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, exception); } } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java index b7faf09a9e..9f80218420 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java @@ -21,6 +21,7 @@ package org.onap.cps.ncmp.api.models; +import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import lombok.Builder; @@ -67,6 +68,34 @@ public class CmHandleRegistrationResponse { .build(); } + /** + * Creates a failure response based on registration error. + * + * @param cmHandleIds list of failed cmHandleIds + * @param registrationError enum describing the type of registration error + * @return CmHandleRegistrationResponse + */ + public static List createFailureResponses(final Collection cmHandleIds, + final RegistrationError registrationError) { + return cmHandleIds.stream() + .map(cmHandleId -> CmHandleRegistrationResponse.createFailureResponse(cmHandleId, registrationError)) + .collect(Collectors.toList()); + } + + /** + * Creates a failure response based on other exception. + * + * @param cmHandleIds list of failed cmHandleIds + * @param exception exception caught during the registration + * @return CmHandleRegistrationResponse + */ + public static List createFailureResponses(final Collection cmHandleIds, + final Exception exception) { + return cmHandleIds.stream() + .map(cmHandleId -> CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception)) + .collect(Collectors.toList()); + } + public static CmHandleRegistrationResponse createSuccessResponse(final String cmHandle) { return CmHandleRegistrationResponse.builder().cmHandle(cmHandle) .status(Status.SUCCESS).build(); diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index 86a32a1a59..2fe521c031 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -28,14 +28,13 @@ import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService import org.onap.cps.ncmp.api.impl.event.lcm.LcmEventsCmHandleStateHandler import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.ncmp.api.inventory.CmHandleQueries import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.InventoryPersistence import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse import org.onap.cps.ncmp.api.models.DmiPluginRegistration import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle -import org.onap.cps.spi.exceptions.AlreadyDefinedException +import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch import org.onap.cps.spi.exceptions.DataNodeNotFoundException import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.exceptions.SchemaSetNotFoundException @@ -185,20 +184,17 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { new NcmpServiceCmHandle(cmHandleId: 'cmhandle2'), new NcmpServiceCmHandle(cmHandleId: 'cmhandle3')]) and: 'cm-handle creation is successful for 1st and 3rd; failed for 2nd' - mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(*_) >> { throw new RuntimeException("Failed") } + mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(*_) >> { throw new AlreadyDefinedExceptionBatch(['cmhandle2']) } when: 'registration is updated to create cm-handles' def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'a response is received for all cm-handles' response.getCreatedCmHandles().size() == 1 and: 'all cm-handles creation fails' - with(response.getCreatedCmHandles().get(0)) { + response.getCreatedCmHandles().each { + assert it.cmHandle == 'cmhandle2' assert it.status == Status.FAILURE - assert it.registrationError == UNKNOWN_ERROR - assert it.errorText == 'Failed' - def sortedCmHandles = it.cmHandle.split(',').sort() - assert sortedCmHandles[0] == 'cmhandle1' - assert sortedCmHandles[1] == 'cmhandle2' - assert sortedCmHandles[2] == 'cmhandle3' + assert it.registrationError == CM_HANDLE_ALREADY_EXIST + assert it.errorText == 'cm-handle already exists' } } @@ -219,10 +215,10 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { assert it.errorText == expectedErrorText } where: - scenario | cmHandleId | exception || expectedError | expectedErrorText - 'cm-handle already exist' | 'cmhandle' | new AlreadyDefinedException('', new RuntimeException()) || CM_HANDLE_ALREADY_EXIST | 'cm-handle already exists' - 'cm-handle has invalid name' | 'cm handle with space' | new DataValidationException("", "") || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id' - 'unknown exception while registering cm-handle' | 'cmhandle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' + scenario | cmHandleId | exception || expectedError | expectedErrorText + 'cm-handle already exist' | 'cmhandle' | new AlreadyDefinedExceptionBatch([cmHandleId]) || CM_HANDLE_ALREADY_EXIST | 'cm-handle already exists' + 'cm-handle has invalid name' | 'cm handle with space' | new DataValidationException("", "") || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id' + 'unknown exception while registering cm-handle' | 'cmhandle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' } def 'Update CM-Handle: Update Operation Response is added to the response'() { -- cgit 1.2.3-korg