From 382662c41c2dc5d9b2c98a0bc0dd1164a14a2d18 Mon Sep 17 00:00:00 2001 From: David Randolph Phillips Date: Wed, 17 Jul 2024 15:24:47 -0400 Subject: [PATCH 1/3] [BI-2093] Merged with BI-2109 --- .../brapi/v2/dao/BrAPIObservationDAO.java | 58 +++++++++++++++++++ .../factory/entity/PendingObservation.java | 10 ++-- .../daos/cache/ProgramCache.java | 14 ++++- 3 files changed, 75 insertions(+), 7 deletions(-) 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..cf4272d37 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,62 @@ 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 { + Map updatedObservationsByDbId = new HashMap<>(); + 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 new InternalServerException("Error saving experiment import", 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..7247b927c 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 @@ -115,13 +113,15 @@ public List brapiPut(List members) throws ApiException, IllegalArgumen return new ArrayList(); } + Map mutatedObservationByDbId = new HashMap<>(); 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); + mutatedObservationByDbId.put(observation.getObservationDbId(), observation); +// Optional.ofNullable(brAPIObservationDAO.updateBrAPIObservation(observation.getObservationDbId(), observation, importContext.getProgram().getId())).ifPresent(updatedObservations::add); } - return (List) updatedObservations; + return (List) brAPIObservationDAO.updateBrAPIObservation(mutatedObservationByDbId, importContext.getProgram().getId()); } /** diff --git a/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java b/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java index 5de4e7344..061260e93 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()) { + 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); From 2ef5d773da3019d30b4b13c73ea61e170d066b04 Mon Sep 17 00:00:00 2001 From: David Randolph Phillips Date: Wed, 17 Jul 2024 15:31:01 -0400 Subject: [PATCH 2/3] [BI-2093] cleand up code in merge --- .../org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java | 3 +-- src/main/java/org/breedinginsight/daos/cache/ProgramCache.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) 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 cf4272d37..e32dac6d9 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java +++ b/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java @@ -305,7 +305,6 @@ public List updateBrAPIObservation(Map updatedObservations = new ArrayList<>(); try { - Map updatedObservationsByDbId = new HashMap<>(); for (Map.Entry entry : mutatedObservationByDbId.entrySet()) { String dbId = entry.getKey(); BrAPIObservation observation = entry.getValue(); @@ -347,7 +346,7 @@ public List updateBrAPIObservation(Map postThese(UUID key, Map toBePosted) throws Exception { 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 + //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())); } From e9ce2c420b5b6e60dae14141797e9eff46dd2b26 Mon Sep 17 00:00:00 2001 From: David Randolph Phillips Date: Thu, 25 Jul 2024 13:27:49 -0400 Subject: [PATCH 3/3] [BI-2093] updated code per PR --- .../factory/entity/PendingObservation.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) 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 7247b927c..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 @@ -112,16 +112,12 @@ public List brapiPut(List members) throws ApiException, IllegalArgumen if (experimentUtilities.isInvalidMemberListForClass(members, BrAPIObservation.class)) { return new ArrayList(); } - - Map mutatedObservationByDbId = new HashMap<>(); - List updatedObservations = new ArrayList<>(); - for (U member : members) { - BrAPIObservation observation = (BrAPIObservation) member; - mutatedObservationByDbId.put(observation.getObservationDbId(), observation); -// Optional.ofNullable(brAPIObservationDAO.updateBrAPIObservation(observation.getObservationDbId(), observation, importContext.getProgram().getId())).ifPresent(updatedObservations::add); - } - + Map mutatedObservationByDbId = members.stream().collect(Collectors.toMap( + m -> ((BrAPIObservation) m).getObservationDbId(), + m -> ((BrAPIObservation) m) + )); return (List) brAPIObservationDAO.updateBrAPIObservation(mutatedObservationByDbId, importContext.getProgram().getId()); + } /**