Skip to content

Commit

Permalink
😨 Implement search cache and more robust report retrieval.
Browse files Browse the repository at this point in the history
  • Loading branch information
psbrandt committed Mar 18, 2021
1 parent 82fafe5 commit 60c0742
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 21 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>edu.phema</groupId>
<artifactId>phema-elm-to-ohdsi</artifactId>
<version>0.4.4-SNAPSHOT</version>
<version>0.4.4</version>
<packaging>jar</packaging>

<name>phema-elm-to-ohdsi</name>
Expand Down
38 changes: 34 additions & 4 deletions src/main/java/edu/phema/elm_to_omop/api/CohortService.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;

/**
Expand Down Expand Up @@ -120,6 +121,7 @@ public CohortService(IValuesetService valuesetService, IOmopRepositoryService om
* @throws CohortServiceException
*/
public CohortDefinitionDTO createCohortDefinition(String cqlString, String statementName) throws CohortServiceException {
logger.info("Creating cohort definition");

try {
ElmToOmopTranslator translator = new ElmToOmopTranslator(valuesetService);
Expand Down Expand Up @@ -274,14 +276,40 @@ public InclusionRuleReport getCohortDefinitionReport(Integer id) throws CohortSe
try {
omopService.queueCohortGeneration(id);

// Retry while the cohort is generating
RetryPolicy retryPolicy = new RetryPolicy();
// FIXME: Just taking the first info object can't be correct
retryPolicy.handleResultIf(info -> ((List<CohortGenerationInfo>) info).get(0).getStatus() != GenerationStatus.COMPLETE);
retryPolicy.withBackoff(1, 30, ChronoUnit.SECONDS);
retryPolicy.handleResultIf(info -> {
Optional<CohortGenerationInfo> maybeGenInfo = ((List<CohortGenerationInfo>) info).stream().filter(cgi -> cgi.getId().getCohortDefinitionId().equals(id)).findFirst();

if (!maybeGenInfo.isPresent()) {
logger.info("Cohort generation is not running for: " + id);

return false;
}

CohortGenerationInfo genInfo = maybeGenInfo.get();

logger.info("Waiting for cohort generation to complete, got status: " + genInfo.getStatus());

return genInfo.getStatus() != GenerationStatus.COMPLETE;
});
retryPolicy.withBackoff(1, 30, ChronoUnit.SECONDS);
Failsafe.with(retryPolicy).get(() -> omopService.getCohortDefinitionInfo(id));

return omopService.getCohortDefinitionReport(id);
// Retry until we actually get an inclusionRules result back
// Seems like it takes a second for the result to be persisted in the database
retryPolicy.handleResultIf(inclReport -> {
int size = ((InclusionRuleReport) inclReport).inclusionRuleStats.size();

logger.info("Waiting until we get stats for inclusion rule. Currently have: " + size);

return size == 0;
});
Failsafe.with(retryPolicy).get(() -> omopService.getCohortDefinitionReport(id));

InclusionRuleReport report = omopService.getCohortDefinitionReport(id);

return report;
} catch (Throwable t) {
throw new CohortServiceException("Error getting cohort definition report", t);
}
Expand Down Expand Up @@ -316,6 +344,8 @@ public InclusionRuleReport getCohortDefinitionReport(String cqlString, String st
* @throws CohortServiceException
*/
public InclusionRuleReport getCohortDefinitionReport(Bundle bundle, String statementName) throws CohortServiceException {
logger.info("Creating cohort report");

try {
CohortDefinitionDTO cohortDefinition = createCohortDefinition(bundle, statementName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,20 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

/**
* This class uses the WebAPI to interact with with the OMOP repository.
*/
public class OmopRepositoryService implements IOmopRepositoryService {
private static ConcurrentHashMap<String, List<Concept>> searchCache;

static {
searchCache = new ConcurrentHashMap<>();
}

private Logger logger = Logger.getLogger(this.getClass().getName());

private String domain;
Expand Down Expand Up @@ -78,30 +86,38 @@ public Concept getConceptMetadata(String id) throws OmopRepositoryException {
* @throws OmopRepositoryException
*/
public List<Concept> vocabularySearch(String query, String vocabularyId) throws OmopRepositoryException {
logger.info("Searching for '" + query + "' in vocabular " + vocabularyId);
logger.info("Searching for '" + query + "' in vocabulary " + vocabularyId);

try {
ConceptSearch conceptSearch = new ConceptSearch();

conceptSearch.query = query;
conceptSearch.vocabularyId = new String[]{vocabularyId};
// First try cache
List<Concept> cachedResult = searchCache.get(query);

if (cachedResult != null) {
logger.info("Cache hit");

// Concept concept = new Concept();
// concept.conceptCode = query;
// concept.vocabularyId = vocabularyId;
// return new ArrayList<Concept>() {{
// add(concept);
// }};
return cachedResult;
} else {
logger.info("Cache miss");

Response response = client
.target(domain + "vocabulary/search")
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(conceptSearch, MediaType.APPLICATION_JSON));
ConceptSearch conceptSearch = new ConceptSearch();

return response.readEntity(new GenericType<List<Concept>>() {
});
conceptSearch.query = query;
conceptSearch.vocabularyId = new String[]{vocabularyId};

Response response = client
.target(domain + "vocabulary/search")
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(conceptSearch, MediaType.APPLICATION_JSON));

List<Concept> result = response.readEntity(new GenericType<List<Concept>>() {
});

// add to cache
searchCache.put(query, result);

return result;
}
} catch (Exception e) {
throw new OmopRepositoryException("Error performing vocabulary search", e);
}
Expand Down

0 comments on commit 60c0742

Please sign in to comment.