Skip to content

Commit

Permalink
Make error-handling in transform consistent with other syncers
Browse files Browse the repository at this point in the history
  • Loading branch information
salander85 committed Oct 31, 2023
1 parent f62e210 commit 751492a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.time.Clock;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import javax.annotation.Nonnull;
import org.slf4j.Logger;
Expand Down Expand Up @@ -77,16 +78,25 @@ public static StateSyncer of(
protected CompletionStage<List<StateDraft>> transform(@Nonnull List<State> states) {
return toStateDrafts(getSourceClient(), referenceIdToKeyCache, states)
.handle(
(drafts, exception) -> {
if (exception != null) {
final SyncException syncException = new SyncException(exception.getCause());
logErrorCallback(LOGGER, "state", syncException, Optional.empty(), List.of());
(stateDrafts, throwable) -> {
if (throwable != null) {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn(throwable.getMessage(), getCompletionExceptionCause(throwable));
}
return List.of();
}
return drafts;
return stateDrafts;
});
}

@Nonnull
private static Throwable getCompletionExceptionCause(@Nonnull final Throwable exception) {
if (exception instanceof CompletionException) {
return getCompletionExceptionCause(exception.getCause());
}
return exception;
}

@Nonnull
@Override
protected ByProjectKeyStatesGet getQuery() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
import com.commercetools.api.models.state.StatePagedQueryResponseBuilder;
import com.commercetools.api.models.state.StateResourceIdentifierBuilder;
import com.commercetools.api.models.state.StateTypeEnum;
import com.commercetools.sync.commons.exceptions.ReferenceTransformException;
import com.commercetools.sync.states.StateSync;
import io.vrap.rmf.base.client.ApiHttpResponse;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
Expand Down Expand Up @@ -111,41 +114,30 @@ void getQuery_ShouldBuildStateQuery() {
}

@Test
void syncWithError_WhenNoKeyIsProvided_ShouldCallErrorCallback() {
void syncWithError_WhenNoKeyIsProvided_ShouldContinueAndLogError() {
// preparation
final ProjectApiRoot sourceClient = mock(ProjectApiRoot.class);
final List<State> stateTypePage =
List.of(readObjectFromResource("state-without-key.json", State.class));
final StatePagedQueryResponse queryResponse =
StatePagedQueryResponseBuilder.of()
.results(stateTypePage)
.limit(20L)
.offset(0L)
.count(1L)
.build();
final ApiHttpResponse apiHttpResponse = mock(ApiHttpResponse.class);
when(apiHttpResponse.getBody()).thenReturn(queryResponse);
final ByProjectKeyStatesGet byProjectKeyStatesGet = mock(ByProjectKeyStatesGet.class);
when(byProjectKeyStatesGet.withLimit(anyInt())).thenReturn(byProjectKeyStatesGet);
when(byProjectKeyStatesGet.withWithTotal(anyBoolean())).thenReturn(byProjectKeyStatesGet);
when(byProjectKeyStatesGet.withSort(anyString())).thenReturn(byProjectKeyStatesGet);
when(byProjectKeyStatesGet.execute())
.thenReturn(CompletableFuture.completedFuture(apiHttpResponse));
when(sourceClient.states()).thenReturn(mock());
when(sourceClient.states().get()).thenReturn(byProjectKeyStatesGet);

// test
final StateSyncer stateSyncer =
StateSyncer.of(sourceClient, mock(ProjectApiRoot.class), getMockedClock());
stateSyncer.sync(null, true).toCompletableFuture().join();
final CompletableFuture<List<StateDraft>> stateDrafts = stateSyncer.transform(stateTypePage).toCompletableFuture();

// assertion
final LoggingEvent errorLog = syncerTestLogger.getAllLoggingEvents().get(1);
assertThat(errorLog.getMessage())
.isEqualTo(
"Error when trying to sync state. Existing key: <<not present>>. Update actions: []");
assertThat(errorLog.getThrowable().get().getMessage())
.containsIgnoringCase("StateDraft: key is missing");
assertThat(stateDrafts).isCompletedWithValue(Collections.emptyList());
assertThat(syncerTestLogger.getAllLoggingEvents())
.anySatisfy(
loggingEvent -> {
assertThat(loggingEvent.getMessage())
.contains(
NullPointerException.class.getCanonicalName()
+ ": StateDraft: key is missing");
assertThat(loggingEvent.getThrowable().isPresent()).isTrue();
assertThat(loggingEvent.getThrowable().get().getCause().getCause())
.isInstanceOf(NullPointerException.class);
});
}

/*
Expand Down

0 comments on commit 751492a

Please sign in to comment.