Skip to content

Commit fbcddeb

Browse files
committed
fix: pass auth context in parallel calls2
1 parent 9407da1 commit fbcddeb

File tree

2 files changed

+109
-95
lines changed

2 files changed

+109
-95
lines changed

src/main/java/fr/insee/sabianedata/ws/service/ExternalApiService.java

Lines changed: 107 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import lombok.extern.slf4j.Slf4j;
1313
import org.springframework.http.HttpStatus;
1414
import org.springframework.http.ResponseEntity;
15+
import org.springframework.security.core.context.SecurityContext;
16+
import org.springframework.security.core.context.SecurityContextHolder;
1517
import org.springframework.stereotype.Service;
1618
import org.springframework.web.client.RestClientException;
1719

@@ -27,116 +29,99 @@ public class ExternalApiService {
2729
private final QueenApiService queenApiService;
2830

2931
public MassiveCampaign postTrainingCourse(MassiveCampaign trainingCourse) {
32+
boolean pearlSuccess = postTrainingCourseToManagementApi(trainingCourse);
33+
boolean queenSuccess = postTrainingCourseToQuestionnaireApi(trainingCourse);
34+
return pearlSuccess && queenSuccess ? trainingCourse : null;
35+
}
3036

31-
boolean pearlCampaignSuccess = false;
32-
boolean pearlSurveyUnitSuccess = false;
33-
boolean assignmentSuccess = false;
34-
35-
log.info("Trying to post pearl campaign");
36-
try {
37-
pearlApiService.postCampaignToApi(trainingCourse.getPearlCampaign());
38-
pearlCampaignSuccess = true;
39-
} catch (Exception e) {
40-
log.error("Error during creation campaign : {}", trainingCourse.getId());
41-
log.error(e.getMessage());
42-
}
37+
private boolean postTrainingCourseToManagementApi(MassiveCampaign trainingCourse) {
38+
boolean pearlCampaignSuccess = runWithErrorLogging(
39+
() -> pearlApiService.postCampaignToApi(trainingCourse.getPearlCampaign()),
40+
String.format("Error during creation campaign : %s", trainingCourse.getId())
41+
);
4342

4443
List<PearlSurveyUnit> pearlSurveyUnitsToPost =
4544
trainingCourse.getSurveyUnits().stream().map(MassiveSurveyUnit::getPearlSurveyUnit).toList();
46-
log.info("Trying to post {} pearl surveyUnits", pearlSurveyUnitsToPost.size());
45+
boolean pearlSurveyUnitSuccess = runWithErrorLogging(
46+
() -> pearlApiService.postUesToApi(pearlSurveyUnitsToPost),
47+
"Error during creation of surveyUnits"
48+
);
4749

48-
try {
49-
pearlApiService.postUesToApi(pearlSurveyUnitsToPost);
50-
pearlSurveyUnitSuccess = true;
51-
} catch (Exception e) {
52-
log.error("Error during creation of surveyUnits");
53-
log.error(e.getMessage());
54-
}
55-
log.info("Trying to post {} assignments", trainingCourse.getAssignments().size());
56-
try {
57-
pearlApiService.postAssignmentsToApi(trainingCourse.getAssignments());
58-
assignmentSuccess = true;
59-
} catch (Exception e) {
60-
log.error("Error during creation of assignments");
61-
log.error(e.getMessage());
62-
}
63-
boolean pearlSuccess = pearlCampaignSuccess && pearlSurveyUnitSuccess && assignmentSuccess;
64-
String pearlMessage = String.format("Campaign : %b, SurveyUnits: %b, Assignments: %b",
65-
pearlCampaignSuccess, pearlSurveyUnitSuccess, assignmentSuccess);
66-
log.info(pearlMessage);
50+
boolean assignmentSuccess = runWithErrorLogging(
51+
() -> pearlApiService.postAssignmentsToApi(trainingCourse.getAssignments()),
52+
"Error during creation of assignments"
53+
);
54+
55+
log.info("Campaign: {}, SurveyUnits: {}, Assignments: {}", pearlCampaignSuccess, pearlSurveyUnitSuccess,
56+
assignmentSuccess);
57+
return pearlCampaignSuccess && pearlSurveyUnitSuccess && assignmentSuccess;
58+
59+
}
60+
61+
private boolean postTrainingCourseToQuestionnaireApi(MassiveCampaign trainingCourse) {
62+
// extract main thread context for parallel stream usage
63+
var securityContext = SecurityContextHolder.getContext();
6764

68-
// POST queen entities
69-
long nomenclaturesSuccess;
70-
long questionnairesSuccess;
71-
long queenSurveyUnitsSuccess;
72-
boolean queenCampaignSuccess = false;
7365

7466
log.info("Trying to post {} nomenclatures", trainingCourse.getQueenCampaign().getNomenclatures().size());
75-
nomenclaturesSuccess = trainingCourse.getQueenCampaign().getNomenclatures().stream().parallel().filter(n -> {
76-
try {
77-
queenApiService.postNomenclaturesToApi(n);
78-
return true;
79-
} catch (Exception e) {
80-
log.error("Error during creation of nomenclature : {}", n.getId());
81-
log.error(e.getMessage());
82-
return false;
83-
}
84-
}).count();
67+
long createdNomenclatures = trainingCourse.getQueenCampaign().getNomenclatures().parallelStream()
68+
.filter(n -> secureParallelCallWithContext(
69+
() -> queenApiService.postNomenclaturesToApi(n),
70+
n.getId(),
71+
"POST nomenclature-%s failed",
72+
securityContext
73+
))
74+
.count();
8575

8676
log.info("Trying to post {} questionnaires",
87-
trainingCourse.getQueenCampaign().getQuestionnaireModels().size());
88-
questionnairesSuccess =
89-
trainingCourse.getQueenCampaign().getQuestionnaireModels().stream().parallel().filter(q -> {
90-
try {
91-
queenApiService.postQuestionnaireModelToApi(q);
92-
return true;
93-
} catch (Exception e) {
94-
log.error("Error during creation of questionnaire : {}",
95-
q.getIdQuestionnaireModel());
96-
log.error(e.getMessage());
97-
return false;
98-
}
99-
}).count();
77+
trainingCourse.getQueenCampaign().getQuestionnaireModels().size());
78+
long createdQuestionnaires = trainingCourse.getQueenCampaign().getQuestionnaireModels().parallelStream()
79+
.filter(q -> secureParallelCallWithContext(
80+
() -> queenApiService.postQuestionnaireModelToApi(q),
81+
q.getIdQuestionnaireModel(),
82+
"POST questionnaire-%s failed",
83+
securityContext
84+
))
85+
.count();
86+
10087

10188
log.info("Trying to post campaign");
102-
try {
103-
queenApiService.postCampaignToApi(trainingCourse.getQueenCampaign());
104-
queenCampaignSuccess = true;
105-
} catch (Exception e) {
106-
log.error("Error during creation of campaignDto : {}", trainingCourse.getId());
107-
log.error(e.getMessage());
108-
}
89+
boolean queenCampaignSuccess = runWithErrorLogging(
90+
() -> queenApiService.postCampaignToApi(trainingCourse.getQueenCampaign()),
91+
String.format("Error during creation campaign : %s", trainingCourse.getId())
92+
);
93+
94+
10995
List<QueenSurveyUnit> queenSurveyUnitsToPost =
11096
trainingCourse.getSurveyUnits().stream().map(MassiveSurveyUnit::getQueenSurveyUnit).toList();
11197

11298
log.info("Trying to post {} queen survey-units", queenSurveyUnitsToPost.size());
113-
queenSurveyUnitsSuccess = queenSurveyUnitsToPost.stream().parallel().filter(su -> {
114-
try {
115-
queenApiService.postUeToApi(su, trainingCourse.getId());
116-
return true;
117-
} catch (Exception e) {
118-
log.error("Error during creation of surveyUnit : {}", su.getId());
119-
log.error(e.getMessage());
120-
return false;
121-
}
122-
}).count();
123-
124-
boolean queenSuccess =
125-
queenCampaignSuccess && nomenclaturesSuccess == trainingCourse.getQueenCampaign().getNomenclatures().size()
126-
&& questionnairesSuccess == trainingCourse.getQueenCampaign().getQuestionnaireModels().size()
127-
&& queenSurveyUnitsSuccess == queenSurveyUnitsToPost.size();
128-
String queenMessage = String.format(
129-
"Nomenclatures: %d/%d, Questionnaires: %d/%d, SurveyUnits: %d/%d, Campaign: %b",
130-
nomenclaturesSuccess, trainingCourse.getQueenCampaign().getNomenclatures().size(),
131-
questionnairesSuccess,
132-
trainingCourse.getQueenCampaign().getQuestionnaireModels().size(), queenSurveyUnitsSuccess,
133-
queenSurveyUnitsToPost.size(), queenCampaignSuccess);
134-
135-
log.info(queenMessage);
136-
137-
return pearlSuccess && queenSuccess ? trainingCourse : null;
99+
long createdQueenSurveyUnits = queenSurveyUnitsToPost.parallelStream()
100+
.filter(su -> secureParallelCallWithContext(
101+
() -> queenApiService.postUeToApi(su, trainingCourse.getId()),
102+
su.getId(),
103+
"POST surveyUnit-%s failed",
104+
securityContext
105+
))
106+
.count();
107+
108+
log.info("Nomenclatures: {}/{} , Questionnaires: {}/{} , SurveyUnits: {}/{} , Campaign: {}",
109+
createdNomenclatures,
110+
trainingCourse.getQueenCampaign().getNomenclatures().size(),
111+
createdQuestionnaires,
112+
trainingCourse.getQueenCampaign().getQuestionnaireModels().size(),
113+
createdQueenSurveyUnits,
114+
queenSurveyUnitsToPost.size(),
115+
queenCampaignSuccess
116+
);
117+
118+
119+
return queenCampaignSuccess && createdNomenclatures == trainingCourse.getQueenCampaign().getNomenclatures().size()
120+
&& createdQuestionnaires == trainingCourse.getQueenCampaign().getQuestionnaireModels().size()
121+
&& createdQueenSurveyUnits == queenSurveyUnitsToPost.size();
138122
}
139123

124+
140125
public boolean checkUsers(List<String> users) {
141126

142127
OrganisationUnitDto ou = pearlApiService.getUserOrganizationUnit();
@@ -169,7 +154,7 @@ public boolean checkUsers(List<String> users) {
169154

170155
}
171156

172-
public ResponseEntity<String> deleteCampaign( String id) {
157+
public ResponseEntity<String> deleteCampaign(String id) {
173158
List<Campaign> pearlCampaigns = pearlApiService.getCampaigns(true);
174159
if (pearlCampaigns.stream().noneMatch(camp -> camp.getId().equals(id))) {
175160
log.error("DELETE campaign with id {} resulting in 404 because it does not exists", id);
@@ -210,4 +195,33 @@ public boolean checkInterviewers(List<String> interviewers) {
210195

211196
}
212197

198+
private boolean secureParallelCallWithContext(
199+
Runnable action,
200+
String entityId,
201+
String errorFormat,
202+
SecurityContext context
203+
) {
204+
SecurityContextHolder.setContext(context);
205+
try {
206+
action.run();
207+
return true;
208+
} catch (Exception e) {
209+
String errorMessage = String.format(errorFormat, entityId);
210+
log.error(errorMessage, e);
211+
return false;
212+
}
213+
}
214+
215+
216+
private boolean runWithErrorLogging(Runnable action, String errorMessage) {
217+
try {
218+
action.run();
219+
return true;
220+
} catch (Exception e) {
221+
log.error(errorMessage);
222+
log.error(e.getMessage(), e);
223+
return false;
224+
}
225+
}
226+
213227
}

src/main/java/fr/insee/sabianedata/ws/service/PearlApiService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public ResponseEntity<String> postCampaignToApi(PearlCampaign pearlCampaign) {
3333
}
3434

3535
public ResponseEntity<String> postUesToApi(List<PearlSurveyUnit> surveyUnits) {
36-
log.info("Create SurveyUnits ");
36+
log.info("Create {} SurveyUnits ",surveyUnits.size());
3737
final String apiUri = applicationProperties.managementUrl().concat("/api/survey-units");
3838
return restTemplate.exchange(apiUri, HttpMethod.POST, new HttpEntity<>(surveyUnits),
3939
String.class);
@@ -56,7 +56,7 @@ public ResponseEntity<String> postUsersToApi(List<UserDto> users, String ouId) {
5656
}
5757

5858
public ResponseEntity<String> postAssignmentsToApi(List<Assignment> assignments) {
59-
log.info("Create assignments");
59+
log.info("Create {} assignments", assignments.size());
6060
final String apiUri = applicationProperties.managementUrl().concat("/api/survey-units/interviewers");
6161
return restTemplate.exchange(apiUri, HttpMethod.POST, new HttpEntity<>(assignments),
6262
String.class);

0 commit comments

Comments
 (0)