Search in sources :

Example 1 with HoldingsRecordCollection

use of org.folio.inventory.domain.HoldingsRecordCollection in project mod-inventory by folio-org.

the class CreateHoldingEventHandler method addHoldings.

private Future<HoldingsRecord> addHoldings(HoldingsRecord holdings, Context context) {
    Promise<HoldingsRecord> promise = Promise.promise();
    HoldingsRecordCollection holdingsRecordCollection = storage.getHoldingsRecordCollection(context);
    holdingsRecordCollection.add(holdings, success -> promise.complete(success.getResult()), failure -> {
        // for now there is a solution via error-message contains. It will be improved via another solution by https://issues.folio.org/browse/RMB-899.
        if (isNotBlank(failure.getReason()) && failure.getReason().contains(UNIQUE_ID_ERROR_MESSAGE)) {
            LOGGER.info("Duplicated event received by InstanceId: {}. Ignoring...", holdings.getId());
            promise.fail(new DuplicateEventException(format("Duplicated event by Holding id: %s", holdings.getId())));
        } else {
            LOGGER.error(format("Error posting Holdings cause %s, status code %s", failure.getReason(), failure.getStatusCode()));
            promise.fail(failure.getReason());
        }
    });
    return promise.future();
}
Also used : DuplicateEventException(org.folio.kafka.exception.DuplicateEventException) HoldingsRecord(org.folio.HoldingsRecord) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection)

Example 2 with HoldingsRecordCollection

use of org.folio.inventory.domain.HoldingsRecordCollection in project mod-inventory by folio-org.

the class HoldingsUpdateDelegate method handle.

public Future<HoldingsRecord> handle(Map<String, String> eventPayload, Record marcRecord, Context context) {
    try {
        JsonObject mappingRules = new JsonObject(eventPayload.get(MAPPING_RULES_KEY));
        MappingParameters mappingParameters = new JsonObject(eventPayload.get(MAPPING_PARAMS_KEY)).mapTo(MappingParameters.class);
        JsonObject parsedRecord = retrieveParsedContent(marcRecord.getParsedRecord());
        String holdingsId = marcRecord.getExternalIdsHolder().getHoldingsId();
        RecordMapper<Holdings> recordMapper = RecordMapperBuilder.buildMapper(MARC_FORMAT);
        var mappedHoldings = recordMapper.mapRecord(parsedRecord, mappingParameters, mappingRules);
        HoldingsRecordCollection holdingsRecordCollection = storage.getHoldingsRecordCollection(context);
        return getHoldingsRecordById(holdingsId, holdingsRecordCollection).onSuccess(existingHoldingsRecord -> fillVersion(existingHoldingsRecord, eventPayload)).compose(existingHoldingsRecord -> mergeRecords(existingHoldingsRecord, mappedHoldings)).compose(updatedHoldingsRecord -> updateHoldingsRecord(updatedHoldingsRecord, holdingsRecordCollection));
    } catch (Exception e) {
        LOGGER.error("Error updating inventory holdings", e);
        return Future.failedFuture(e);
    }
}
Also used : Context(org.folio.inventory.common.Context) Holdings(org.folio.Holdings) Record(org.folio.rest.jaxrs.model.Record) Promise(io.vertx.core.Promise) HttpStatus(org.apache.http.HttpStatus) Future(io.vertx.core.Future) HoldingsRecord(org.folio.HoldingsRecord) String.format(java.lang.String.format) RecordMapperBuilder(org.folio.processing.mapping.defaultmapper.RecordMapperBuilder) Storage(org.folio.inventory.storage.Storage) Logger(org.apache.logging.log4j.Logger) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) Map(java.util.Map) JsonObject(io.vertx.core.json.JsonObject) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException) LogManager(org.apache.logging.log4j.LogManager) ParsedRecord(org.folio.rest.jaxrs.model.ParsedRecord) RecordMapper(org.folio.processing.mapping.defaultmapper.RecordMapper) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) Holdings(org.folio.Holdings) JsonObject(io.vertx.core.json.JsonObject) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException)

Example 3 with HoldingsRecordCollection

use of org.folio.inventory.domain.HoldingsRecordCollection in project mod-inventory by folio-org.

the class UpdateHoldingEventHandler method handle.

@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
    CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
    try {
        dataImportEventPayload.setEventType(DI_INVENTORY_HOLDING_UPDATED.value());
        if (dataImportEventPayload.getContext() == null || isEmpty(dataImportEventPayload.getContext().get(HOLDINGS.value())) || isEmpty(dataImportEventPayload.getContext().get(MARC_BIBLIOGRAPHIC.value()))) {
            throw new EventProcessingException(CONTEXT_EMPTY_ERROR_MESSAGE);
        }
        if (dataImportEventPayload.getCurrentNode().getChildSnapshotWrappers().isEmpty()) {
            LOGGER.error(ACTION_HAS_NO_MAPPING_MSG);
            return CompletableFuture.failedFuture(new EventProcessingException(ACTION_HAS_NO_MAPPING_MSG));
        }
        LOGGER.info("Processing UpdateHoldingEventHandler starting with jobExecutionId: {}.", dataImportEventPayload.getJobExecutionId());
        HoldingsRecord tmpHoldingsRecord = retrieveHolding(dataImportEventPayload.getContext());
        String holdingId = tmpHoldingsRecord.getId();
        String hrid = tmpHoldingsRecord.getHrid();
        String instanceId = tmpHoldingsRecord.getInstanceId();
        String permanentLocationId = tmpHoldingsRecord.getPermanentLocationId();
        if (StringUtils.isAnyBlank(hrid, instanceId, permanentLocationId, holdingId)) {
            throw new EventProcessingException(EMPTY_REQUIRED_FIELDS_ERROR_MESSAGE);
        }
        Context context = constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
        String jobExecutionId = dataImportEventPayload.getJobExecutionId();
        String recordId = dataImportEventPayload.getContext().get(RECORD_ID_HEADER);
        String chunkId = dataImportEventPayload.getContext().get(CHUNK_ID_HEADER);
        mappingMetadataCache.get(jobExecutionId, context).map(parametersOptional -> parametersOptional.orElseThrow(() -> new EventProcessingException(format(MAPPING_METADATA_NOT_FOUND_MESSAGE, jobExecutionId, recordId, chunkId)))).onSuccess(mappingMetadataDto -> {
            prepareEvent(dataImportEventPayload);
            MappingParameters mappingParameters = Json.decodeValue(mappingMetadataDto.getMappingParams(), MappingParameters.class);
            MappingManager.map(dataImportEventPayload, new MappingContext().withMappingParameters(mappingParameters));
            HoldingsRecordCollection holdingsRecords = storage.getHoldingsRecordCollection(context);
            HoldingsRecord holding = retrieveHolding(dataImportEventPayload.getContext());
            holdingsRecords.update(holding, holdingSuccess -> constructDataImportEventPayload(future, dataImportEventPayload, holding), failure -> {
                if (failure.getStatusCode() == HttpStatus.SC_CONFLICT) {
                    processOLError(dataImportEventPayload, future, holdingsRecords, holding, failure);
                } else {
                    dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
                    LOGGER.error(format(CANNOT_UPDATE_HOLDING_ERROR_MESSAGE, holding.getId(), jobExecutionId, recordId, chunkId, failure.getReason(), failure.getStatusCode()));
                    future.completeExceptionally(new EventProcessingException(format(UPDATE_HOLDING_ERROR_MESSAGE, jobExecutionId, recordId, chunkId)));
                }
            });
        }).onFailure(e -> {
            LOGGER.error("Error updating inventory Holdings by jobExecutionId: '{}'", jobExecutionId, e);
            future.completeExceptionally(e);
        });
    } catch (Exception e) {
        LOGGER.error("Failed to update Holdings", e);
        future.completeExceptionally(e);
    }
    return future;
}
Also used : Context(org.folio.inventory.common.Context) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) MappingContext(org.folio.processing.mapping.mapper.MappingContext) Json(io.vertx.core.json.Json) Context(org.folio.inventory.common.Context) EventHandler(org.folio.processing.events.services.handler.EventHandler) MappingManager(org.folio.processing.mapping.MappingManager) HttpStatus(org.apache.http.HttpStatus) Failure(org.folio.inventory.common.domain.Failure) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ACTION_PROFILE(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.ACTION_PROFILE) StringUtils(org.apache.commons.lang3.StringUtils) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) HOLDINGS(org.folio.ActionProfile.FolioRecord.HOLDINGS) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) ProfileSnapshotWrapper(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper) ObjectMapperTool(org.folio.dbschema.ObjectMapperTool) JsonObject(io.vertx.core.json.JsonObject) Objects.isNull(java.util.Objects.isNull) ActionProfile(org.folio.ActionProfile) StringUtils.isEmpty(org.apache.commons.lang3.StringUtils.isEmpty) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) MARC_BIBLIOGRAPHIC(org.folio.ActionProfile.FolioRecord.MARC_BIBLIOGRAPHIC) MappingContext(org.folio.processing.mapping.mapper.MappingContext) DataImportEventPayload(org.folio.DataImportEventPayload) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) HoldingsRecord(org.folio.HoldingsRecord) String.format(java.lang.String.format) DI_INVENTORY_HOLDING_UPDATED(org.folio.DataImportEventTypes.DI_INVENTORY_HOLDING_UPDATED) Storage(org.folio.inventory.storage.Storage) UPDATE(org.folio.ActionProfile.Action.UPDATE) Logger(org.apache.logging.log4j.Logger) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) LogManager(org.apache.logging.log4j.LogManager) MappingMetadataCache(org.folio.inventory.dataimport.cache.MappingMetadataCache) MappingContext(org.folio.processing.mapping.mapper.MappingContext) HoldingsRecord(org.folio.HoldingsRecord) CompletableFuture(java.util.concurrent.CompletableFuture) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) DataImportEventPayload(org.folio.DataImportEventPayload) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 4 with HoldingsRecordCollection

use of org.folio.inventory.domain.HoldingsRecordCollection in project mod-inventory by folio-org.

the class UpdateItemEventHandler method addHoldingToPayloadIfNeeded.

private Future<DataImportEventPayload> addHoldingToPayloadIfNeeded(DataImportEventPayload dataImportEventPayload, Context context, Item updatedItem) {
    Promise<DataImportEventPayload> promise = Promise.promise();
    if (StringUtils.isBlank(dataImportEventPayload.getContext().get(HOLDINGS.value()))) {
        HoldingsRecordCollection holdingsRecordCollection = storage.getHoldingsRecordCollection(context);
        holdingsRecordCollection.findById(updatedItem.getHoldingId(), success -> {
            LOG.info("Successfully retrieved Holdings for the hotlink by id: {}", updatedItem.getHoldingId());
            dataImportEventPayload.getContext().put(HOLDINGS.value(), Json.encodePrettily(success.getResult()));
            promise.complete(dataImportEventPayload);
        }, failure -> {
            LOG.warn("Error retrieving Holdings for the hotlink by id {} cause {}, status code {}", updatedItem.getHoldingId(), failure.getReason(), failure.getStatusCode());
            promise.complete(dataImportEventPayload);
        });
    } else {
        LOG.debug("Holdings already exists in payload with for the hotlink with id {}", updatedItem.getHoldingId());
        promise.complete(dataImportEventPayload);
    }
    return promise.future();
}
Also used : HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) DataImportEventPayload(org.folio.DataImportEventPayload)

Example 5 with HoldingsRecordCollection

use of org.folio.inventory.domain.HoldingsRecordCollection in project mod-inventory by folio-org.

the class MoveApi method updateHoldings.

private void updateHoldings(RoutingContext routingContext, WebContext context, List<String> idsToUpdate, List<HoldingsRecord> holdingsToUpdate) {
    HoldingsRecordCollection storageHoldingsRecordsCollection = storage.getHoldingsRecordCollection(context);
    List<CompletableFuture<HoldingsRecord>> updateFutures = holdingsToUpdate.stream().map(storageHoldingsRecordsCollection::update).collect(Collectors.toList());
    CompletableFuture.allOf(updateFutures.toArray(new CompletableFuture[0])).handle((vVoid, throwable) -> updateFutures.stream().filter(future -> !future.isCompletedExceptionally()).map(CompletableFuture::join).map(HoldingsRecord::getId).collect(toList())).thenAccept(updatedIds -> respond(routingContext, idsToUpdate, updatedIds));
}
Also used : WebContext(org.folio.inventory.common.WebContext) ItemUtil(org.folio.inventory.support.ItemUtil) WebClient(io.vertx.ext.web.client.WebClient) URL(java.net.URL) Router(io.vertx.ext.web.Router) CompletableFuture(java.util.concurrent.CompletableFuture) Item(org.folio.inventory.domain.items.Item) RoutingContext(io.vertx.ext.web.RoutingContext) BodyHandler(io.vertx.ext.web.handler.BodyHandler) ArrayList(java.util.ArrayList) ServerErrorResponse(org.folio.inventory.support.http.server.ServerErrorResponse) JsonResponse(org.folio.inventory.support.http.server.JsonResponse) CollectionResourceClient(org.folio.inventory.storage.external.CollectionResourceClient) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) MultipleRecordsFetchClient(org.folio.inventory.storage.external.MultipleRecordsFetchClient) MoveValidator.holdingsMoveHasRequiredFields(org.folio.inventory.validation.MoveValidator.holdingsMoveHasRequiredFields) ItemCollection(org.folio.inventory.domain.items.ItemCollection) JsonObject(io.vertx.core.json.JsonObject) JsonArrayHelper.toListOfStrings(org.folio.inventory.support.JsonArrayHelper.toListOfStrings) MalformedURLException(java.net.MalformedURLException) OkapiHttpClient(org.folio.inventory.support.http.client.OkapiHttpClient) JsonResponse.unprocessableEntity(org.folio.inventory.support.http.server.JsonResponse.unprocessableEntity) JsonResponse.success(org.folio.inventory.support.http.server.JsonResponse.success) Collectors(java.util.stream.Collectors) HoldingsRecord(org.folio.HoldingsRecord) Storage(org.folio.inventory.storage.Storage) Objects(java.util.Objects) Collectors.toList(java.util.stream.Collectors.toList) MoveValidator.itemsMoveHasRequiredFields(org.folio.inventory.validation.MoveValidator.itemsMoveHasRequiredFields) List(java.util.List) ListUtils(org.apache.commons.collections15.ListUtils) HttpServerResponse(io.vertx.core.http.HttpServerResponse) ValidationError(org.folio.inventory.support.http.server.ValidationError) Optional(java.util.Optional) CqlQuery(org.folio.inventory.storage.external.CqlQuery) HttpClient(io.vertx.core.http.HttpClient) CompletableFuture(java.util.concurrent.CompletableFuture) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection)

Aggregations

HoldingsRecordCollection (org.folio.inventory.domain.HoldingsRecordCollection)6 HoldingsRecord (org.folio.HoldingsRecord)5 JsonObject (io.vertx.core.json.JsonObject)4 Storage (org.folio.inventory.storage.Storage)4 String.format (java.lang.String.format)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 HttpStatus (org.apache.http.HttpStatus)3 LogManager (org.apache.logging.log4j.LogManager)3 Logger (org.apache.logging.log4j.Logger)3 DataImportEventPayload (org.folio.DataImportEventPayload)3 Context (org.folio.inventory.common.Context)3 MappingParameters (org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters)3 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)2 Json (io.vertx.core.json.Json)2 HashMap (java.util.HashMap)2 Objects.isNull (java.util.Objects.isNull)2 StringUtils (org.apache.commons.lang3.StringUtils)2 StringUtils.isEmpty (org.apache.commons.lang3.StringUtils.isEmpty)2 ActionProfile (org.folio.ActionProfile)2 UPDATE (org.folio.ActionProfile.Action.UPDATE)2