Skip to content

Commit 8ce7e2c

Browse files
author
molodkov yaroslav
authored
add diamon priority for 2.7.7 for fix vocabulary switching(https://gi… (#1552)
* add diamon priority for 2.7.7 for fix vocabulary switching(OHDSI/Atlas#2223) * add diamon priority for 2.7.7 add JDoc for for SourcePriorityService class * add migration for priority
1 parent f5db430 commit 8ce7e2c

File tree

6 files changed

+138
-19
lines changed

6 files changed

+138
-19
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package org.ohdsi.webapi.service;
2+
3+
import java.util.Arrays;
4+
import java.util.Collections;
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.Optional;
9+
import org.apache.commons.collections4.map.PassiveExpiringMap;
10+
import org.ohdsi.sql.SqlTranslate;
11+
import org.ohdsi.webapi.shiro.management.datasource.SourceAccessor;
12+
import org.ohdsi.webapi.source.Source;
13+
import org.ohdsi.webapi.source.SourceDaimon;
14+
import org.ohdsi.webapi.source.SourceRepository;
15+
import org.springframework.beans.factory.annotation.Autowired;
16+
import org.springframework.jdbc.CannotGetJdbcConnectionException;
17+
import org.springframework.jdbc.core.JdbcTemplate;
18+
import org.springframework.stereotype.Service;
19+
20+
/**
21+
* This code was extracted from the master branch to fix https://github.com/OHDSI/Atlas/issues/2223 issue.
22+
* There is no need to merge it into the master as the same functionality implemented there in another place.
23+
*/
24+
@Service
25+
public class SourcePriorityService extends AbstractDaoService {
26+
27+
@Autowired
28+
private SourceRepository sourceRepository;
29+
@Autowired
30+
private SourceAccessor sourceAccessor;
31+
32+
private Map<Source, Boolean> connectionAvailability = Collections.synchronizedMap(new PassiveExpiringMap<>(5000));
33+
34+
public Source getPrioritySourceForDaimon(SourceDaimon.DaimonType daimonType) {
35+
36+
List<Source> sourcesByDaimonPriority = sourceRepository.findAllSortedByDiamonPrioirty(daimonType);
37+
38+
for (Source source : sourcesByDaimonPriority) {
39+
if (!(sourceAccessor.hasAccess(source) && connectionAvailability.computeIfAbsent(source, this::checkConnectionSafe))) {
40+
continue;
41+
}
42+
return source;
43+
}
44+
45+
return null;
46+
}
47+
48+
public Map<SourceDaimon.DaimonType, Source> getPriorityDaimons() {
49+
50+
class SourceValidator {
51+
private Map<Integer, Boolean> checkedSources = new HashMap<>();
52+
53+
private boolean isSourceAvaialble(Source source) {
54+
55+
return checkedSources.computeIfAbsent(source.getSourceId(),
56+
v -> sourceAccessor.hasAccess(source) && connectionAvailability.computeIfAbsent(source, SourcePriorityService.this::checkConnectionSafe));
57+
}
58+
}
59+
60+
SourceValidator sourceValidator = new SourceValidator();
61+
Map<SourceDaimon.DaimonType, Source> priorityDaimons = new HashMap<>();
62+
Arrays.asList(SourceDaimon.DaimonType.values()).forEach(d -> {
63+
64+
List<Source> sources = sourceRepository.findAllSortedByDiamonPrioirty(d);
65+
Optional<Source> source = sources.stream().filter(sourceValidator::isSourceAvaialble)
66+
.findFirst();
67+
source.ifPresent(s -> priorityDaimons.put(d, s));
68+
});
69+
return priorityDaimons;
70+
}
71+
72+
private boolean checkConnectionSafe(Source source) {
73+
74+
try {
75+
checkConnection(source);
76+
return true;
77+
} catch (CannotGetJdbcConnectionException ex) {
78+
return false;
79+
}
80+
}
81+
82+
public void checkConnection(Source source) {
83+
84+
final JdbcTemplate jdbcTemplate = getSourceJdbcTemplate(source);
85+
jdbcTemplate.execute(SqlTranslate.translateSql("select 1;", source.getSourceDialect()).replaceAll(";$", ""));
86+
}
87+
88+
}

src/main/java/org/ohdsi/webapi/service/SourceService.java

+18-19
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.glassfish.jersey.media.multipart.FormDataParam;
1212
import org.jasypt.encryption.pbe.PBEStringEncryptor;
1313
import org.jasypt.properties.PropertyValueEncryptionUtils;
14-
import org.ohdsi.sql.SqlTranslate;
1514
import org.ohdsi.webapi.common.SourceMapKey;
1615
import org.ohdsi.webapi.shiro.management.Security;
1716
import org.ohdsi.webapi.shiro.management.datasource.SourceAccessor;
@@ -56,13 +55,16 @@ public class SourceService extends AbstractDaoService {
5655
private ApplicationEventPublisher publisher;
5756
@Autowired
5857
private VocabularyService vocabularyService;
58+
@Autowired
59+
private SourcePriorityService sourcePriorityService;
5960

6061
@Autowired
6162
private SourceAccessor sourceAccessor;
6263

6364
@Value("${datasource.ohdsi.schema}")
6465
private String schema;
6566

67+
6668
private boolean encryptorPasswordSet = false;
6769

6870
@PostConstruct
@@ -171,22 +173,7 @@ public Collection<SourceInfo> refreshSources() {
171173
@GET
172174
@Produces(MediaType.APPLICATION_JSON)
173175
public SourceInfo getPriorityVocabularySourceInfo() {
174-
int priority = 0;
175-
SourceInfo priorityVocabularySourceInfo = null;
176-
177-
for (Source source : sourceRepository.findAll()) {
178-
for (SourceDaimon daimon : source.getDaimons()) {
179-
if (daimon.getDaimonType() == SourceDaimon.DaimonType.Vocabulary && sourceAccessor.hasAccess(source)) {
180-
int daimonPriority = daimon.getPriority();
181-
if (daimonPriority >= priority) {
182-
priority = daimonPriority;
183-
priorityVocabularySourceInfo = new SourceInfo(source);
184-
}
185-
}
186-
}
187-
}
188-
189-
return priorityVocabularySourceInfo;
176+
return new SourceInfo(sourcePriorityService.getPrioritySourceForDaimon(SourceDaimon.DaimonType.Vocabulary));
190177
}
191178

192179
@Path("{key}")
@@ -341,12 +328,24 @@ public Response delete(@PathParam("sourceId") Integer sourceId) throws Exception
341328
public SourceInfo checkConnection(@PathParam("key") final String sourceKey) {
342329

343330
final Source source = sourceRepository.findBySourceKey(sourceKey);
344-
final JdbcTemplate jdbcTemplate = getSourceJdbcTemplate(source);
345-
jdbcTemplate.execute(SqlTranslate.translateSql("select 1;", source.getSourceDialect()).replaceAll(";$", ""));
331+
sourcePriorityService.checkConnection(source);
346332
return source.getSourceInfo();
347333
}
348334

349335

336+
@Path("daimon/priority")
337+
@GET
338+
@Produces(MediaType.APPLICATION_JSON)
339+
public Map<SourceDaimon.DaimonType, SourceInfo> getPriorityDaimons() {
340+
341+
return sourcePriorityService.getPriorityDaimons()
342+
.entrySet().stream()
343+
.collect(Collectors.toMap(
344+
Map.Entry::getKey,
345+
e -> new SourceInfo(e.getValue())
346+
));
347+
}
348+
350349
@Path("{sourceKey}/daimons/{daimonType}/set-priority")
351350
@POST
352351
@Produces(MediaType.APPLICATION_JSON)

src/main/java/org/ohdsi/webapi/source/SourceRepository.java

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.ohdsi.webapi.source;
1717

18+
import java.util.List;
19+
import org.springframework.data.jpa.repository.Query;
1820
import org.springframework.data.repository.CrudRepository;
1921

2022
/**
@@ -24,4 +26,7 @@
2426
public interface SourceRepository extends CrudRepository<Source, Integer> {
2527
Source findBySourceKey(String sourceKey);
2628
Source findBySourceId(int sourceId);
29+
@Query("SELECT s FROM Source s JOIN s.daimons sd WHERE sd.daimonType = ?1 ORDER BY sd.priority DESC")
30+
List<Source> findAllSortedByDiamonPrioirty(SourceDaimon.DaimonType daimonType);
31+
2732
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
INSERT INTO ${ohdsiSchema}.sec_permission(id, value, description) VALUES
2+
(${ohdsiSchema}.sec_permission_id_seq.nextval, 'source:daimon:priority:get', 'Get priority of Source Daimons');
3+
4+
INSERT INTO ${ohdsiSchema}.sec_role_permission(id, role_id, permission_id)
5+
SELECT ${ohdsiSchema}.sec_role_permission_sequence.nextval, sr.id, sp.id
6+
FROM ${ohdsiSchema}.sec_permission SP, ${ohdsiSchema}.sec_role sr
7+
WHERE sp.value IN (
8+
'source:daimon:priority:get'
9+
) AND sr.name IN ('Atlas users');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
INSERT INTO ${ohdsiSchema}.sec_permission(id, value, description) VALUES
2+
(nextval('${ohdsiSchema}.sec_permission_id_seq'), 'source:daimon:priority:get', 'Get priority of Source Daimons');
3+
4+
INSERT INTO ${ohdsiSchema}.sec_role_permission(id, role_id, permission_id)
5+
SELECT nextval('${ohdsiSchema}.sec_role_permission_sequence'), sr.id, sp.id
6+
FROM ${ohdsiSchema}.sec_permission SP, ${ohdsiSchema}.sec_role sr
7+
WHERE sp.value IN (
8+
'source:daimon:priority:get'
9+
) AND sr.name IN ('Atlas users');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
INSERT INTO ${ohdsiSchema}.sec_permission(id, value, description) VALUES
2+
(NEXT VALUE FOR ${ohdsiSchema}.sec_permission_id_seq, 'source:daimon:priority:get', 'Get priority of Source Daimons');
3+
4+
INSERT INTO ${ohdsiSchema}.sec_role_permission(id, role_id, permission_id)
5+
SELECT NEXT VALUE FOR ${ohdsiSchema}.sec_role_permission_sequence, sr.id, sp.id
6+
FROM ${ohdsiSchema}.sec_permission SP, ${ohdsiSchema}.sec_role sr
7+
WHERE sp.value IN (
8+
'source:daimon:priority:get'
9+
) AND sr.name IN ('Atlas users');

0 commit comments

Comments
 (0)