Skip to content

Commit d0124fd

Browse files
committed
Refactored getCodeAssignmentGradingForStudent
1 parent 9cc16c8 commit d0124fd

1 file changed

Lines changed: 150 additions & 82 deletions

File tree

src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingService.java

Lines changed: 150 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,24 @@ private List<Grading> getCodeAssignmentGradingForAdmin(final AssignmentEntity as
189189

190190

191191
private List<Grading> getCodeAssignmentGradingForStudent(final AssignmentEntity assignment, final LoggedInUser currentUser) {
192-
final GradingEntity.PrimaryKey pk = new GradingEntity.PrimaryKey(assignment.getId(), currentUser.getId());
192+
GradingEntity gradingEntity = ensureGradingEntityExists(assignment.getId(), currentUser.getId());
193+
194+
findAndSetRepositoryLinkIfMissing(gradingEntity, assignment, currentUser);
195+
196+
if (hasRepositoryLink(gradingEntity)) {
197+
syncAndUpdateGrading(gradingEntity, assignment, currentUser);
198+
}
199+
200+
gradingEntity = gradingRepository.save(gradingEntity);
201+
return List.of(assignmentMapper.gradingEntityToDto(gradingEntity));
202+
}
203+
204+
/**
205+
* Ensures a grading entity exists for the given assignment and student.
206+
* Creates a new entity with metadata if it doesn't exist.
207+
*/
208+
private GradingEntity ensureGradingEntityExists(final UUID assignmentId, final UUID studentId) {
209+
final GradingEntity.PrimaryKey pk = new GradingEntity.PrimaryKey(assignmentId, studentId);
193210
GradingEntity gradingEntity = gradingRepository.findById(pk).orElse(null);
194211

195212
if (gradingEntity == null) {
@@ -205,97 +222,148 @@ private List<Grading> getCodeAssignmentGradingForStudent(final AssignmentEntity
205222
gradingEntity.setCodeAssignmentGradingMetadata(metadata);
206223
}
207224

208-
if (gradingEntity.getCodeAssignmentGradingMetadata() == null ||
209-
gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink() == null) {
210-
try {
211-
String assignmentName = contentServiceClient.queryContentsOfCourse(currentUser.getId(), assignment.getCourseId()).stream()
212-
.filter(assignmentDto -> assignmentDto.getId().equals(assignment.getId()))
213-
.findFirst()
214-
.orElseThrow(() -> new EntityNotFoundException("Assignment with externalId %s not found".formatted(assignment.getExternalId())))
215-
.getMetadata().getName();
216-
217-
String courseTitle = courseServiceClient.queryCourseById(assignment.getCourseId()).getTitle();
218-
// no isPresent check, since if we are here, the external course must exist
219-
String organizationName = externalCourseRepository.findById(courseTitle).get().getOrganizationName();
220-
221-
String repoLink = codeAssessmentProvider.findRepository(assignmentName, organizationName, currentUser);
222-
gradingEntity.getCodeAssignmentGradingMetadata().setRepoLink(repoLink);
223-
} catch (ExternalPlatformConnectionException | UserServiceConnectionException |
224-
ContentServiceConnectionException | CourseServiceConnectionException e) {
225-
log.error("Failed to find repository for assignment {} and student {}: {}", assignment.getId(), currentUser.getId(), e.toString());
226-
}
225+
return gradingEntity;
226+
}
227+
228+
/**
229+
* Checks if the grading entity has a repository link set.
230+
*/
231+
private boolean hasRepositoryLink(final GradingEntity gradingEntity) {
232+
return gradingEntity.getCodeAssignmentGradingMetadata() != null &&
233+
gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink() != null;
234+
}
235+
236+
/**
237+
* Finds and sets the repository link for the student if it's missing.
238+
*/
239+
private void findAndSetRepositoryLinkIfMissing(final GradingEntity gradingEntity,
240+
final AssignmentEntity assignment,
241+
final LoggedInUser currentUser) {
242+
if (hasRepositoryLink(gradingEntity)) {
243+
return;
227244
}
228245

229-
if (gradingEntity.getCodeAssignmentGradingMetadata() != null &&
230-
gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink() != null) {
231-
ExternalGrading externalGrading;
232-
try {
233-
externalGrading = codeAssessmentProvider.syncGradeForStudent(gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink(), currentUser);
234-
} catch (ExternalPlatformConnectionException | UserServiceConnectionException e) {
235-
log.error("Failed to sync student grade for assignment {} and student {}: {}", assignment.getId(), currentUser.getId(), e.toString());
236-
gradingEntity = gradingRepository.save(gradingEntity);
237-
return List.of(assignmentMapper.gradingEntityToDto(gradingEntity));
238-
}
246+
try {
247+
String assignmentName = contentServiceClient.queryContentsOfCourse(currentUser.getId(), assignment.getCourseId()).stream()
248+
.filter(assignmentDto -> assignmentDto.getId().equals(assignment.getId()))
249+
.findFirst()
250+
.orElseThrow(() -> new EntityNotFoundException("Assignment with externalId %s not found".formatted(assignment.getExternalId())))
251+
.getMetadata().getName();
239252

240-
if (externalGrading.achievedPoints() != null){
241-
gradingEntity.setAchievedCredits(externalGrading.achievedPoints());
242-
}
243-
gradingEntity.setDate(externalGrading.date());
253+
String courseTitle = courseServiceClient.queryCourseById(assignment.getCourseId()).getTitle();
254+
String organizationName = externalCourseRepository.findById(courseTitle).get().getOrganizationName();
244255

245-
CodeAssignmentGradingMetadataEntity metadata = gradingEntity.getCodeAssignmentGradingMetadata();
246-
metadata.setStatus(externalGrading.status());
247-
metadata.setFeedbackTableHtml(externalGrading.tableHtml());
256+
String repoLink = codeAssessmentProvider.findRepository(assignmentName, organizationName, currentUser);
257+
gradingEntity.getCodeAssignmentGradingMetadata().setRepoLink(repoLink);
258+
} catch (ExternalPlatformConnectionException | UserServiceConnectionException |
259+
ContentServiceConnectionException | CourseServiceConnectionException e) {
260+
log.error("Failed to find repository for assignment {} and student {}: {}",
261+
assignment.getId(), currentUser.getId(), e.toString());
262+
}
263+
}
248264

249-
if (assignment.getTotalCredits() == null || (externalGrading.totalPoints() != null && externalGrading.totalPoints() > assignment.getTotalCredits())) {
250-
assignment.setTotalCredits(externalGrading.totalPoints());
265+
/**
266+
* Syncs grading from external system, updates the grading entity, and handles code submission events.
267+
*/
268+
private void syncAndUpdateGrading(final GradingEntity gradingEntity,
269+
final AssignmentEntity assignment,
270+
final LoggedInUser currentUser) {
271+
ExternalGrading externalGrading;
272+
try {
273+
externalGrading = codeAssessmentProvider.syncGradeForStudent(
274+
gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink(), currentUser);
275+
} catch (ExternalPlatformConnectionException | UserServiceConnectionException e) {
276+
log.error("Failed to sync student grade for assignment {} and student {}: {}",
277+
assignment.getId(), currentUser.getId(), e.toString());
278+
return;
279+
}
280+
281+
updateGradingFromExternalGrading(gradingEntity, externalGrading, assignment);
282+
handleCodeSubmissionEvent(gradingEntity, externalGrading, assignment, currentUser);
283+
}
284+
285+
/**
286+
* Updates the grading entity with data from external grading.
287+
*/
288+
private void updateGradingFromExternalGrading(final GradingEntity gradingEntity,
289+
final ExternalGrading externalGrading,
290+
final AssignmentEntity assignment) {
291+
if (externalGrading.achievedPoints() != null) {
292+
gradingEntity.setAchievedCredits(externalGrading.achievedPoints());
293+
}
294+
gradingEntity.setDate(externalGrading.date());
295+
296+
CodeAssignmentGradingMetadataEntity metadata = gradingEntity.getCodeAssignmentGradingMetadata();
297+
metadata.setStatus(externalGrading.status());
298+
metadata.setFeedbackTableHtml(externalGrading.tableHtml());
299+
300+
if (assignment.getTotalCredits() == null ||
301+
(externalGrading.totalPoints() != null && externalGrading.totalPoints() > assignment.getTotalCredits())) {
302+
assignment.setTotalCredits(externalGrading.totalPoints());
303+
}
304+
}
305+
306+
/**
307+
* Handles code submission event publishing with commit-based deduplication.
308+
*/
309+
private void handleCodeSubmissionEvent(final GradingEntity gradingEntity,
310+
final ExternalGrading externalGrading,
311+
final AssignmentEntity assignment,
312+
final LoggedInUser currentUser) {
313+
CodeAssignmentGradingMetadataEntity metadata = gradingEntity.getCodeAssignmentGradingMetadata();
314+
String lastProcessedCommit = metadata.getLastProcessedCommitSha();
315+
String currentCommit = externalGrading.commitSha();
316+
317+
if (!shouldSendCodeSubmissionEvent(lastProcessedCommit, currentCommit, assignment.getId(), currentUser.getId())) {
318+
return;
319+
}
320+
321+
try {
322+
if (codeAssessmentProvider instanceof de.unistuttgart.iste.meitrex.assignment_service.service.code_assignment.GithubClassroom githubClassroom) {
323+
de.unistuttgart.iste.meitrex.assignment_service.service.code_assignment.StudentCodeSubmission codeSubmission =
324+
githubClassroom.fetchStudentCode(metadata.getRepoLink(), currentUser);
325+
326+
codeSubmission.setAssignmentId(assignment.getId());
327+
codeSubmission.setCourseId(assignment.getCourseId());
328+
329+
publishStudentCodeSubmittedEvent(codeSubmission);
330+
331+
metadata.setLastProcessedCommitSha(currentCommit != null ? currentCommit : "NO_COMMIT_SHA_PROCESSED");
251332
}
252-
253-
String lastProcessedCommit = metadata.getLastProcessedCommitSha();
254-
String currentCommit = externalGrading.commitSha();
255-
boolean shouldSendEvent = false;
256-
257-
if (currentCommit != null) {
258-
if (lastProcessedCommit == null || lastProcessedCommit.equals("NO_COMMIT_SHA_PROCESSED")) {
259-
shouldSendEvent = true;
260-
} else if (!currentCommit.equals(lastProcessedCommit)) {
261-
shouldSendEvent = true;
262-
} else {
263-
log.debug("Skipping code submission event. Commit {} already processed for student {} on assignment {}",
264-
currentCommit, currentUser.getId(), assignment.getId());
265-
}
333+
} catch (ExternalPlatformConnectionException | UserServiceConnectionException e) {
334+
log.error("Failed to fetch student code for assignment {} and student {}: {}",
335+
assignment.getId(), currentUser.getId(), e.toString());
336+
}
337+
}
338+
339+
/**
340+
* Determines whether a code submission event should be sent based on commit SHA comparison.
341+
*/
342+
private boolean shouldSendCodeSubmissionEvent(final String lastProcessedCommit,
343+
final String currentCommit,
344+
final UUID assignmentId,
345+
final UUID studentId) {
346+
if (currentCommit != null) {
347+
if (lastProcessedCommit == null || lastProcessedCommit.equals("NO_COMMIT_SHA_PROCESSED")) {
348+
return true;
349+
} else if (!currentCommit.equals(lastProcessedCommit)) {
350+
return true;
266351
} else {
267-
if (lastProcessedCommit == null || lastProcessedCommit.equals("NO_COMMIT_SHA_PROCESSED")) {
268-
shouldSendEvent = true;
269-
log.warn("No commit SHA available for assignment {} and student {}, sending event without commit tracking",
270-
assignment.getId(), currentUser.getId());
271-
} else {
272-
log.debug("No commit SHA and event already sent once for student {} on assignment {}, skipping",
273-
currentUser.getId(), assignment.getId());
274-
}
352+
log.debug("Skipping code submission event. Commit {} already processed for student {} on assignment {}",
353+
currentCommit, studentId, assignmentId);
354+
return false;
275355
}
276-
277-
if (shouldSendEvent) {
278-
try {
279-
if (codeAssessmentProvider instanceof de.unistuttgart.iste.meitrex.assignment_service.service.code_assignment.GithubClassroom githubClassroom) {
280-
de.unistuttgart.iste.meitrex.assignment_service.service.code_assignment.StudentCodeSubmission codeSubmission =
281-
githubClassroom.fetchStudentCode(gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink(), currentUser);
282-
283-
codeSubmission.setAssignmentId(assignment.getId());
284-
codeSubmission.setCourseId(assignment.getCourseId());
285-
286-
publishStudentCodeSubmittedEvent(codeSubmission);
287-
288-
metadata.setLastProcessedCommitSha(currentCommit != null ? currentCommit : "NO_COMMIT_SHA_PROCESSED");
289-
}
290-
} catch (ExternalPlatformConnectionException | UserServiceConnectionException e) {
291-
log.error("Failed to fetch student code for assignment {} and student {}: {}",
292-
assignment.getId(), currentUser.getId(), e.toString());
293-
}
356+
} else {
357+
if (lastProcessedCommit == null || lastProcessedCommit.equals("NO_COMMIT_SHA_PROCESSED")) {
358+
log.warn("No commit SHA available for assignment {} and student {}, sending event without commit tracking",
359+
assignmentId, studentId);
360+
return true;
361+
} else {
362+
log.debug("No commit SHA and event already sent once for student {} on assignment {}, skipping",
363+
studentId, assignmentId);
364+
return false;
294365
}
295366
}
296-
297-
gradingEntity = gradingRepository.save(gradingEntity);
298-
return List.of(assignmentMapper.gradingEntityToDto(gradingEntity));
299367
}
300368

301369
/**

0 commit comments

Comments
 (0)