diff --git a/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java b/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java index c9d0b2b7f..e32dac6d9 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java +++ b/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java @@ -295,4 +295,61 @@ public BrAPIObservation updateBrAPIObservation(String dbId, BrAPIObservation obs throw new InternalServerException("Unknown error has occurred: " + e.getMessage(), e); } } + + // This method overloads updateBrAPIObservation(String dbId, BrAPIObservation observation, UUID programId) + // It was added to increase efficiency. It insures that ProgramCache.populate() is called only once + // not once per observation. + public List updateBrAPIObservation(Map mutatedObservationByDbId, UUID programId) throws ApiException { + ObservationsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ObservationsApi.class); + var program = programDAO.fetchOneById(programId); + + List updatedObservations = new ArrayList<>(); + try { + for (Map.Entry entry : mutatedObservationByDbId.entrySet()) { + String dbId = entry.getKey(); + BrAPIObservation observation = entry.getValue(); + if (observation == null) { + throw new Exception("Null observation"); + } + + ApiResponse response = null; + try { + response = api.observationsObservationDbIdPut(dbId, observation); + } catch (ApiException e) { + throw new RuntimeException(e); + } + if (response == null) { + throw new ApiException("Response is null", 0, null, null); + } + BrAPIObservationSingleResponse body = response.getBody(); + if (body == null) { + throw new ApiException("Response is missing body", 0, response.getHeaders(), null); + } + BrAPIObservation updatedObservation = body.getResult(); + if (updatedObservation == null) { + throw new ApiException("Response body is missing result", 0, response.getHeaders(), response.getBody().toString()); + } + updatedObservations.add(updatedObservation); + + if (!Objects.equals(observation.getValue(), updatedObservation.getValue()) + || !Objects.equals(observation.getObservationTimeStamp(), updatedObservation.getObservationTimeStamp())) { + String message; + if (!Objects.equals(observation.getValue(), updatedObservation.getValue())) { + message = String.format("Updated observation, %s, from BrAPI service does not match requested update %s.", updatedObservation.getValue(), observation.getValue()); + } else { + message = String.format("Updated observation timestamp, %s, from BrAPI service does not match requested update timestamp %s.", updatedObservation.getObservationTimeStamp(), observation.getObservationTimeStamp()); + } + throw new Exception(message); + } + } + Map processedObservations = processObservationsForCache(updatedObservations, program.getKey()); + return programObservationCache.postThese(programId,processedObservations); + } catch (ApiException e) { + log.error("Error updating observation: " + Utilities.generateApiExceptionLogMessage(e), e); + throw e; + } catch (Exception e) { + log.error("Error updating observation: ", e); + throw new InternalServerException(e.getMessage(), e); + } + } } diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/appendoverwrite/factory/entity/PendingObservation.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/appendoverwrite/factory/entity/PendingObservation.java index edf63408c..47c016af6 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/appendoverwrite/factory/entity/PendingObservation.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/appendoverwrite/factory/entity/PendingObservation.java @@ -31,9 +31,7 @@ import org.breedinginsight.services.OntologyService; import org.breedinginsight.services.exceptions.DoesNotExistException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; @Prototype @@ -114,14 +112,12 @@ public List brapiPut(List members) throws ApiException, IllegalArgumen if (experimentUtilities.isInvalidMemberListForClass(members, BrAPIObservation.class)) { return new ArrayList(); } + Map mutatedObservationByDbId = members.stream().collect(Collectors.toMap( + m -> ((BrAPIObservation) m).getObservationDbId(), + m -> ((BrAPIObservation) m) + )); + return (List) brAPIObservationDAO.updateBrAPIObservation(mutatedObservationByDbId, importContext.getProgram().getId()); - List updatedObservations = new ArrayList<>(); - for (U member : members) { - BrAPIObservation observation = (BrAPIObservation) member; - Optional.ofNullable(brAPIObservationDAO.updateBrAPIObservation(observation.getObservationDbId(), observation, importContext.getProgram().getId())).ifPresent(updatedObservations::add); - } - - return (List) updatedObservations; } /** diff --git a/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java b/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java index 5de4e7344..213a7f6bc 100644 --- a/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java +++ b/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java @@ -174,16 +174,26 @@ public List post(UUID key, Callable> postMethod) throws Except Map response = null; try { response = postMethod.call(); + return postThese(key, response); + } catch (Exception e) { + log.error("Error posting data and populating the cache", e); + invalidate(key); + throw e; + } + } + public List postThese(UUID key, Map toBePosted) throws Exception { + log.debug("posting for key: " + generateCacheKey(key)); + try { String cacheKey = generateCacheKey(key); RMap map = connection.getMap(cacheKey); - //temporarily populate the cache with the returned objects from the postMethod so they show in immediate cache requests - for(Map.Entry obj : response.entrySet()) { + //temporarily populate the cache with the returned objects from the postMethod, so they show in immediate cache requests + for(Map.Entry obj : toBePosted.entrySet()) { map.put(obj.getKey(), gson.toJson(obj.getValue())); } populate(key); - return new ArrayList<>(response.values()); + return new ArrayList<>(toBePosted.values()); } catch (Exception e) { log.error("Error posting data and populating the cache", e); invalidate(key);