use of org.folio.inventory.domain.instances.InstanceCollection in project mod-inventory by folio-org.
the class CreateInstanceEventHandler method handle.
@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
try {
dataImportEventPayload.setEventType(DI_INVENTORY_INSTANCE_CREATED.value());
HashMap<String, String> payloadContext = dataImportEventPayload.getContext();
if (payloadContext == null || payloadContext.isEmpty() || isEmpty(dataImportEventPayload.getContext().get(MARC_BIBLIOGRAPHIC.value()))) {
LOGGER.error(PAYLOAD_HAS_NO_DATA_MSG);
return CompletableFuture.failedFuture(new EventProcessingException(PAYLOAD_HAS_NO_DATA_MSG));
}
String jobExecutionId = dataImportEventPayload.getJobExecutionId();
String recordId = dataImportEventPayload.getContext().get(RECORD_ID_HEADER);
if (dataImportEventPayload.getCurrentNode().getChildSnapshotWrappers().isEmpty()) {
LOGGER.error(ACTION_HAS_NO_MAPPING_MSG);
return CompletableFuture.failedFuture(new EventProcessingException(format(ACTION_HAS_NO_MAPPING_MSG, jobExecutionId, recordId)));
}
Context context = EventHandlingUtil.constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
Record targetRecord = Json.decodeValue(payloadContext.get(EntityType.MARC_BIBLIOGRAPHIC.value()), Record.class);
String chunkId = dataImportEventPayload.getContext().get(CHUNK_ID_HEADER);
Future<RecordToEntity> recordToInstanceFuture = idStorageService.store(targetRecord.getId(), UUID.randomUUID().toString(), dataImportEventPayload.getTenant());
recordToInstanceFuture.onSuccess(res -> {
String instanceId = res.getEntityId();
mappingMetadataCache.get(jobExecutionId, context).compose(parametersOptional -> parametersOptional.map(mappingMetadata -> prepareAndExecuteMapping(dataImportEventPayload, new JsonObject(mappingMetadata.getMappingRules()), Json.decodeValue(mappingMetadata.getMappingParams(), MappingParameters.class))).orElseGet(() -> Future.failedFuture(format(MAPPING_PARAMETERS_NOT_FOUND_MSG, jobExecutionId, recordId, chunkId)))).compose(v -> {
InstanceCollection instanceCollection = storage.getInstanceCollection(context);
JsonObject instanceAsJson = prepareInstance(dataImportEventPayload, instanceId, jobExecutionId);
List<String> errors = EventHandlingUtil.validateJsonByRequiredFields(instanceAsJson, requiredFields);
if (!errors.isEmpty()) {
String msg = format("Mapped Instance is invalid: %s, by jobExecutionId: '%s' and recordId: '%s' and chunkId: '%s' ", errors, jobExecutionId, recordId, chunkId);
LOGGER.warn(msg);
return Future.failedFuture(msg);
}
Instance mappedInstance = Instance.fromJson(instanceAsJson);
return addInstance(mappedInstance, instanceCollection).compose(createdInstance -> precedingSucceedingTitlesHelper.createPrecedingSucceedingTitles(mappedInstance, context).map(createdInstance));
}).onSuccess(ar -> {
dataImportEventPayload.getContext().put(INSTANCE.value(), Json.encode(ar));
future.complete(dataImportEventPayload);
}).onFailure(e -> {
if (!(e instanceof DuplicateEventException)) {
LOGGER.error("Error creating inventory Instance by jobExecutionId: '{}' and recordId: '{}' and chunkId: '{}' ", jobExecutionId, recordId, chunkId, e);
}
future.completeExceptionally(e);
});
}).onFailure(failure -> {
LOGGER.error("Error creating inventory recordId and instanceId relationship by jobExecutionId: '{}' and recordId: '{}' and chunkId: '{}' ", jobExecutionId, recordId, chunkId, failure);
future.completeExceptionally(failure);
});
} catch (Exception e) {
LOGGER.error("Error creating inventory Instance", e);
future.completeExceptionally(e);
}
return future;
}
use of org.folio.inventory.domain.instances.InstanceCollection in project mod-inventory by folio-org.
the class MarcBibMatchedPostProcessingEventHandler method handle.
@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
try {
HashMap<String, String> payloadContext = dataImportEventPayload.getContext();
if (isNull(payloadContext)) {
LOGGER.error(PAYLOAD_HAS_NO_DATA_MSG);
future.completeExceptionally(new EventProcessingException(PAYLOAD_HAS_NO_DATA_MSG));
return future;
}
if (isBlank(payloadContext.get(MATCHED_MARC_BIB_KEY))) {
LOGGER.info(MATCHED_RECORD_NOT_EXISTS_MSG);
future.complete(dataImportEventPayload);
return future;
}
Record matchedRecord = new JsonObject(payloadContext.get(MATCHED_MARC_BIB_KEY)).mapTo(Record.class);
String instanceId = ParsedRecordUtil.getAdditionalSubfieldValue(matchedRecord.getParsedRecord(), ParsedRecordUtil.AdditionalSubfields.I);
Context context = EventHandlingUtil.constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
InstanceCollection instanceCollection = storage.getInstanceCollection(context);
HoldingCollection holdingCollection = storage.getHoldingCollection(context);
if (isBlank(instanceId)) {
future.complete(dataImportEventPayload);
return future;
}
instanceCollection.findById(instanceId).whenComplete((v, t) -> {
if (t == null && v != null) {
dataImportEventPayload.getContext().put(INSTANCE.value(), Json.encode(v));
try {
holdingCollection.findByCql(format("instanceId=%s", v.getId()), PagingParameters.defaults(), findResult -> {
if (findResult.getResult() != null && findResult.getResult().totalRecords == 1) {
dataImportEventPayload.getContext().put(HOLDINGS.value(), Json.encode(findResult.getResult().records.get(0)));
}
future.complete(dataImportEventPayload);
}, failure -> {
LOGGER.error(ERROR_HOLDING_MSG + format(". StatusCode: %s. Message: %s", failure.getStatusCode(), failure.getReason()));
future.complete(dataImportEventPayload);
});
} catch (UnsupportedEncodingException e) {
LOGGER.error(ERROR_HOLDING_MSG, e);
future.complete(dataImportEventPayload);
}
} else {
LOGGER.error(ERROR_INSTANCE_MSG, t);
future.complete(dataImportEventPayload);
}
});
} catch (Exception e) {
LOGGER.error(ERROR_INSTANCE_MSG, e);
future.completeExceptionally(e);
}
return future;
}
use of org.folio.inventory.domain.instances.InstanceCollection in project mod-inventory by folio-org.
the class ReplaceInstanceEventHandler method handle.
@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
// NOSONAR
CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
try {
dataImportEventPayload.setEventType(DI_INVENTORY_INSTANCE_UPDATED.value());
HashMap<String, String> payloadContext = dataImportEventPayload.getContext();
if (payloadContext == null || payloadContext.isEmpty() || isEmpty(dataImportEventPayload.getContext().get(MARC_BIBLIOGRAPHIC.value())) || isEmpty(dataImportEventPayload.getContext().get(INSTANCE.value()))) {
LOGGER.error(PAYLOAD_HAS_NO_DATA_MSG);
return CompletableFuture.failedFuture(new EventProcessingException(PAYLOAD_HAS_NO_DATA_MSG));
}
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 ReplaceInstanceEventHandler starting with jobExecutionId: {}.", dataImportEventPayload.getJobExecutionId());
Context context = EventHandlingUtil.constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
Instance instanceToUpdate = Instance.fromJson(new JsonObject(dataImportEventPayload.getContext().get(INSTANCE.value())));
prepareEvent(dataImportEventPayload);
String jobExecutionId = dataImportEventPayload.getJobExecutionId();
String recordId = dataImportEventPayload.getContext().get(RECORD_ID_HEADER);
String chunkId = dataImportEventPayload.getContext().get(CHUNK_ID_HEADER);
mappingMetadataCache.get(jobExecutionId, context).compose(parametersOptional -> parametersOptional.map(mappingMetadata -> prepareAndExecuteMapping(dataImportEventPayload, new JsonObject(mappingMetadata.getMappingRules()), new JsonObject(mappingMetadata.getMappingParams()).mapTo(MappingParameters.class), instanceToUpdate)).orElseGet(() -> Future.failedFuture(format(MAPPING_PARAMETERS_NOT_FOUND_MSG, jobExecutionId, recordId, chunkId)))).compose(e -> {
JsonObject instanceAsJson = prepareTargetInstance(dataImportEventPayload, instanceToUpdate);
InstanceCollection instanceCollection = storage.getInstanceCollection(context);
List<String> errors = EventHandlingUtil.validateJsonByRequiredFields(instanceAsJson, requiredFields);
if (!errors.isEmpty()) {
String msg = format("Mapped Instance is invalid: %s, by jobExecutionId: '%s' and recordId: '%s' and chunkId: '%s' ", errors, jobExecutionId, recordId, chunkId);
LOGGER.warn(msg);
return Future.failedFuture(msg);
}
Instance mappedInstance = Instance.fromJson(instanceAsJson);
return updateInstanceAndRetryIfOlExists(mappedInstance, instanceCollection, dataImportEventPayload).compose(updatedInstance -> precedingSucceedingTitlesHelper.getExistingPrecedingSucceedingTitles(mappedInstance, context)).map(precedingSucceedingTitles -> precedingSucceedingTitles.stream().map(titleJson -> titleJson.getString("id")).collect(Collectors.toSet())).compose(titlesIds -> precedingSucceedingTitlesHelper.deletePrecedingSucceedingTitles(titlesIds, context)).compose(ar -> precedingSucceedingTitlesHelper.createPrecedingSucceedingTitles(mappedInstance, context)).map(instanceAsJson);
}).onComplete(ar -> {
if (ar.succeeded()) {
dataImportEventPayload.getContext().put(INSTANCE.value(), ar.result().encode());
dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
future.complete(dataImportEventPayload);
} else {
dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
String errMessage = format("Error updating inventory Instance by jobExecutionId: '%s' and recordId: '%s' and chunkId: '%s': %s ", jobExecutionId, recordId, chunkId, ar.cause());
LOGGER.error(errMessage);
future.completeExceptionally(ar.cause());
}
});
} catch (Exception e) {
LOGGER.error("Error updating inventory Instance", e);
future.completeExceptionally(e);
}
return future;
}
use of org.folio.inventory.domain.instances.InstanceCollection in project mod-inventory by folio-org.
the class MatchInstanceEventHandlerUnitTest method shouldPutMultipleMatchResultToPayloadOnHandleEventPayload.
@Test
public void shouldPutMultipleMatchResultToPayloadOnHandleEventPayload(TestContext testContext) throws UnsupportedEncodingException {
Async async = testContext.async();
List<Instance> matchedInstances = List.of(new Instance(UUID.randomUUID().toString(), "1", "in1", "MARC", "Wonderful", "12334"), new Instance(UUID.randomUUID().toString(), "1", "in2", "MARC", "Wonderful", "12334"));
doAnswer(invocation -> {
Consumer<Success<MultipleRecords<Instance>>> successHandler = invocation.getArgument(2);
Success<MultipleRecords<Instance>> result = new Success<>(new MultipleRecords<>(matchedInstances, 2));
successHandler.accept(result);
return null;
}).when(instanceCollection).findByCql(eq(format("hrid == \"%s\"", INSTANCE_HRID)), any(PagingParameters.class), any(Consumer.class), any(Consumer.class));
MatchProfile subMatchProfile = new MatchProfile().withExistingRecordType(INSTANCE).withIncomingRecordType(MARC_BIBLIOGRAPHIC);
EventHandler eventHandler = new MatchInstanceEventHandler(mappingMetadataCache);
HashMap<String, String> context = new HashMap<>();
context.put(MAPPING_PARAMS, LOCATIONS_PARAMS);
context.put(RELATIONS, MATCHING_RELATIONS);
DataImportEventPayload eventPayload = createEventPayload().withContext(context);
eventPayload.getCurrentNode().setChildSnapshotWrappers(List.of(new ProfileSnapshotWrapper().withContent(subMatchProfile).withContentType(MATCH_PROFILE).withReactTo(MATCH)));
eventHandler.handle(eventPayload).whenComplete((processedPayload, throwable) -> testContext.verify(v -> {
testContext.assertNull(throwable);
testContext.assertEquals(1, processedPayload.getEventsChain().size());
testContext.assertEquals(DI_INVENTORY_INSTANCE_MATCHED.value(), processedPayload.getEventType());
assertThat(new JsonArray(processedPayload.getContext().get(MULTI_MATCH_IDS)), hasItems(matchedInstances.get(0).getId(), matchedInstances.get(1).getId()));
async.complete();
}));
}
use of org.folio.inventory.domain.instances.InstanceCollection in project mod-inventory by folio-org.
the class ExternalInstanceCollectionFailureExamples method serverErrorWhenGettingAllInstancesTriggersFailureCallback.
@Test
public void serverErrorWhenGettingAllInstancesTriggersFailureCallback() throws InterruptedException, ExecutionException, TimeoutException {
InstanceCollection collection = createCollection();
CompletableFuture<Failure> failureCalled = new CompletableFuture<>();
collection.findAll(PagingParameters.defaults(), success -> fail("Completion callback should not be called"), failureCalled::complete);
Failure failure = failureCalled.get(1000, TimeUnit.MILLISECONDS);
check(failure);
}
Aggregations