From e9099eac905a1666ecd750082c5066d5410de4f2 Mon Sep 17 00:00:00 2001 From: Jason Loux Date: Tue, 7 Jul 2026 17:25:49 -0400 Subject: [PATCH 1/3] Remove rest of cache code from ObservationDAO --- .../brapi/v2/dao/BrAPIObservationDAO.java | 91 ++----------------- 1 file changed, 9 insertions(+), 82 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 639ed9826..48346e495 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java +++ b/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java @@ -69,7 +69,6 @@ public class BrAPIObservationDAO extends BrAPICachedDAO { private final BrAPIDAOUtil brAPIDAOUtil; private final BrAPIEndpointProvider brAPIEndpointProvider; private final String referenceSource; - private boolean runScheduledTasks; private final TraitService traitService; private final int brapiMaxPageSize; @@ -83,75 +82,17 @@ public BrAPIObservationDAO(ProgramDAO programDAO, @Property(name = "brapi.server.reference-source") String referenceSource, @Property(name = "micronaut.bi.api.run-scheduled-tasks") boolean runScheduledTasks, @Property(name = "brapi.cache.fetch-page-size") int brapiFetchPageSize, - ProgramCacheProvider programCacheProvider, TraitService traitService) { + TraitService traitService) { this.programDAO = programDAO; this.importDAO = importDAO; this.observationUnitDAO = observationUnitDAO; this.brAPIDAOUtil = brAPIDAOUtil; this.brAPIEndpointProvider = brAPIEndpointProvider; this.referenceSource = referenceSource; - this.runScheduledTasks = runScheduledTasks; this.traitService = traitService; - this.programCache = programCacheProvider.getProgramCache(this::fetchProgramObservations, BrAPIObservation.class); this.brapiMaxPageSize = brapiFetchPageSize; } - @Scheduled(initialDelay = "${startup.delay.observation}") - public void setup() { - if(!runScheduledTasks) { - return; - } - // Populate the observation cache for all programs on startup. - log.debug("populating observation cache"); - List programs = programDAO.getActive(); - if (programs != null) { - programCache.populate(programs.stream().map(Program::getId).collect(Collectors.toList())); - } - } - - /** - * Fetch formatted observations for this program. - */ - private Map fetchProgramObservations(UUID programId) throws ApiException { - ObservationsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ObservationsApi.class); - // Get the program. - List programs = programDAO.get(programId); - if (programs.size() != 1) { - throw new InternalServerException("Program was not found for given id"); - } - Program program = programs.get(0); - - // Set query params and make call. - BrAPIObservationSearchRequest observationSearch = new BrAPIObservationSearchRequest(); - observationSearch.externalReferenceIds(List.of(programId.toString())); - observationSearch.externalReferenceSources(List.of(Utilities.generateReferenceSource(referenceSource, ExternalReferenceSource.PROGRAMS))); - return processObservationsForCache(brAPIDAOUtil.search( - api::searchObservationsPost, - api::searchObservationsSearchResultsDbIdGet, - observationSearch - ), program.getKey()); - } - - /** - * Process a list of observations for insertion into the cache. - */ - private Map processObservationsForCache(List programObservations, String programKey) { - // Process programObservations in place (strip program key, etc.). - processObservations(programKey, programObservations); - // Build map. - Map programObservationsMap = new HashMap<>(); - log.trace("processing observationUnits for cache: " + programObservations); - for (BrAPIObservation observation: programObservations) { - BrAPIExternalReference xref = observation - .getExternalReferences() - .stream() - .filter(reference -> String.format("%s/%s", referenceSource, ExternalReferenceSource.OBSERVATIONS.getName()).equals(reference.getReferenceSource())) - .findFirst().orElseThrow(() -> new IllegalStateException("No BI external reference found")); - programObservationsMap.put(xref.getReferenceId(), observation); - } - return programObservationsMap; - } - /** * Process BrAPIObservations for use in DeltaBreed (e.g. strip program key). */ @@ -305,11 +246,9 @@ public List createBrAPIObservations(List brA var program = programDAO.fetchOneById(programId); try { if (!brAPIObservationList.isEmpty()) { - Callable> postFunction = () -> { List postResponse = brAPIDAOUtil.post(brAPIObservationList, upload, api::observationsPost, importDAO::update); - return processObservationsForCache(postResponse, program.getKey()); - }; - return programCache.post(programId, postFunction); + processObservations(program.getKey(), postResponse); + return postResponse; } return new ArrayList<>(); } catch (Exception e) { @@ -348,15 +287,13 @@ private List getBrAPIObservationsUsingBrAPIProgramId(Program p return result; } - // 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 { + // TODO: Instead of a for loop, utilize BrAPI Observations put to do all updates in one request. [BI-2969] for (Map.Entry entry : mutatedObservationByDbId.entrySet()) { String dbId = entry.getKey(); BrAPIObservation observation = entry.getValue(); @@ -364,23 +301,13 @@ public List updateBrAPIObservation(Map response = null; + BrAPIObservation updatedObservation; + try { - response = api.observationsObservationDbIdPut(dbId, observation); + updatedObservation = brAPIDAOUtil.put(dbId, observation, api::observationsObservationDbIdPut); } 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()) @@ -394,8 +321,8 @@ public List updateBrAPIObservation(Map processedObservations = processObservationsForCache(updatedObservations, program.getKey()); - return programCache.postThese(programId,processedObservations); + processObservations(program.getKey(), updatedObservations); + return updatedObservations; } catch (ApiException e) { log.error("Error updating observation: " + Utilities.generateApiExceptionLogMessage(e), e); throw e; From a5ef8262119459ae9a841a76b08baae7063b239e Mon Sep 17 00:00:00 2001 From: Jason Loux Date: Wed, 8 Jul 2026 12:52:14 -0400 Subject: [PATCH 2/3] Fix unit test failures --- .../org/breedinginsight/brapi/v2/services/BrAPITrialService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java index 8e0b4bae6..4d1544940 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java +++ b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java @@ -836,7 +836,6 @@ public int deleteExperiment(Program program, UUID experimentId, boolean hard) th } // TODO: if performance is poor, implement more precise invalidation, possibly using hierarchical cache keys. studyDAO.repopulateCache(program.getId()); - observationDAO.repopulateCache(program.getId()); observationUnitDAO.repopulateCache(program.getId()); } From 799712211200240f3a66315635b5b2139b6fa102 Mon Sep 17 00:00:00 2001 From: Jason Loux Date: Wed, 8 Jul 2026 13:31:12 -0400 Subject: [PATCH 3/3] Remove referenced to CachedDAO parent class, remove imports --- .../breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java | 6 +----- 1 file changed, 1 insertion(+), 5 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 fb026a984..dfd1fddc1 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java +++ b/src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIObservationDAO.java @@ -18,7 +18,6 @@ import io.micronaut.context.annotation.Property; import io.micronaut.http.server.exceptions.InternalServerException; -import io.micronaut.scheduling.annotation.Scheduled; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; @@ -33,12 +32,10 @@ import org.brapi.v2.model.pheno.BrAPIObservationUnit; import org.brapi.v2.model.pheno.request.BrAPIObservationSearchRequest; import org.brapi.v2.model.pheno.response.BrAPIObservationListResponse; -import org.brapi.v2.model.pheno.response.BrAPIObservationSingleResponse; import org.breedinginsight.brapps.importer.daos.ImportDAO; import org.breedinginsight.brapps.importer.model.ImportUpload; import org.breedinginsight.brapps.importer.services.ExternalReferenceSource; import org.breedinginsight.daos.ProgramDAO; -import org.breedinginsight.daos.cache.ProgramCacheProvider; import org.breedinginsight.model.Program; import org.breedinginsight.services.TraitService; import org.breedinginsight.services.brapi.BrAPIEndpointProvider; @@ -50,14 +47,13 @@ import javax.inject.Inject; import javax.inject.Singleton; import java.util.*; -import java.util.concurrent.Callable; import java.util.stream.Collectors; import static org.brapi.v2.model.BrAPIWSMIMEDataTypes.APPLICATION_JSON; @Singleton @Slf4j -public class BrAPIObservationDAO extends BrAPICachedDAO { +public class BrAPIObservationDAO { private ProgramDAO programDAO; private ImportDAO importDAO;