Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development: Optimize local git repository cleanup #9322

Conversation

julian-christl
Copy link
Member

@julian-christl julian-christl commented Sep 16, 2024

Checklist

General

Server

Motivation and Context

The two deleted database calls were highly inefficient and took > 30 seconds on production.

I also modified the Gradle run configuration template as currently with every test execution npmInstall and other tasks get executed for no reason

Description

We actually only need the repository URI for deleting the local repository. Everything else is either irrelevant or only for logging purposes. Thus, I created one query searching both conditions (exercises and exams) at once and only returning the URI.
To have finer control, I reworked it as a paginated run. The batch size is up for debate.

Steps for Testing

Local Test only
Prerequisites:

  • Local Programming Setup
  • An exam with a programming exercise with the online editor activated
  • A course programming exercise with the online editor activated
  1. Participate in the exam exercise
  2. Participate in the course exercise
  3. Make sure that the repository working copies exist in your file system (most likely in the folder repos) (be careful if unrelated copies already exist. Don't get confused or delete them beforehand).
  4. Make sure the due date of your exercises has passed.
  5. Stop your server
  6. Go into the AutomaticProgrammingExerciseCleanupService.cleanupGitWorkingCopiesOnArtemisServer() and update the earliestDate to be before your exercise/exam due dates (i.e. earliestDate and latestDate should include the due dates).
  7. Setup up the artemis.scheduling.programming-exercises-cleanup-time to a reasonable schedule for you to test or modify the scheduled parameter of the cleanup() method so you don't have to wait.
  8. Start the server and wait for the cleanup to commence (watch the logs)
  9. The working copies from step 4 are expected to have been removed.

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.







Review Progress

Performance Review

  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Test Coverage

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Enhanced cleanup process for Git repositories associated with programming exercises, focusing on local working copies.
    • Introduced new methods for targeted retrieval of programming exercises with eager loading of participations.
  • Bug Fixes

    • Removed outdated query methods that were no longer necessary, streamlining data access.
  • Chores

    • Updated Gradle run configuration to exclude additional setup tasks, improving build efficiency.

@julian-christl julian-christl self-assigned this Sep 16, 2024
@github-actions github-actions bot added the server Pull requests that update Java code. (Added Automatically!) label Sep 16, 2024
@krusche krusche changed the title Development: Optimise Local Git Repository Cleanup Development: Optimize local git repository cleanup Sep 17, 2024
coderabbitai[bot]
coderabbitai bot previously approved these changes Sep 17, 2024
@julian-christl julian-christl marked this pull request as ready for review September 17, 2024 11:47
@julian-christl julian-christl requested a review from a team as a code owner September 17, 2024 11:47
Copy link

coderabbitai bot commented Sep 17, 2024

Walkthrough

The changes involve updates to a Gradle configuration file to expand the exclusion of tasks during execution, as well as modifications to Java repository and service classes. This includes the removal of specific query methods from the ProgrammingExerciseRepository, the addition of a new method, and a renaming of a method in the AutomaticProgrammingExerciseCleanupService to better reflect its focused operation. These alterations indicate a refinement in the handling of programming exercises and their associated data.

Changes

File Change Summary
.idea/runConfigurations/_template__of_Gradle.xml Updated scriptParameters to exclude multiple tasks: -x nodeSetup, -x npmSetup, -x npmInstall, and -x webapp.
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseRepository.java Removed methods: findAllWithStudentParticipationByRecentDueDate and findAllWithStudentParticipationByRecentExamEndDate; added method: findWithEagerTemplateAndSolutionParticipationsById.
src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java Renamed method from cleanupGitRepositoriesOnArtemisServer to cleanupGitWorkingCopiesOnArtemisServer, added cleanup logic.
src/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseTestService.java Updated test method to call cleanupGitWorkingCopiesOnArtemisServer instead of the old method.

Possibly related PRs

Suggested labels

ready to merge

Suggested reviewers

  • JohannesStoehr
  • pzdr7
  • coolchock
  • krusche
  • edkaya
  • Strohgelaender

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Outside diff range comments (2)
src/test/java/de/tum/cit/aet/artemis/exercise/programming/ProgrammingExerciseTestService.java (2)

Line range hint 2363-2363: Rename test method to reflect the updated method being tested

The test method automaticCleanupGitRepositories() now calls cleanupGitWorkingCopiesOnArtemisServer(). To maintain clarity and consistency, consider renaming the test method to automaticCleanupGitWorkingCopies() to accurately reflect the functionality being tested.

Apply this diff to rename the test method:

-void automaticCleanupGitRepositories() {
+void automaticCleanupGitWorkingCopies() {

Line range hint 2363-2387: Add assertions to verify the behavior of cleanupGitWorkingCopiesOnArtemisServer()

The test method currently lacks assertions to validate the behavior of cleanupGitWorkingCopiesOnArtemisServer(). Without assertions, the test may not effectively detect regressions or unintended side effects. Consider adding appropriate assertions or verifying interactions with mocked services to ensure the method functions as expected.

Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between c299fea and 006560e.

Files selected for processing (5)
  • .idea/runConfigurations/_template__of_Gradle.xml (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseRepository.java (0 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (4 hunks)
  • src/test/java/de/tum/cit/aet/artemis/exercise/programming/ProgrammingExerciseTestService.java (1 hunks)
Files not reviewed due to no reviewable changes (1)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseRepository.java
Additional context used
Path-based instructions (3)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/test/java/de/tum/cit/aet/artemis/exercise/programming/ProgrammingExerciseTestService.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

Additional comments not posted (3)
.idea/runConfigurations/_template__of_Gradle.xml (1)

7-7: Optimized Exclusions Enhance Test Run Efficiency

The addition of -x nodeSetup -x npmSetup -x npmInstall -x webapp to the scriptParameters effectively skips unnecessary tasks during test runs, leading to improved execution times. This aligns with the PR's objective to optimize the build process.

src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (2)

12-13: Imports added for pagination support

The addition of Page and Pageable imports is necessary for the new paginated query method.


169-181: Ensure efficient query execution with indexes

The query filters data based on pe.dueDate and pe.exerciseGroup.exam.endDate. To optimize performance for large datasets, verify that indexes exist on these date fields.

Run the following script to check for indexes on the relevant date columns:

Verification successful

Indexes are in place, but entity field definitions are unclear

The necessary indexes for optimizing the query performance are present in the database schema:

  • exam_end_date on the exam table
  • exercise_due_date on the exercise table

These indexes align with the fields used in the query (pe.dueDate and pe.exerciseGroup.exam.endDate), which should ensure efficient query execution for large datasets.

However, it's worth noting that the actual field definitions for dueDate in the Exercise class and endDate in the Exam class were not directly visible in our search. This could be due to inheritance, getter/setter methods, or alternative naming conventions. While this doesn't affect the query performance, it might be beneficial for code maintainability to review how these fields are defined and accessed in the entity classes.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if indexes exist on pe.dueDate and pe.exerciseGroup.exam.endDate fields.

# Expected: Index annotations on dueDate and endDate fields to improve query performance.

# Search for @Index annotations on the dueDate field in ProgrammingExercise entity
rg --type java "@Index.*dueDate" src/main/java/

# Search for @Index annotations on the endDate field in Exam entity
rg --type java "@Index.*endDate" src/main/java/

Length of output: 99


Script:

#!/bin/bash
# Description: Further investigation of index definitions

# Search for @Table annotations with indexes attribute
echo "Searching for @Table annotations with indexes:"
rg --type java "@Table\([^)]*indexes\s*=" src/main/java/

# Search for database migration scripts
echo "Searching for database migration scripts:"
fd -e sql -e xml -e yaml -e yml | grep -i "migration\|flyway\|liquibase"

# Search for custom index creation methods
echo "Searching for custom index creation methods:"
rg --type java "createIndex|addIndex" src/main/java/

# Broader search for potential entity classes
echo "Searching for potential entity classes:"
rg --type java "class (ProgrammingExercise|Exam)" src/main/java/

Length of output: 10526


Script:

#!/bin/bash
# Description: Search for index creations in Liquibase changelogs and locate entity classes

# Search for index creations on dueDate and endDate in Liquibase changelogs
echo "Searching for index creations in Liquibase changelogs:"
rg -i "createIndex.*(?:due_date|end_date)" src/main/resources/config/liquibase/

# Search for ProgrammingExercise and Exam entity classes
echo "Searching for ProgrammingExercise and Exam entity classes:"
rg --type java "@Entity.*class (ProgrammingExercise|Exam)" src/main/java/

# If entity classes are not found, search for classes extending a common base class or implementing an interface
echo "Searching for potential entity classes with inheritance:"
rg --type java "class (ProgrammingExercise|Exam).*extends.*" src/main/java/

Length of output: 4143


Script:

#!/bin/bash
# Description: Confirm field existence and index naming

# Check for dueDate field in Exercise class
echo "Searching for dueDate field in Exercise class:"
rg --type java "class Exercise.*\{[\s\S]*?dueDate.*?;" src/main/java/

# Check for endDate field in Exam class
echo "Searching for endDate field in Exam class:"
rg --type java "class Exam.*\{[\s\S]*?endDate.*?;" src/main/java/

# Double-check index names in Liquibase changelogs
echo "Verifying index names in Liquibase changelogs:"
rg -i "createIndex.*(?:exercise.*due_date|exam.*end_date)" src/main/resources/config/liquibase/

Length of output: 1193

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 006560e and 490483b.

Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (4 hunks)
Additional context used
Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

Additional comments not posted (3)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (3)

12-13: Imports added are appropriate

The addition of Page and Pageable imports is necessary to support pagination in the new repository method.


169-181: Previous review comments are still applicable

The issues highlighted in the previous review comments regarding potential NullPointerException when accessing pe.exerciseGroup.exam.endDate and the confusion with parameter names earliestDate and latestDate are still present in this code segment.


169-181: Method implementation aligns with objectives

The new method findRepositoryUrisForGitCleanupByRecentDueDateOrRecentExamEndDate effectively retrieves repository URIs based on recent due dates or exam end dates, which should optimize the cleanup process as intended.

coderabbitai[bot]
coderabbitai bot previously approved these changes Sep 17, 2024
Strohgelaender
Strohgelaender previously approved these changes Sep 17, 2024
Copy link
Contributor

@Strohgelaender Strohgelaender left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code makes sense

JohannesStoehr
JohannesStoehr previously approved these changes Sep 18, 2024
Copy link
Contributor

@JohannesStoehr JohannesStoehr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code

Copy link
Contributor

@magaupp magaupp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally with an non-exam exercise with an due date 4 months in the past and multiple participants. The query always returned 0 urls: Found 0 student participations...

coderabbitai[bot]
coderabbitai bot previously approved these changes Sep 19, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between cc90456 and b59a154.

📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🔇 Additional comments (8)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (2)

12-13: Remove unnecessary imports

The imports org.springframework.data.domain.Page and org.springframework.data.domain.Pageable are not necessary unless pagination is used in the code. Please ensure these imports are required; otherwise, consider removing them to keep the code clean.

Run the following script to check if Page and Pageable are used elsewhere in this file:


12-13: Ensure compliance with coding guidelines

Please verify that the changes adhere to the provided coding guidelines, specifically:

  • naming:CamelCase: Method and variable names should use CamelCase.
  • practices:avoid_transactions: Avoid unnecessary transactions in repository methods.
  • java:avoid_star_imports: Ensure imports are explicit and avoid using wildcard imports.

Run the following script to check for wildcard imports:

Also applies to: 167-181

✅ Verification successful

No Wildcard Imports Found

No wildcard imports are present in the repository, ensuring compliance with the java:avoid_star_imports guideline.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that no wildcard imports are used.
# Test: Search for wildcard imports in Java files.
grep -rn 'import .*.\*;' src/main/java/

Length of output: 41


Script:

#!/bin/bash
# Description: Accurately verify that no wildcard imports are used.
# Test: Search for wildcard imports in Java files with a refined grep pattern.
grep -rn '^import\s\+[^;]*\.\*;' src/main/java/

Length of output: 49

src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (6)

6-6: Import statement is necessary and correct

The import of java.net.URISyntaxException is required for proper exception handling in the deleteLocalRepositoryByUriString method.


20-21: Pagination imports are appropriate

The imports of Page and Pageable from org.springframework.data.domain are correctly added for handling pagination in repository queries.


31-31: Import of VcsRepositoryUri is valid

Including VcsRepositoryUri is essential for constructing repository URIs when deleting local repositories.


91-91: Initiate cleanup of Git working copies

The invocation of cleanupGitWorkingCopiesOnArtemisServer() correctly starts the cleanup process for local Git repositories.


94-94: Proper exception logging

The added log statement ensures that any exceptions occurring during cleanupGitWorkingCopiesOnArtemisServer() are logged with the stack trace, aiding in debugging.


129-145: Logic in cleanStudentParticipationsRepositories is sound

The method efficiently retrieves and processes repository URIs in batches to delete local student repositories. The pagination logic and loop structure are correctly implemented.

julian-christl and others added 3 commits October 3, 2024 00:21
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between b59a154 and 829b8c2.

📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

📓 Learnings (1)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (1)
Learnt from: julian-christl
PR: ls1intum/Artemis#9322
File: src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java:0-0
Timestamp: 2024-09-17T12:06:23.646Z
Learning: In Artemis, an `ExerciseGroup` always has an associated `Exam`, so `exerciseGroup.exam` is never null.
🔇 Additional comments (2)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (2)

12-13: LGTM: Appropriate imports added

The new imports for Page and Pageable from org.springframework.data.domain are correctly added to support the new paginated query method.


167-180: 🛠️ Refactor suggestion

Consider optimizing the query and improving naming

  1. Method name:
    The current method name is quite long. Consider a more concise name that still captures the essence of the operation.

  2. Date range comparison:
    The date range comparisons can be simplified using the BETWEEN keyword for better readability.

  3. Parameter naming:
    The parameter names 'earliestDate' and 'latestDate' might be confusing as they are used in reverse order in the conditions. Consider using 'startDate' and 'endDate' for clarity.

  4. JOIN operations:
    Verify if LEFT JOINs are necessary for pe.exerciseGroup and eg.exam. If these relationships are always present, using INNER JOINs might improve performance.

Here's a suggested refactoring:

-    @Query("""
-            SELECT participation.repositoryUri
-            FROM ProgrammingExerciseStudentParticipation participation
-                JOIN TREAT (participation.exercise AS ProgrammingExercise) pe
-                LEFT JOIN pe.exerciseGroup eg
-                LEFT JOIN eg.exam exam
-            WHERE participation.repositoryUri IS NOT NULL
-                AND (
-                    (pe.dueDate IS NOT NULL AND pe.dueDate BETWEEN :earliestDate AND :latestDate)
-                    OR (eg IS NOT NULL AND exam IS NOT NULL AND exam.endDate BETWEEN :earliestDate AND :latestDate)
-                )
-            """)
-    Page<String> findRepositoryUrisByRecentDueDateOrRecentExamEndDate(@Param("earliestDate") ZonedDateTime earliestDate, @Param("latestDate") ZonedDateTime latestDate,
-            Pageable pageable);
+    @Query("""
+            SELECT participation.repositoryUri
+            FROM ProgrammingExerciseStudentParticipation participation
+                JOIN TREAT (participation.exercise AS ProgrammingExercise) pe
+                LEFT JOIN pe.exerciseGroup eg
+                LEFT JOIN eg.exam exam
+            WHERE participation.repositoryUri IS NOT NULL
+                AND (
+                    (pe.dueDate IS NOT NULL AND pe.dueDate BETWEEN :startDate AND :endDate)
+                    OR (eg IS NOT NULL AND exam IS NOT NULL AND exam.endDate BETWEEN :startDate AND :endDate)
+                )
+            """)
+    Page<String> findRepositoryUrisByDateRange(@Param("startDate") ZonedDateTime startDate, @Param("endDate") ZonedDateTime endDate,
+            Pageable pageable);

To verify if LEFT JOINs are necessary, we can check if there are exercises without exercise groups or exams:

If this query returns results, it confirms that LEFT JOINs are necessary.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between b59a154 and 0606817.

📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🔇 Additional comments (3)
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java (3)

175-176: Good use of BETWEEN for date range checks

The use of the BETWEEN operator for date range checks is a good practice. It's clear, concise, and generally performs well. Keep this approach for date range filtering.


179-180: Effective use of pagination for large result sets

The method returns a Page<String>, which is an excellent choice for handling potentially large result sets. This approach allows for efficient memory usage and improved performance when dealing with a large number of repository URIs.


170-172: 🛠️ Refactor suggestion

Consider optimizing joins if exerciseGroup and exam are always present

The query uses LEFT JOINs for pe.exerciseGroup and eg.exam. If you're certain that these relationships always exist for valid records, consider using INNER JOINs instead. This could potentially improve query performance.

However, if there's a possibility that these relationships might not always exist, the current LEFT JOINs are appropriate.

To verify if INNER JOINs can be safely used, we can check if there are any programming exercises without exercise groups or exams:

If these patterns are always present, consider updating the query to use INNER JOINs:

-JOIN TREAT (participation.exercise AS ProgrammingExercise) pe
-LEFT JOIN pe.exerciseGroup eg
-LEFT JOIN eg.exam exam
+JOIN TREAT (participation.exercise AS ProgrammingExercise) pe
+JOIN pe.exerciseGroup eg
+JOIN eg.exam exam
✅ Verification successful

LEFT JOINs are appropriate for the current data model

Based on the analysis of the codebase, the current use of LEFT JOINs in the query is appropriate and should be maintained. Here's why:

  1. The relationships between ProgrammingExercise, ExerciseGroup, and Exam are indirect and hierarchical.
  2. Not all ProgrammingExercises are guaranteed to be part of an ExerciseGroup or Exam.
  3. The codebase shows examples of accessing ExerciseGroup and Exam through ProgrammingExercise, but these relationships may not always exist.

For example, in ExamDateService.java, we see:

return getExamProgrammingExerciseUnlockDate(exercise.getExerciseGroup().getExam());

This suggests that a ProgrammingExercise can be associated with an ExerciseGroup, which in turn can be associated with an Exam. However, these associations are not mandatory for all ProgrammingExercises.

Therefore, using LEFT JOINs ensures that all ProgrammingExercises are included in the query results, even if they don't have associated ExerciseGroups or Exams. Changing to INNER JOINs could potentially exclude valid ProgrammingExercises from the query results.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for programming exercises without exercise groups or exams
ast-grep --lang java --pattern 'class ProgrammingExercise {
  $$$
  ExerciseGroup exerciseGroup;
  $$$
}'

ast-grep --lang java --pattern 'class ExerciseGroup {
  $$$
  Exam exam;
  $$$
}'

Length of output: 439


Script:

#!/bin/bash
# Check for ProgrammingExercise classes without ExerciseGroup, excluding problematic file
fd --type f --extension java --exclude 'src/test/resources/test-data/repository-export/EncodingISO_8559_1.java' | \
xargs -I {} ast-grep --lang java --pattern 'class ProgrammingExercise {
  $$$
  ExerciseGroup exerciseGroup;
  $$$
}'

# Check for ExerciseGroup classes without Exam, excluding problematic file
fd --type f --extension java --exclude 'src/test/resources/test-data/repository-export/EncodingISO_8559_1.java' | \
xargs -I {} ast-grep --lang java --pattern 'class ExerciseGroup {
  $$$
  Exam exam;
  $$$
}'

Length of output: 279729


Script:

#!/bin/bash
# Search for ProgrammingExercise class definition
echo "Searching for ProgrammingExercise class:"
rg "class ProgrammingExercise" --type java --glob '!**/EncodingISO_8559_1.java'

# Search for ExerciseGroup within ProgrammingExercise
echo "\nSearching for ExerciseGroup within ProgrammingExercise:"
rg "class ProgrammingExercise.*?ExerciseGroup" --type java --glob '!**/EncodingISO_8559_1.java' -U

# Search for Exam within ExerciseGroup
echo "\nSearching for Exam within ExerciseGroup:"
rg "class ExerciseGroup.*?Exam" --type java --glob '!**/EncodingISO_8559_1.java' -U

Length of output: 10895


Script:

#!/bin/bash
# Examine ProgrammingExercise class
echo "Examining ProgrammingExercise class:"
rg "class ProgrammingExercise.*?ExerciseGroup|class ProgrammingExercise.*?Exam" src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExercise.java -U

# Check Exercise class
echo "\nChecking Exercise class:"
rg "class Exercise.*?ExerciseGroup|class Exercise.*?Exam" --type java -U

# Search for usage of ProgrammingExercise, ExerciseGroup, and Exam together
echo "\nSearching for usage of ProgrammingExercise, ExerciseGroup, and Exam together:"
rg "ProgrammingExercise.*?ExerciseGroup.*?Exam" --type java -U

Length of output: 1245

Copy link
Contributor

@magaupp magaupp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-tested

Copy link
Contributor

@dmytropolityka dmytropolityka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also tested locally, works with course and exam exercises

Copy link
Contributor

@JohannesStoehr JohannesStoehr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reapprove after merge

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range comments (1)
src/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseTestService.java (1)

Line range hint 2359-2387: Avoid direct database access in test method

According to the coding guidelines (avoid_db_access: true), tests should not directly access the database. In the automaticCleanupGitRepositories test method, several repository methods are called, such as programmingExerciseRepository.save(exercise);. Please refactor the test to use static mocks and fixed data instead.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 0606817 and 193ba86.

📒 Files selected for processing (3)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseRepository.java (0 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (5 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseTestService.java (1 hunks)
💤 Files with no reviewable changes (1)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseRepository.java
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseTestService.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

🔇 Additional comments (4)
src/main/java/de/tum/cit/aet/artemis/programming/service/AutomaticProgrammingExerciseCleanupService.java (4)

101-127: Refactored method improves clarity and maintainability

The cleanupGitWorkingCopiesOnArtemisServer method has been refactored to delegate specific cleanup tasks to helper methods. This enhances readability and adheres to the single responsibility principle.


105-107: 🧹 Nitpick (assertive)

Variable names might be confusing

The variables latestDate and earliestDate might cause confusion because earliestDate is actually older than latestDate. For better readability, consider renaming them to startDate and endDate.


146-152: ⚠️ Potential issue

Catch broader exceptions during repository deletion

Currently, only URISyntaxException is caught in the deleteLocalRepositoryByUriString method. If gitService.deleteLocalRepository(vcsRepositoryUrl) can throw other exceptions (e.g., GitAPIException, IOException), it's advisable to catch these to prevent the cleanup process from failing.

Modify the catch block to handle general exceptions:

} catch (URISyntaxException e) {
    log.error("Cannot create URI for repositoryUri: {}", uri, e);
+} catch (Exception e) {
+    log.error("Failed to delete local repository for URI: {}", uri, e);
}

Likely invalid or redundant comment.


51-52: 🛠️ Refactor suggestion

Consider making 'STUDENT_PARTICIPATION_CLEANUP_BATCH_SIZE' configurable

To enhance flexibility, consider externalizing the STUDENT_PARTICIPATION_CLEANUP_BATCH_SIZE to application properties. This allows for easier adjustments without code changes.

Apply this diff to make the batch size configurable:

-private static final int STUDENT_PARTICIPATION_CLEANUP_BATCH_SIZE = 500;
+@Value("${artemis.cleanup.student-participation-batch-size:500}")
+private int studentParticipationCleanupBatchSize;

And update the usage:

-Pageable pageable = Pageable.ofSize(STUDENT_PARTICIPATION_CLEANUP_BATCH_SIZE);
+Pageable pageable = Pageable.ofSize(studentParticipationCleanupBatchSize);

Likely invalid or redundant comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chore performance programming Pull requests that affect the corresponding module ready to merge server Pull requests that update Java code. (Added Automatically!) small tests
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

6 participants