Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
36b6b0d
try to improve database performance
krusche Aug 10, 2025
dd9e7e1
additional performance improvements
krusche Aug 10, 2025
c218720
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 11, 2025
8cda8d9
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 12, 2025
a5d66cb
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 14, 2025
f683494
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 16, 2025
7ecb3ee
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 26, 2025
1b3e6d0
Merge branch 'develop' into chore/improve-management-stats-performance
tobias-lippert Aug 26, 2025
e46a314
cleanup and add logging
tobias-lippert Aug 26, 2025
037fdf6
speedup active students query
tobias-lippert Aug 26, 2025
0072bd8
fix bug assessments over 100%
tobias-lippert Sep 1, 2025
53efabc
add exercise id to result
tobias-lippert Sep 2, 2025
ec9675b
set exercise id for programming exercise results
tobias-lippert Sep 2, 2025
9ee9a88
add changelog to master.xml
tobias-lippert Sep 2, 2025
81e8529
adjust query to new table layout
tobias-lippert Sep 4, 2025
4940811
adapt query
tobias-lippert Sep 5, 2025
bac732d
Revert "speedup active students query"
tobias-lippert Sep 5, 2025
fc8ee50
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Sep 21, 2025
5a47625
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Oct 4, 2025
d4fd6b6
migration
tobias-lippert Oct 4, 2025
a89f982
adapt queries
tobias-lippert Oct 4, 2025
b697052
fix architecture tests
tobias-lippert Oct 5, 2025
8c7abfa
fix course tests
tobias-lippert Oct 5, 2025
4fb8942
switch to liquibase migration
tobias-lippert Oct 6, 2025
0bdaf62
try to fix migration
tobias-lippert Oct 6, 2025
43eddf0
fix db migration
tobias-lippert Oct 7, 2025
2670a00
add rollback
tobias-lippert Oct 7, 2025
3f9ce53
fix server style, guard against some empty clauses and introduce help…
tobias-lippert Oct 7, 2025
b56d1d7
fix server style again
tobias-lippert Oct 7, 2025
b36c0a8
down to 511 test failures
tobias-lippert Oct 8, 2025
ae3bf01
down to 57 test failures
tobias-lippert Oct 8, 2025
cc4f177
down to 45 test failures
tobias-lippert Oct 8, 2025
9a809ef
fix remaining tests
tobias-lippert Oct 8, 2025
a7a00de
rabbit
tobias-lippert Oct 8, 2025
cf1f2e5
code review
tobias-lippert Oct 10, 2025
612b115
fix javadoc
tobias-lippert Oct 10, 2025
8994631
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Oct 12, 2025
1736988
remove newline at the end of runconfig
tobias-lippert Oct 12, 2025
a31473d
fix indentation
tobias-lippert Oct 14, 2025
74f9984
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Oct 15, 2025
7ce07eb
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Oct 15, 2025
901c7e3
Merge branch 'develop' into chore/further-management-stats-improvement
krusche Oct 18, 2025
5be817f
Merge branch 'develop' into chore/further-management-stats-improvement
florian-glombik Oct 22, 2025
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
2 changes: 1 addition & 1 deletion .idea/runConfigurations/Artemis_BuildAgent__Prod_.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ public class Result extends DomainObject implements Comparable<Result> {
@JsonIgnore
private Instant lastModifiedDate;

@Column(name = "exercise_id")
@JsonIgnore
private Long exerciseId;

public ZonedDateTime getCompletionDate() {
return completionDate;
}
Expand Down Expand Up @@ -173,6 +177,14 @@ public Instant getLastModifiedDate() {
return lastModifiedDate;
}

public Long getExerciseId() {
return exerciseId;
}

public void setExerciseId(Long exerciseId) {
this.exerciseId = exerciseId;
}

/**
* Sets the score to the specified score rounded to 4 decimal places.
* If you are handling student results that potentially need rounding, use {@link Result#setScore(Double score, Course course)} instead!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,13 @@ public interface ComplaintRepository extends ArtemisJpaRepository<Complaint, Lon
""")
Optional<Complaint> findByIdWithEagerAssessor(@Param("complaintId") Long complaintId);

/**
* This magic method counts the number of complaints by complaint type associated to a course id
*
* @param courseId - the id of the course we want to filter by
* @param complaintType - type of complaint we want to filter by
* @return number of more feedback requests associated to course courseId
*/
long countByResult_Submission_Participation_Exercise_Course_IdAndComplaintType(Long courseId, ComplaintType complaintType);

/**
* This magic method counts the number of complaints by complaint type associated to an exam id
*
* @param examId - the id of the exam we want to filter by
* @param complaintType - type of complaint we want to filter by
* @return number of complaints associated to course examId
*/
long countByResult_Submission_Participation_Exercise_ExerciseGroup_Exam_IdAndComplaintType(Long examId, ComplaintType complaintType);
@Query("""
SELECT COUNT(c)
FROM Complaint c
WHERE c.result.exerciseId IN :exerciseIds
AND c.complaintType = :complaintType
""")
long countByExerciseIdsAndComplaintType(@Param("exerciseIds") Set<Long> exerciseIds, @Param("complaintType") ComplaintType complaintType);

@Query("""
SELECT c
Expand Down Expand Up @@ -142,7 +132,7 @@ SELECT COUNT(c)
@Query("""
SELECT COUNT(c)
FROM Complaint c
WHERE c.result.submission.participation.exercise.id = :exerciseId
WHERE c.result.exerciseId = :exerciseId
AND c.complaintType = :complaintType
""")
long countComplaintsByExerciseIdAndComplaintType(@Param("exerciseId") Long exerciseId, @Param("complaintType") ComplaintType complaintType);
Expand All @@ -156,13 +146,13 @@ SELECT COUNT(c)
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.assessment.dto.dashboard.ExerciseMapEntryDTO(
c.result.submission.participation.exercise.id,
c.result.exerciseId,
COUNT(DISTINCT c)
)
FROM Complaint c
WHERE c.result.submission.participation.exercise.id IN :exerciseIds
WHERE c.result.exerciseId IN :exerciseIds
AND c.complaintType = :complaintType
GROUP BY c.result.submission.participation.exercise.id
GROUP BY c.result.exerciseId
""")
List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintType(@Param("exerciseIds") Set<Long> exerciseIds, @Param("complaintType") ComplaintType complaintType);

Expand All @@ -175,14 +165,14 @@ SELECT COUNT(c)
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.assessment.dto.dashboard.ExerciseMapEntryDTO(
c.result.submission.participation.exercise.id,
c.result.exerciseId,
COUNT(DISTINCT c)
)
FROM Complaint c
WHERE c.result.submission.participation.exercise.id IN :exerciseIds
WHERE c.result.exerciseId IN :exerciseIds
AND c.complaintType = :complaintType
AND c.result.submission.participation.testRun = FALSE
GROUP BY c.result.submission.participation.exercise.id
GROUP BY c.result.exerciseId
""")
List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintTypeIgnoreTestRuns(@Param("exerciseIds") Set<Long> exerciseIds,
@Param("complaintType") ComplaintType complaintType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ public interface ComplaintResponseRepository extends ArtemisJpaRepository<Compla
/**
* This magic method counts the number of complaints responses by complaint type associated to a course id
*
* @param courseId - the id of the course we want to filter by
* @param complaintType - complaint type we want to filter by
* @return number of complaints response associated to course courseId
*/
long countByComplaint_Result_Submission_Participation_Exercise_Course_Id_AndComplaint_ComplaintType_AndSubmittedTimeIsNotNull(Long courseId, ComplaintType complaintType);

/**
* This magic method counts the number of complaints responses by complaint type associated to an exam id
*
* @param examId - the id of the exam we want to filter by
* @param complaintType - complaint type we want to filter by
* @return number of complaints response associated to exam examId
*/
long countByComplaint_Result_Submission_Participation_Exercise_ExerciseGroup_Exam_Id_AndComplaint_ComplaintType_AndSubmittedTimeIsNotNull(Long examId,
ComplaintType complaintType);

@Query("""
SELECT COUNT(DISTINCT cr)
FROM ComplaintResponse cr
JOIN cr.complaint c
JOIN c.result r
WHERE r.exerciseId IN :exerciseIds
AND cr.submittedTime IS NOT NULL
AND c.complaintType = :complaintType
""")
long countComplaintResponsesForExerciseIdsAndComplaintType(@Param("exerciseIds") Set<Long> exerciseIds, @Param("complaintType") ComplaintType complaintType);

/**
* This magic method counts the number of complaints responses by complaint type associated to an exercise id
Expand All @@ -55,7 +55,7 @@ long countByComplaint_Result_Submission_Participation_Exercise_ExerciseGroup_Exa
@Query("""
SELECT COUNT(DISTINCT cr)
FROM ComplaintResponse cr
WHERE cr.complaint.result.submission.participation.exercise.id = :exerciseId
WHERE cr.complaint.result.exerciseId = :exerciseId
AND cr.complaint.complaintType = :complaintType
AND cr.submittedTime IS NOT NULL
""")
Expand All @@ -70,15 +70,15 @@ SELECT COUNT(DISTINCT cr)
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.assessment.dto.dashboard.ExerciseMapEntryDTO(
cr.complaint.result.submission.participation.exercise.id,
cr.complaint.result.exerciseId,
COUNT(DISTINCT cr)
)
FROM ComplaintResponse cr
WHERE cr.complaint.result.submission.participation.exercise.id IN :exerciseIds
WHERE cr.complaint.result.exerciseId IN :exerciseIds
AND cr.submittedTime IS NOT NULL
AND cr.complaint.complaintType = :complaintType
AND cr.complaint.result.submission.participation.testRun = FALSE
GROUP BY cr.complaint.result.submission.participation.exercise.id
GROUP BY cr.complaint.result.exerciseId
""")
List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintComplaintTypeIgnoreTestRuns(@Param("exerciseIds") Set<Long> exerciseIds,
@Param("complaintType") ComplaintType complaintType);
Expand All @@ -92,14 +92,14 @@ List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintComplaintTypeI
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.assessment.dto.dashboard.ExerciseMapEntryDTO(
cr.complaint.result.submission.participation.exercise.id,
cr.complaint.result.exerciseId,
COUNT(DISTINCT cr)
)
FROM ComplaintResponse cr
WHERE cr.complaint.result.submission.participation.exercise.id IN :exerciseIds
WHERE cr.complaint.result.exerciseId IN :exerciseIds
AND cr.submittedTime IS NOT NULL
AND cr.complaint.complaintType = :complaintType
GROUP BY cr.complaint.result.submission.participation.exercise.id
GROUP BY cr.complaint.result.exerciseId
""")
List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintComplaintType(@Param("exerciseIds") Set<Long> exerciseIds,
@Param("complaintType") ComplaintType complaintType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@

import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Profile;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import de.tum.cit.aet.artemis.assessment.domain.AssessmentType;
import de.tum.cit.aet.artemis.assessment.domain.ExampleSubmission;
Expand Down Expand Up @@ -48,11 +52,12 @@
public interface ResultRepository extends ArtemisJpaRepository<Result, Long> {

@Query("""

SELECT r
FROM Result r
LEFT JOIN FETCH r.assessor
WHERE r.id = :resultId
""")
FROM Result r
LEFT JOIN FETCH r.assessor
WHERE r.id = :resultId
""")
Optional<Result> findByIdWithEagerAssessor(@Param("resultId") long resultId);

@EntityGraph(type = LOAD, attributePaths = "submission")
Expand Down Expand Up @@ -220,7 +225,7 @@ SELECT COUNT(r)
WHERE r.completionDate IS NOT NULL
AND r.assessor IS NOT NULL
AND p.testRun = FALSE
AND p.exercise.id IN :exerciseIds
AND r.exerciseId IN :exerciseIds
""")
long countAssessmentsForExerciseIdsIgnoreTestRuns(@Param("exerciseIds") Set<Long> exerciseIdsWithManualAssessment);

Expand Down Expand Up @@ -931,4 +936,37 @@ SELECT MAX(r2.id)
)
""")
Set<Result> findLatestResultsByParticipationIds(@Param("participationIds") Set<Long> participationIds);

@Transactional
@Modifying
@Query("""
UPDATE Result r
SET r.exerciseId = (
SELECT p.exercise.id
FROM Submission s
JOIN s.participation p
WHERE s.id = r.submission.id
)
WHERE r.exerciseId IS NULL
AND r.id IN :ids
""")
int backfillExerciseIdBatch(@Param("ids") List<Long> ids);

@Query("""
SELECT r.id
FROM Result r
WHERE r.exerciseId IS NULL
ORDER BY r.id
""")
Slice<Long> findResultIdsWithoutExerciseId(Pageable pageable);

@Query("""
SELECT r.id
FROM Result r
WHERE r.exerciseId IS NULL
AND r.id > :afterId
ORDER BY r.id
""")
List<Long> findNextIds(@Param("afterId") long afterId, Pageable pageable);

}
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ else if (participant instanceof Team) {
}
}

public long countComplaintsByCourseId(long courseId) {
return complaintRepository.countByResult_Submission_Participation_Exercise_Course_IdAndComplaintType(courseId, ComplaintType.COMPLAINT);
public long countComplaintsByExerciseIds(Set<Long> exerciseIds) {
return complaintRepository.countByExerciseIdsAndComplaintType(exerciseIds, ComplaintType.COMPLAINT);
}

public long countMoreFeedbackRequestsByCourseId(long courseId) {
return complaintRepository.countByResult_Submission_Participation_Exercise_Course_IdAndComplaintType(courseId, ComplaintType.MORE_FEEDBACK);
public long countMoreFeedbackRequestsByCourseId(Set<Long> exerciseIds) {
return complaintRepository.countByExerciseIdsAndComplaintType(exerciseIds, ComplaintType.MORE_FEEDBACK);
}

/**
Expand All @@ -188,9 +188,8 @@ public long countMoreFeedbackRequestsByCourseId(long courseId) {
* @param courseId the id of the course
* @return the number of responses
*/
public long countComplaintResponsesByCourseId(long courseId) {
return complaintResponseRepository.countByComplaint_Result_Submission_Participation_Exercise_Course_Id_AndComplaint_ComplaintType_AndSubmittedTimeIsNotNull(courseId,
ComplaintType.COMPLAINT);
public long countComplaintResponsesByExerciseIds(Set<Long> exerciseIds) {
return complaintResponseRepository.countComplaintResponsesForExerciseIdsAndComplaintType(exerciseIds, ComplaintType.COMPLAINT);
}

/**
Expand All @@ -199,9 +198,8 @@ public long countComplaintResponsesByCourseId(long courseId) {
* @param courseId the id of the course
* @return the number of responses
*/
public long countMoreFeedbackRequestResponsesByCourseId(long courseId) {
return complaintResponseRepository.countByComplaint_Result_Submission_Participation_Exercise_Course_Id_AndComplaint_ComplaintType_AndSubmittedTimeIsNotNull(courseId,
ComplaintType.MORE_FEEDBACK);
public long countMoreFeedbackRequestResponsesByExerciseIds(Set<Long> exerciseIds) {
return complaintResponseRepository.countComplaintResponsesForExerciseIdsAndComplaintType(exerciseIds, ComplaintType.MORE_FEEDBACK);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import de.tum.cit.aet.artemis.core.config.migration.entries.ResultExerciseIdMigrationEntry;

/**
* This component allows registering certain entries containing functionality that gets executed on application startup. The entries must extend {@link MigrationEntry}.
* It should definitely be executed on startup, so we make it non-lazy.
Expand All @@ -30,6 +32,7 @@ public class MigrationRegistry {
public MigrationRegistry(MigrationService migrationService) {
this.migrationService = migrationService;
// Here we define the order of the ChangeEntries
migrationEntryMap.put(1, ResultExerciseIdMigrationEntry.class);
}

/**
Expand Down
Loading
Loading