Skip to content

Commit

Permalink
MODBULKOPS-301 Added offset, errorType
Browse files Browse the repository at this point in the history
  • Loading branch information
obozhko-folio committed Jan 23, 2025
1 parent b2e6be4 commit c9989b0
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.folio.bulkops.domain.dto.BulkOperationStart;
import org.folio.bulkops.domain.dto.BulkOperationStep;
import org.folio.bulkops.domain.dto.EntityType;
import org.folio.bulkops.domain.dto.ErrorType;
import org.folio.bulkops.domain.dto.Errors;
import org.folio.bulkops.domain.dto.FileContentType;
import org.folio.bulkops.domain.dto.IdentifierType;
Expand Down Expand Up @@ -92,8 +93,8 @@ public ResponseEntity<BulkOperationCollection> getBulkOperationCollection(String
}

@Override
public ResponseEntity<Errors> getErrorsPreviewByOperationId(UUID operationId, Integer limit) {
return new ResponseEntity<>(errorService.getErrorsPreviewByBulkOperationId(operationId, limit), HttpStatus.OK);
public ResponseEntity<Errors> getErrorsPreviewByOperationId(UUID operationId, Integer limit, Integer offset, ErrorType errorType) {
return new ResponseEntity<>(errorService.getErrorsPreviewByBulkOperationId(operationId, limit, offset, errorType), HttpStatus.OK);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

@Repository
public interface BulkOperationExecutionContentRepository extends JpaRepository<BulkOperationExecutionContent, UUID> {
Page<BulkOperationExecutionContent> findByBulkOperationIdAndErrorMessageIsNotNull(UUID bulkOperationId, OffsetRequest offsetRequest);
Page<BulkOperationExecutionContent> findByBulkOperationIdAndErrorMessageIsNotNullOrderByErrorType(UUID bulkOperationId, OffsetRequest offsetRequest);
Page<BulkOperationExecutionContent> findByBulkOperationIdAndErrorMessageIsNotNullAndErrorTypeIsOrderByErrorType(UUID bulkOperationId, OffsetRequest offsetRequest, ErrorType errorType);
Optional<BulkOperationExecutionContent> findFirstByBulkOperationIdAndIdentifier(UUID bulkOperationId, String identifier);
int countAllByBulkOperationIdAndErrorMessageIsNotNullAndErrorTypeIs(UUID bulkOperationId, ErrorType errorType);

Expand Down
20 changes: 13 additions & 7 deletions src/main/java/org/folio/bulkops/service/ErrorService.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.folio.bulkops.repository.BulkOperationRepository;
import org.folio.bulkops.util.Constants;
import org.folio.spring.data.OffsetRequest;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
Expand Down Expand Up @@ -90,7 +91,7 @@ public void deleteErrorsByBulkOperationId(UUID bulkOperationId) {
log.info("Errors deleted for bulk operation {}", bulkOperationId);
}

public Errors getErrorsPreviewByBulkOperationId(UUID bulkOperationId, int limit) {
public Errors getErrorsPreviewByBulkOperationId(UUID bulkOperationId, int limit, int offset, ErrorType errorType) {
var bulkOperation = operationRepository.findById(bulkOperationId)
.orElseThrow(() -> new NotFoundException("BulkOperation was not found by id=" + bulkOperationId));
if (Set.of(DATA_MODIFICATION, REVIEW_CHANGES, REVIEWED_NO_MARC_RECORDS).contains(bulkOperation.getStatus()) || COMPLETED_WITH_ERRORS == bulkOperation.getStatus() && noCommittedErrors(bulkOperation) && noCommittedWarnings(bulkOperation)) {
Expand All @@ -100,7 +101,7 @@ public Errors getErrorsPreviewByBulkOperationId(UUID bulkOperationId, int limit)
.toList())
.totalRecords(errors.getTotalRecords());
} else if (COMPLETED == bulkOperation.getStatus() || COMPLETED_WITH_ERRORS == bulkOperation.getStatus()) {
return getExecutionErrors(bulkOperationId, limit);
return getExecutionErrors(bulkOperationId, limit, offset, errorType);
} else {
throw new NotFoundException("Errors preview is not available");
}
Expand Down Expand Up @@ -151,14 +152,19 @@ private Error prepareInternalErrorRepresentation(Error e) {
return new Error().message(error[1]).parameters(List.of(new Parameter().key(IDENTIFIER).value(error[0])));
}

public String getErrorsCsvByBulkOperationId(UUID bulkOperationId) {
return getErrorsPreviewByBulkOperationId(bulkOperationId, Integer.MAX_VALUE).getErrors().stream()
public String getErrorsCsvByBulkOperationId(UUID bulkOperationId, int offset, ErrorType errorType) {
return getErrorsPreviewByBulkOperationId(bulkOperationId, Integer.MAX_VALUE, offset, errorType).getErrors().stream()
.map(error -> String.join(Constants.COMMA_DELIMETER, ObjectUtils.isEmpty(error.getParameters()) ? EMPTY : error.getParameters().get(0).getValue(), error.getMessage()))
.collect(Collectors.joining(Constants.NEW_LINE_SEPARATOR));
}

private Errors getExecutionErrors(UUID bulkOperationId, int limit) {
var errorPage = executionContentRepository.findByBulkOperationIdAndErrorMessageIsNotNull(bulkOperationId, OffsetRequest.of(0, limit));
private Errors getExecutionErrors(UUID bulkOperationId, int limit, int offset, ErrorType errorType) {
Page<BulkOperationExecutionContent> errorPage;
if (isNull(errorType)) {
errorPage = executionContentRepository.findByBulkOperationIdAndErrorMessageIsNotNullOrderByErrorType(bulkOperationId, OffsetRequest.of(offset, limit));
} else {
errorPage = executionContentRepository.findByBulkOperationIdAndErrorMessageIsNotNullAndErrorTypeIsOrderByErrorType(bulkOperationId, OffsetRequest.of(offset, limit), errorType);
}
var errors = errorPage.toList().stream()
.map(this::executionContentToFolioError)
.toList();
Expand Down Expand Up @@ -188,7 +194,7 @@ private Error executionContentToFolioError(BulkOperationExecutionContent content
}

public String uploadErrorsToStorage(UUID bulkOperationId) {
var contents = executionContentRepository.findByBulkOperationIdAndErrorMessageIsNotNull(bulkOperationId, OffsetRequest.of(0, Integer.MAX_VALUE));
var contents = executionContentRepository.findByBulkOperationIdAndErrorMessageIsNotNullOrderByErrorType(bulkOperationId, OffsetRequest.of(0, Integer.MAX_VALUE));
if (!contents.isEmpty()) {
var errorsString = contents.stream()
.map(content -> String.join(Constants.COMMA_DELIMETER, content.getIdentifier(), content.getErrorMessage(), content.getErrorType().getValue()))
Expand Down
14 changes: 14 additions & 0 deletions src/main/resources/swagger.api/bulk-operations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,18 @@ paths:
schema:
type: integer
description: The numbers of errors to return
- in: query
name: offset
required: false
schema:
type: integer
description: Query offset
- in: query
name: errorType
required: false
schema:
$ref: "#/components/schemas/errorType"
description: The error type
responses:
'200':
description: Collection of errors for preview
Expand Down Expand Up @@ -628,3 +640,5 @@ components:
record:
type: object
description: Example response
errorType:
$ref: 'schemas/error_type.json#/ErrorType'
3 changes: 1 addition & 2 deletions src/main/resources/swagger.api/schemas/error_type.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"enum": [
"ERROR",
"WARNING"
],
"default": "ERROR"
]
}
}
19 changes: 10 additions & 9 deletions src/test/java/org/folio/bulkops/service/ErrorServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ void shouldGetErrorsPreviewByBulkOperationId(OperationStatusType statusType) {

mockErrorsData(statusType, operationId);

var actual = errorService.getErrorsPreviewByBulkOperationId(operationId, 2);
var actual = errorService.getErrorsPreviewByBulkOperationId(operationId, 2, 0, null);
assertThat(actual.getErrors(), hasSize(2));

bulkOperationRepository.deleteById(operationId);
Expand All @@ -179,7 +179,7 @@ void shouldRejectErrorsPreviewOnWrongOperationStatus(OperationStatusType statusT
try (var context = new FolioExecutionContextSetter(folioExecutionContext)) {
var operationId = bulkOperationRepository.save(BulkOperation.builder().id(UUID.randomUUID()).status(statusType).build()).getId();

assertThrows(NotFoundException.class, () -> errorService.getErrorsPreviewByBulkOperationId(operationId, 10));
assertThrows(NotFoundException.class, () -> errorService.getErrorsPreviewByBulkOperationId(operationId, 10, 0, ErrorType.ERROR));

bulkOperationRepository.deleteById(operationId);
}
Expand All @@ -195,7 +195,7 @@ void shouldGetErrorsCsvByBulkOperationId(OperationStatusType statusType) {

mockErrorsData(statusType, operationId);

var actual = errorService.getErrorsCsvByBulkOperationId(operationId).split(LF);
var actual = errorService.getErrorsCsvByBulkOperationId(operationId, 0, null).split(LF);
Arrays.sort(expected);
Arrays.sort(actual);

Expand All @@ -212,7 +212,7 @@ void shouldRejectErrorsCsvOnWrongOperationStatus(OperationStatusType statusType)
try (var context = new FolioExecutionContextSetter(folioExecutionContext)) {
var operationId = bulkOperationRepository.save(BulkOperation.builder().id(UUID.randomUUID()).status(statusType).build()).getId();

assertThrows(NotFoundException.class, () -> errorService.getErrorsCsvByBulkOperationId(operationId));
assertThrows(NotFoundException.class, () -> errorService.getErrorsCsvByBulkOperationId(operationId, 0, ErrorType.ERROR));

bulkOperationRepository.deleteById(operationId);
}
Expand Down Expand Up @@ -247,7 +247,7 @@ void shouldReturnErrorsPreviewOnCompletedWithErrors(int committedErrors) {
.build());
}

var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 10);
var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 10, 0, null);

assertThat(errors.getErrors(), hasSize(2));
}
Expand All @@ -274,9 +274,10 @@ void testOptimisticLockErrorProcessing() {
.errorMessage(format("%s %s", message, link))
.uiErrorMessage(message)
.linkToFailedEntity(link)
.errorType(ErrorType.ERROR)
.build());

var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 1);
var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 1, 0, ErrorType.ERROR);

assertThat(errors.getErrors(), hasSize(1));
assertThat(errors.getErrors().get(0).getParameters(), hasSize(2));
Expand Down Expand Up @@ -320,7 +321,7 @@ void testSaveErrorsFromDataImport(IdentifierType identifierType, boolean related
.build())
.getId();
errorService.saveErrorsFromDataImport(operationId, dataImportJobId);
var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 1);
var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 1, 0, ErrorType.ERROR);

assertThat(errors.getErrors(), hasSize(1));
assertEquals("some MARC error", errors.getErrors().get(0).getMessage());
Expand All @@ -346,7 +347,7 @@ void shouldNotSaveError_IfErrorFromDataImportIsEmpty() {
.build())
.getId();
errorService.saveErrorsFromDataImport(operationId, dataImportJobId);
var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 1);
var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 1, 0, ErrorType.ERROR);

assertThat(errors.getErrors(), hasSize(0));
}
Expand Down Expand Up @@ -375,7 +376,7 @@ void testSaveErrorsFromDataImport_whenDiscardedAndNoMessage() {
.build())
.getId();
errorService.saveErrorsFromDataImport(operationId, dataImportJobId);
var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 1);
var errors = errorService.getErrorsPreviewByBulkOperationId(operationId, 1, 0, ErrorType.ERROR);

assertThat(errors.getErrors(), hasSize(1));
assertEquals(DATA_IMPORT_ERROR_DISCARDED, errors.getErrors().get(0).getMessage());
Expand Down

0 comments on commit c9989b0

Please sign in to comment.