Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions src/main/java/org/breedinginsight/brapi/v2/dao/BrAPICachedDAO.java

This file was deleted.

87 changes: 15 additions & 72 deletions src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIStudyDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.google.gson.JsonObject;
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.brapi.client.v2.model.exceptions.ApiException;
import org.brapi.client.v2.model.queryParams.core.StudyQueryParams;
Expand All @@ -32,7 +31,6 @@
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.brapi.BrAPIEndpointProvider;
import org.breedinginsight.utilities.BrAPIDAOUtil;
Expand All @@ -42,16 +40,14 @@
import javax.inject.Singleton;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

@Slf4j
@Singleton
public class BrAPIStudyDAO extends BrAPICachedDAO<BrAPIStudy> {
public class BrAPIStudyDAO {
@Property(name = "brapi.server.reference-source")
private String referenceSource;
@Property(name = "micronaut.bi.api.run-scheduled-tasks")
private boolean runScheduledTasks;

@Property(name = "brapi.cache.fetch-page-size")
private int brapiMaxPageSize;

Expand All @@ -61,52 +57,15 @@ public class BrAPIStudyDAO extends BrAPICachedDAO<BrAPIStudy> {
private final BrAPIEndpointProvider brAPIEndpointProvider;

@Inject
public BrAPIStudyDAO(ProgramDAO programDAO, ImportDAO importDAO, BrAPIDAOUtil brAPIDAOUtil, BrAPIEndpointProvider brAPIEndpointProvider, ProgramCacheProvider programCacheProvider) {
public BrAPIStudyDAO(
ProgramDAO programDAO,
ImportDAO importDAO,
BrAPIDAOUtil brAPIDAOUtil,
BrAPIEndpointProvider brAPIEndpointProvider) {
this.programDAO = programDAO;
this.importDAO = importDAO;
this.brAPIDAOUtil = brAPIDAOUtil;
this.brAPIEndpointProvider = brAPIEndpointProvider;
this.programCache = programCacheProvider.getProgramCache(this::fetchProgramStudy, BrAPIStudy.class);
}

@Scheduled(initialDelay = "${startup.delay.study}")
public void setup() {
if(!runScheduledTasks) {
return;
}
// Populate study cache for all programs on startup
log.debug("populating study cache");
List<Program> programs = programDAO.getActive();
if(programs != null) {
programCache.populate(programs.stream().map(Program::getId).collect(Collectors.toList()));
}
}


/**
* Fetch formatted study for this program
* @param programId
* @return Map - Key = string representing study UUID, value = formatted BrAPIStudy
* @throws ApiException
*/
private Map<String, BrAPIStudy> fetchProgramStudy(UUID programId) throws ApiException {
StudiesApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), StudiesApi.class);
// Get the program key
List<Program> programs = programDAO.get(programId);
if (programs.size() != 1) {
throw new InternalServerException("Program was not found for given key");
}
Program program = programs.get(0);

// Set query params and make call
BrAPIStudySearchRequest studySearch = new BrAPIStudySearchRequest();
studySearch.externalReferenceIDs(List.of(programId.toString()));
studySearch.externalReferenceSources(List.of(Utilities.generateReferenceSource(referenceSource, ExternalReferenceSource.PROGRAMS)));
return processStudyForDisplay(brAPIDAOUtil.search(
api::searchStudiesPost,
api::searchStudiesSearchResultsDbIdGet,
studySearch
), program.getKey());
}

/**
Expand Down Expand Up @@ -201,39 +160,23 @@ public List<BrAPIStudy> getStudiesByExperimentIds(@NotNull Collection<UUID> expe

public List<BrAPIStudy> createBrAPIStudies(List<BrAPIStudy> brAPIStudyList, UUID programId, ImportUpload upload) throws ApiException {
StudiesApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), StudiesApi.class);
List<BrAPIStudy> createdStudies = new ArrayList<>();

try {
if (!brAPIStudyList.isEmpty()) {
Callable<Map<String, BrAPIStudy>> postCallback = () -> {
List<BrAPIStudy> postedStudies = brAPIDAOUtil
.post(brAPIStudyList, upload, api::studiesPost, importDAO::update);
return environmentById(postedStudies);
};
createdStudies.addAll(programCache.post(programId, postCallback));
//Create studies directly through BrAPI.
List<BrAPIStudy> postedStudies = brAPIDAOUtil.post(brAPIStudyList, upload, api::studiesPost, importDAO::update);

// Return the BrAPI response without updating Redis.
return postedStudies;
}

return createdStudies;
// Preserve the existing empty-input behavior.
return new ArrayList<>();
} catch (Exception e) {
throw new InternalServerException("Unknown error has occurred: " + e.getMessage(), e);
}
}

/**
* @return Map - Key = BI external reference ID, Value = BrAPIStudy
* */
private Map<String, BrAPIStudy> environmentById(List<BrAPIStudy> studies) {
Map<String, BrAPIStudy> environmentById = new HashMap<>();
for (BrAPIStudy environment: studies) {
BrAPIExternalReference xref = environment
.getExternalReferences()
.stream()
.filter(reference -> String.format("%s/%s", referenceSource, ExternalReferenceSource.STUDIES.getName()).equals(reference.getReferenceSource()))
.findFirst().orElseThrow(() -> new IllegalStateException("No BI external reference found"));
environmentById.put(xref.getReferenceID(), environment);
}
return environmentById;
}

public List<BrAPIStudy> getStudiesByStudyDbId(Collection<String> studyDbIds, Program program) throws ApiException {
if(studyDbIds.isEmpty()) {
return Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,8 +814,6 @@ public int deleteExperiment(Program program, UUID experimentId, boolean hard) th
for (BrAPIListSummary list : lists) {
listDAO.deleteBrAPIList(list.getListDbId(), program.getId(), hard);
}
// TODO: if performance is poor, implement more precise invalidation, possibly using hierarchical cache keys.
studyDAO.repopulateCache(program.getId());
}

// Successful or not, return the number of observations in this experiment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.brapi.v2.model.BrAPIExternalReference;
import org.brapi.v2.model.core.BrAPIStudy;
import org.brapi.v2.model.core.BrAPITrial;
import org.brapi.v2.model.germ.BrAPIGermplasm;
import org.breedinginsight.BrAPITest;
Expand Down Expand Up @@ -218,6 +219,8 @@ void setup() throws Exception {

envIds.clear();
brAPIStudyDAO.getStudies(program.getId())
.stream()
.sorted(Comparator.comparing(BrAPIStudy::getStudyName))
.forEach(study -> envIds.add(study.getStudyDbId()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.breedinginsight.brapi.v2.dao;

import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Function3;
import lombok.SneakyThrows;
Expand All @@ -26,11 +27,9 @@
import org.brapi.v2.model.core.BrAPIStudy;
import org.brapi.v2.model.core.request.BrAPIStudySearchRequest;
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.FetchFunction;
import org.breedinginsight.daos.cache.ProgramCache;
import org.breedinginsight.daos.cache.ProgramCacheProvider;
import org.breedinginsight.model.Program;
import org.breedinginsight.services.brapi.BrAPIEndpointProvider;
import org.breedinginsight.utilities.BrAPIDAOUtil;
Expand All @@ -56,7 +55,6 @@ public class BrAPIStudyDAOUnitTest {
private BrAPIStudyDAO studyDAO;
private ProgramDAO programDAO;
private BrAPIDAOUtil brAPIDAOUtil;
private ProgramCache<BrAPIStudy> programCache;
private Program program;
private UUID programId;
private UUID environmentId;
Expand All @@ -76,11 +74,7 @@ void setup() {

programDAO = mock(ProgramDAO.class);
brAPIDAOUtil = mock(BrAPIDAOUtil.class);
ProgramCacheProvider programCacheProvider = mock(ProgramCacheProvider.class);
programCache = mock(ProgramCache.class);

when(programCacheProvider.getProgramCache(any(FetchFunction.class), eq(BrAPIStudy.class)))
.thenReturn(programCache);
when(programDAO.get(programId)).thenReturn(List.of(program));
when(programDAO.getCoreClient(programId)).thenReturn(mock(BrAPIClient.class));
when(programDAO.getProgramBrAPI(program)).thenReturn(brapiProgram);
Expand All @@ -89,8 +83,7 @@ void setup() {
programDAO,
mock(ImportDAO.class),
brAPIDAOUtil,
new BrAPIEndpointProvider(),
programCacheProvider
new BrAPIEndpointProvider()
);

Field referenceSource = BrAPIStudyDAO.class.getDeclaredField("referenceSource");
Expand Down Expand Up @@ -119,7 +112,6 @@ void getStudiesUsesDirectBrAPIGetInsteadOfProgramCache() {
assertEquals("brapi-program-1", queryParamsCaptor.getValue().programDbId());
assertEquals(0, queryParamsCaptor.getValue().page());
assertEquals(1000, queryParamsCaptor.getValue().pageSize());
verify(programCache, never()).get(any(UUID.class));
}

@Test
Expand All @@ -143,8 +135,6 @@ void getStudiesByStudyDbIdUsesDirectBrAPISearch() {

assertEquals(List.of("brapi-program-1"), requestCaptor.getValue().getProgramDbIds());
assertEquals(List.of(studyDbId), requestCaptor.getValue().getStudyDbIds());

verify(programCache, never()).get(any(UUID.class));
}

@Test
Expand All @@ -158,6 +148,28 @@ void getStudyByDbIdReturnsEmptyWhenBrAPIDoesNotFindStudy() {
assertTrue(result.isEmpty());
}

@Test
@SneakyThrows
void createBrAPIStudiesReturnsDirectBrAPIPostResponse() {

BrAPIStudy requestedStudy = new BrAPIStudy().studyName("Env1 [TEST-1]");
List<BrAPIStudy> requestedStudies = List.of(requestedStudy);

BrAPIStudy createdStudy = new BrAPIStudy().studyDbId("study-db-id").studyName("Env1 [TEST-1]");
ImportUpload upload = mock(ImportUpload.class);

doReturn(List.of(createdStudy))
.when(brAPIDAOUtil)
.post(eq(requestedStudies),eq(upload),any(Function.class),any(Consumer.class));

List<BrAPIStudy> result = studyDAO.createBrAPIStudies(requestedStudies,programId,upload);

assertEquals(1, result.size());
assertEquals("study-db-id",result.get(0).getStudyDbId());

verify(brAPIDAOUtil).post(eq(requestedStudies),eq(upload),any(Function.class),any(Consumer.class));
}

private BrAPIStudy study(UUID environmentId, String studyName) {
BrAPIExternalReference studyReference = new BrAPIExternalReference()
.referenceSource(Utilities.generateReferenceSource(REFERENCE_SOURCE, ExternalReferenceSource.STUDIES))
Expand Down
Loading