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

Integrated code lifecycle: Improve build status updates for users #9818

Open
wants to merge 48 commits into
base: develop
Choose a base branch
from

Conversation

BBesrour
Copy link
Member

@BBesrour BBesrour commented Nov 18, 2024

DEPLOY ONLY ON TS3!!

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I added pre-authorization annotations according to the guidelines and checked the course groups for all new REST Calls (security).
  • I documented the Java code using JavaDoc style.

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the principle of data economy for all client-server REST calls.
  • I strictly followed the client coding and design guidelines.
  • Following the theming guidelines, I specified colors only in the theming variable files and checked that the changes look consistent in both the light and the dark theme.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.
  • I added authorities to all new routes and checked the course groups for displaying navigation elements (links, buttons).
  • I documented the TypeScript code using JSDoc style.
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

Changes affecting Programming Exercises

  • High priority: I tested all changes and their related features with all corresponding user types on a test server configured with the integrated lifecycle setup (LocalVC and LocalCI).
  • I tested all changes and their related features with all corresponding user types on a test server configured with Gitlab and Jenkins.

Motivation and Context

We want to provide users with better status about their build jobs. This is done by differentiating (in the UI) when a build job is queued, and when it is being processed. And also providing an estimation for each stage

Description

Build queue duration estimation

The queue duration estimation calculates the waiting time for a build job in the queue before it starts processing. It considers the availability of build agents and the jobs already running or queued. The system tracks agent availability by calculating the remaining processing times of currently running jobs and uses this information to simulate job assignments. For the queued jobs, a simulation determines when each job will be assigned to the next available agent, updating agent availability based on job durations. If the number of queued jobs before the target job is fewer than the available agents, the target job can start immediately once an agent is free. Otherwise, the algorithm calculates the time at which the next agent becomes available to start the target job.

Server Client communication

Previously, the server sends the client a message via websockets when a new submission is available, this triggers the client to show building and testing UI. Now, it changes it to Queued. When the build starts processing, the server now sends another message with the build timing information (estimated completion date, and build start date), this will trigger the progress bar animation.

Steps for Testing

### On Non-LocalCI servers (TS5, TS6)

1. Make sure that pushing code (and the result component that show the status) behavior didnt change.

On LocalCI servers (TS1-4)

Prerequisites:

  • 1 instructor
  • Server with ICL
  1. Create a programming exercise (enable online and offline IDE)
  2. After creation, make sure that the status showing the template/solution build plans doesnt show a progress bar.
  3. Open Dev tools (needed for later). Usually you can open it by pressing F12
  4. As a student, submit from the code editor and make sure the that result component is intuitive and provides "accurate" information.
  5. Check network tab in dev tools and look for this request (/queue-duration-estimation). Make sure that it completed in less than 100ms
  6. As a student, submit from IDE (clone and push) and make sure that the result component (whether in the code editor or the course overview) is intuitive and provides "accurate" information.
  7. Submit again (either from code editor or IDE) and try to break things by reloading the page, go back and forth between pages etc
  8. Browse around artemis (especially intstructor views) and make sure the result component behaves as expected

Exam Mode Testing

Prerequisites:

  • 1 Student
  • 1 Exam with a Programming Exercise
  1. Submit programming exercise using offline/online IDE
  2. Make sure that the result component in the code editor intuitive and provides "accurate" information
  3. Make sure that the result component in the overview page is intuitive and provides "accurate" information

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 client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • 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

Exam Mode Test

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Screenshots

image

image

image

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced build job tracking with estimated completion dates and durations.
    • New SubmissionProcessingDTO class for managing submission processing details.
    • Added a progress bar in the UI for displaying build and queue statuses.
    • New endpoint for estimating build job queue duration.
    • Support for displaying progress bars in various components.
    • Introduction of the ProgrammingExerciseBuildStatistics class for tracking build statistics.
    • New input properties in components to manage progress bar visibility and timing information.
    • Improved submission status feedback in the UI with new localization entries.
    • New methods and properties in various components for managing and displaying build progress.
  • Bug Fixes

    • Improved error handling during build job processing.
  • Documentation

    • Updated localization files to include new keys for queued status and estimated time of arrival.
  • Style

    • New CSS classes for progress bar styling.
  • Tests

    • Expanded test coverage for build job timing and submission processing scenarios.
    • Added tests for handling submission state changes and timing information.
    • New tests for verifying the behavior of components with progress bars.

@BBesrour BBesrour self-assigned this Nov 18, 2024
@BBesrour BBesrour requested a review from a team as a code owner November 18, 2024 21:23
@github-actions github-actions bot added tests server Pull requests that update Java code. (Added Automatically!) client Pull requests that update TypeScript code. (Added Automatically!) database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. buildagent Pull requests that affect the corresponding module core Pull requests that affect the corresponding module exercise Pull requests that affect the corresponding module programming Pull requests that affect the corresponding module labels Nov 18, 2024
Copy link

coderabbitai bot commented Nov 18, 2024

Walkthrough

The pull request introduces significant enhancements to the handling of build job timing and processing across various components in the system. Key updates include modifications to the BuildJobQueueItem, JobTimingInfo, and SubmissionDTO structures to accommodate additional timing information such as estimated completion dates and durations. New methods and properties are added to services and components to manage and display this timing information effectively, including the introduction of a new ResultProgressBarComponent for visual feedback during the build process.

Changes

File Change Summary
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildJobQueueItem.java Updated constructors to include ZonedDateTime estimatedCompletionDate and long estimatedDuration in JobTimingInfo.
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/FinishedBuildJobDTO.java Modified ResultDTO.of(Result result) method to include additional parameters for SubmissionDTO.
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/JobTimingInfo.java Added fields ZonedDateTime estimatedCompletionDate and long estimatedDuration.
src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java Enhanced job timing handling, updated addToProcessingJobs, and modified error handling in checkAvailabilityAndProcessNextBuild.
src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java Added constants SUBMISSION_PROCESSING and SUBMISSION_PROCESSING_TOPIC.
src/main/java/de/tum/cit/aet/artemis/exercise/dto/SubmissionDTO.java Added boolean isProcessing and ZonedDateTime estimatedCompletionDate fields, updated of method.
src/main/java/de/tum/cit/aet/artemis/programming/dto/ResultDTO.java Updated of(Result result) method to include additional parameters for SubmissionDTO.
src/main/java/de/tum/cit/aet/artemis/programming/dto/SubmissionProcessingDTO.java New record class introduced to encapsulate submission processing details.
src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingMessagingService.java Added method for notifying about submission processing, updated existing methods for consistency.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIQueueWebsocketService.java Added dependency on ProgrammingMessagingService, new notification method for build processing.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java Introduced new private methods for updating exercise build duration.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCITriggerService.java Updated triggerBuild method to include new parameters and calculate estimated duration.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java Added methods for estimating queue duration and checking submission processing.
src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java Updated return type for getLatestPendingSubmission to SubmissionDTO.
src/main/webapp/app/entities/programming/programming-submission.model.ts Added optional properties for isProcessing, buildStartDate, and estimatedCompletionDate.
src/main/webapp/app/entities/programming/submission-processing-dto.ts New file defining SubmissionProcessingDTO with relevant properties.
src/main/webapp/app/exercises/shared/result/result-progress-bar/result-progress-bar.component.html Introduced a new HTML template for a progress bar component.
src/main/webapp/app/exercises/shared/result/result-progress-bar/result-progress-bar.component.ts New component for displaying build progress with reactive features.
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java Added tests for build job timing information and submission processing.
src/test/java/de/tum/cit/aet/artemis/programming/service/programming-submission.service.spec.ts Enhanced tests for submission state management and websocket interactions.

Possibly related PRs

Suggested labels

ready to merge, feature

Suggested reviewers

  • SimonEntholzer
  • JohannesStoehr
  • az108
  • coolchock

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 pmd (7.7.0)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java

The following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.


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: 30

🧹 Outside diff range and nitpick comments (45)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (1)

170-175: Clarify the need for both setExercise and setProgrammingExercise methods

In lines 173~ and 174~, both setExercise(exercise) and setProgrammingExercise(exercise) are called on programmingExerciseParticipation. Please verify if both methods are necessary and that they update different properties. If they serve the same purpose, consider using only one to eliminate redundancy and improve code clarity.

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java (2)

400-403: Rename method getBuildAgentsCapacity() to updateBuildAgentsCapacity() for clarity

The method getBuildAgentsCapacity() updates the buildAgentsCapacity and runningBuildJobCount fields, rather than simply retrieving values. Renaming it to updateBuildAgentsCapacity() would better reflect its purpose and improve code readability.

Apply this diff to rename the method and its usages:

-    private void getBuildAgentsCapacity() {
+    private void updateBuildAgentsCapacity() {
         buildAgentsCapacity = buildAgentInformation.values().stream()
                 .mapToInt(BuildAgentInformation::maxNumberOfConcurrentBuildJobs).sum();
         runningBuildJobCount = buildAgentInformation.values().stream()
                 .mapToInt(BuildAgentInformation::numberOfCurrentBuildJobs).sum();
     }

-    this.getBuildAgentsCapacity();
+    this.updateBuildAgentsCapacity();

378-398: Consider making BuildAgentListener a static nested class

The inner class BuildAgentListener does not access any instance members of the enclosing class. Making it a static nested class can improve clarity and reduce unnecessary references to the enclosing class.

Apply this diff:

-    private class BuildAgentListener
+    private static class BuildAgentListener
             implements EntryAddedListener<String, BuildAgentInformation>,
                        EntryRemovedListener<String, BuildAgentInformation>,
                        EntryUpdatedListener<String, BuildAgentInformation> {
src/main/webapp/app/exercises/programming/participate/programming-submission.service.ts (4)

Line range hint 713-745: Ensure correct handling of build timing information

When processing the pending submission, the code tries to access submission.estimatedCompletionDate and submission.buildStartDate, which might be undefined. Ensure that these properties are available or handle the undefined case to prevent errors.

Apply this diff to handle undefined properties:

let buildTimingInfo: BuildTimingInfo | undefined = {
    estimatedCompletionDate: submission.estimatedCompletionDate,
    buildStartDate: submission.buildStartDate,
};
-buildTimingInfo = buildTimingInfo ?? this.startedProcessingCache.get(submission.commitHash!);
+buildTimingInfo = buildTimingInfo || this.startedProcessingCache.get(submission.commitHash!);
this.removeSubmissionFromProcessingCache(submission.commitHash!);

Additionally, verify that submission.commitHash is defined before using it.


896-903: Consider access modifiers for new methods

The methods setLocalCIProfile and getIsLocalCIProfile can be marked as private or protected if they are not intended to be accessed from outside the service.

Apply this diff to adjust the access modifiers:

-public setLocalCIProfile(isLocalCIProfile: boolean) {
+private setLocalCIProfile(isLocalCIProfile: boolean) {
    this.isLocalCIProfile = isLocalCIProfile;
}

-public getIsLocalCIProfile() {
+private getIsLocalCIProfile() {
    return this.isLocalCIProfile;
}

73-74: Follow consistent formatting for comments

Ensure that there is a space after the comment delimiters for readability and consistency.

Apply this diff to adjust the comment formatting:

-//Default value: 30 seconds.
+// Default value: 30 seconds.

268-294: Handle potential race conditions in websocket message processing

When processing websocket messages, there could be a race condition if messages arrive out of order. Consider adding logic to handle such scenarios to ensure that the state remains consistent.

src/main/webapp/app/entities/programming/submission-processing-dto.ts (1)

3-9: Consider adding fields for comprehensive build status tracking.

Based on the PR objectives to improve build status updates, consider adding these fields:

  • status: BuildStatus - enum for states like 'QUEUED', 'PROCESSING', 'COMPLETED'
  • queuePosition?: number - position in the build queue
  • estimatedQueueDuration?: number - expected wait time in queue

This would provide more detailed status information to users.

src/main/webapp/app/exercises/shared/result/updating-result.component.html (1)

15-17: LGTM! Consider adding tooltips for timing information.

The new timing properties (estimatedCompletionDate, buildStartDate) and progress visualization (showProgressBar) effectively support the build queue duration estimation system. These additions will help users better understand build timelines.

Consider enhancing the user experience further by adding tooltips that explain the estimated completion time in a user-friendly format (e.g., "Expected to complete in ~5 minutes").

     [estimatedCompletionDate]="estimatedCompletionDate"
     [buildStartDate]="buildStartDate"
-    [showProgressBar]="showProgressBar"
+    [showProgressBar]="showProgressBar"
+    [matTooltip]="getEstimatedTimeTooltip()"
+    matTooltipPosition="above"
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/JobTimingInfo.java (2)

13-14: Document the unit of measurement for estimatedDuration

The estimatedDuration field is of type long but its unit of measurement (seconds, milliseconds, etc.) is not documented. This could lead to inconsistent usage across the codebase.

Add a Javadoc comment to specify the unit:

 @JsonIgnoreProperties(ignoreUnknown = true)
 @JsonInclude(JsonInclude.Include.NON_EMPTY)
+/**
+ * Record representing timing information for build jobs.
+ *
+ * @param submissionDate When the job was submitted
+ * @param buildStartDate When the build started processing
+ * @param buildCompletionDate When the build completed
+ * @param estimatedCompletionDate Expected completion time
+ * @param estimatedDuration Expected duration in milliseconds
+ */
 public record JobTimingInfo(ZonedDateTime submissionDate, ...

13-14: Breaking Change: Plan migration strategy for shared data structures

As noted in the comment, this change affects shared data structures in Hazelcast/Redis. A migration strategy is needed to handle existing serialized data.

Consider the following recommendations:

  1. Document the migration steps in release notes
  2. Implement a data migration script
  3. Consider adding version information to the serialized data
  4. Plan for backward compatibility during the migration period
src/main/webapp/app/entities/programming/programming-submission.model.ts (1)

9-11: Consider enhancing type safety and documentation.

While the implementation is correct, we could improve it further:

  1. Add JSDoc comments to document the purpose and usage of each new property
  2. Consider using a union type for more precise state management

Here's a suggested enhancement:

+    /**
+     * Indicates whether the submission is currently being processed by the build system.
+     * Used to differentiate between queued and active processing states.
+     */
     public isProcessing?: boolean;
+    /**
+     * Timestamp when the build process started.
+     * Used for calculating actual build duration.
+     */
     public buildStartDate?: dayjs.Dayjs;
+    /**
+     * Predicted completion time based on build queue analysis.
+     * Used to display estimated wait time to users.
+     */
     public estimatedCompletionDate?: dayjs.Dayjs;

Consider adding a type for better state management:

type SubmissionState = 'QUEUED' | 'PROCESSING' | 'COMPLETED' | 'FAILED';
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseBuildConfigRepository.java (1)

21-23: Add Javadoc to document the exception behavior.

The implementation looks good and follows the repository's pattern for handling missing entities. Consider adding documentation to clarify the exception thrown when the config is not found.

Add this documentation above the method:

+    /**
+     * Retrieves a programming exercise build configuration by its programming exercise ID.
+     *
+     * @param programmingExerciseId the ID of the programming exercise
+     * @return the build configuration
+     * @throws EntityNotFoundException if no build configuration exists for the given programming exercise ID
+     */
     default ProgrammingExerciseBuildConfig findByProgrammingExerciseIdElseThrow(Long programmingExerciseId) {
src/main/java/de/tum/cit/aet/artemis/exercise/dto/SubmissionDTO.java (2)

18-19: LGTM! Consider adding field documentation.

The new fields appropriately support the build status tracking requirements. Good choice using ZonedDateTime for timestamp fields and primitive boolean for isProcessing.

Consider adding Javadoc for the new fields to document their purpose:

/**
 * DTO containing {@link Submission} information.
 * This does not include large reference attributes in order to send minimal data to the client.
 *
 * @param isProcessing indicates if the submission is currently being processed
 * @param buildStartDate the date when the build started processing
 * @param estimatedCompletionDate the estimated date when the build will complete
 */

27-37: Consider grouping timing parameters into a separate record.

To improve maintainability and reduce parameter count, consider extracting timing-related fields into a separate record.

Create a new record:

public record SubmissionTiming(
    boolean isProcessing,
    ZonedDateTime buildStartDate,
    ZonedDateTime estimatedCompletionDate
) {}

Then refactor the method:

-public static SubmissionDTO of(Submission submission, boolean isProcessing, ZonedDateTime buildStartDate, ZonedDateTime estimatedCompletionDate) {
+public static SubmissionDTO of(Submission submission, SubmissionTiming timing) {
     if (submission instanceof ProgrammingSubmission programmingSubmission) {
         return new SubmissionDTO(/*...*/,
-            isProcessing, buildStartDate, estimatedCompletionDate);
+            timing.isProcessing(), timing.buildStartDate(), timing.estimatedCompletionDate());
     }
     return new SubmissionDTO(/*...*/,
-        false, null, null);
+        SubmissionTiming.DEFAULT);  // Add a static DEFAULT instance with false/null values
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/FinishedBuildJobDTO.java (1)

39-39: Consider using builder pattern for better readability

The SubmissionDTO.of() call with multiple boolean and null parameters reduces code clarity. Consider using the builder pattern or creating a more explicit factory method for finished build jobs.

Example approach:

-SubmissionDTO submissionDTO = result.getSubmission() == null ? null : SubmissionDTO.of(result.getSubmission(), false, null, null);
+SubmissionDTO submissionDTO = result.getSubmission() == null ? null : 
+    SubmissionDTO.finishedBuildOf(result.getSubmission());  // New factory method specifically for finished builds
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildJobQueueItem.java (2)

Line range hint 1-15: Consider implementing versioning strategy for shared data structure changes.

Given that this is a shared data structure between core and build agent nodes, and changes require migration or clearing of Hazelcast/Redis data, consider implementing a versioning strategy to handle data structure evolution more gracefully.

Consider:

  1. Adding version field to the record
  2. Implementing migration scripts
  3. Adding documentation about migration steps in release notes

32-34: Consider adding validation for timing information consistency.

The constructor should ensure that the timing information is consistent (e.g., completion dates are after start dates).

Consider adding validation:

 public BuildJobQueueItem(BuildJobQueueItem queueItem, ZonedDateTime buildCompletionDate, BuildStatus status) {
+    Objects.requireNonNull(buildCompletionDate, "buildCompletionDate must not be null");
+    Objects.requireNonNull(status, "status must not be null");
+    if (queueItem.jobTimingInfo.buildStartDate() != null && buildCompletionDate.isBefore(queueItem.jobTimingInfo.buildStartDate())) {
+        throw new IllegalArgumentException("buildCompletionDate must be after buildStartDate");
+    }
     this(queueItem.id(), queueItem.name(), queueItem.buildAgent(), queueItem.participationId(), queueItem.courseId(), queueItem.exerciseId(), queueItem.retryCount(),
             queueItem.priority(), status, queueItem.repositoryInfo(), new JobTimingInfo(queueItem.jobTimingInfo.submissionDate(), queueItem.jobTimingInfo.buildStartDate(),
                     buildCompletionDate, queueItem.jobTimingInfo.estimatedCompletionDate(), queueItem.jobTimingInfo.estimatedDuration()),
             queueItem.buildConfig(), null);
 }
src/main/java/de/tum/cit/aet/artemis/programming/dto/ResultDTO.java (1)

Line range hint 27-29: Consider implementing server-side result string calculation

The TODO comment raises a valid architectural point about moving result string calculations from client to server side. This would improve consistency across different clients and simplify client-side logic.

Would you like me to help create a GitHub issue to track the implementation of server-side result string calculation? I can provide a detailed implementation plan that includes:

  • Adding result string calculation logic to the server
  • Updating the DTO to include the calculated string
  • Removing client-side calculation logic
src/main/webapp/app/exercises/programming/participate/code-editor-student-container.component.html (1)

78-81: Progress bar integration aligns with PR objectives

The addition of [showProgressBar]="true" to the <jhi-updating-result> component enhances the user experience by providing visual feedback during build status updates, which aligns well with the PR's goal of improving build status visibility.

Consider making the progress bar visibility configurable based on the submission state (queued vs. processing) to provide more granular feedback to users.

-                  [showProgressBar]="true"
+                  [showProgressBar]="participation.submissionState === 'QUEUED' || participation.submissionState === 'PROCESSING'"
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIQueueWebsocketService.java (2)

42-43: Update constructor's javadoc to include the new parameter

The constructor injection is correctly implemented, but the javadoc needs to be updated to include the programmingMessagingService parameter.

     /**
      * Instantiates a new Local ci queue websocket service.
      *
      * @param hazelcastInstance                the hazelcast instance
      * @param localCIWebsocketMessagingService the local ci build queue websocket service
      * @param sharedQueueManagementService     the local ci shared build job queue service
+     * @param programmingMessagingService       the programming messaging service
      */

Also applies to: 56-56, 60-60


154-157: Add debug logging for build processing notifications

Consider adding debug logging to track notification delivery, similar to other debug logs in the service.

     private void notifyUserAboutBuildProcessing(long exerciseId, long participationId, String commitHash, ZonedDateTime buildStartDate, ZonedDateTime estimatedCompletionDate) {
+        log.debug("Notifying user about build processing - exercise: {}, participation: {}, estimated completion: {}", exerciseId, participationId, estimatedCompletionDate);
         var submissionProcessingDTO = new SubmissionProcessingDTO(exerciseId, participationId, commitHash, buildStartDate, estimatedCompletionDate);
         programmingMessagingService.notifyUserAboutSubmissionProcessing(submissionProcessingDTO, exerciseId, participationId);
     }
src/main/webapp/app/exercises/shared/result/result.component.html (2)

7-15: LGTM! Consider adding ARIA attributes for better accessibility.

The implementation correctly differentiates the queued state and follows the new Angular syntax guidelines. The conditional display of estimated time enhances user experience.

Consider adding aria-label to improve accessibility:

-            <span class="text-primary">
+            <span class="text-primary" role="status" aria-label="{{ 'artemisApp.editor.queued' | translate }}">

16-37: Enhance progress bar accessibility.

The progress bar implementation looks good, but could benefit from better accessibility support.

Consider these accessibility enhancements:

-                    <div class="progress position-relative" role="progressbar" [style.min-width.px]="200" [style.height.px]="30">
+                    <div 
+                        class="progress position-relative" 
+                        role="progressbar" 
+                        [attr.aria-valuenow]="progressBarValue"
+                        aria-valuemin="0"
+                        aria-valuemax="100"
+                        [attr.aria-label]="'artemisApp.editor.eta' | translate"
+                        [style.min-width.px]="200" 
+                        [style.height.px]="30">
src/main/webapp/i18n/en/editor.json (1)

34-36: LGTM with a minor suggestion for the ETA info text.

The new translation keys are well-integrated and align perfectly with the PR objectives to improve build status visibility. The messages are clear and consistent with the existing style.

Consider making the ETA explanation slightly more specific:

-            "etaInfo": "Estimated time until build is finished. This is an estimate and can vary.",
+            "etaInfo": "Estimated time until your build is finished. This time is calculated based on current queue status and may vary.",
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingSubmissionRepository.java (2)

162-170: Consider consolidating duplicate query methods.

This query is very similar to the existing findByParticipationIdAndCommitHashOrderByIdDescWithFeedbacksAndTeamStudents method, but fetches fewer associations. Consider:

  1. Renaming this method to indicate it's a "light" version
  2. Or creating a single method with optional fetch joins based on a parameter

Example refactor to combine both methods:

-@Query("""
-        SELECT s
-        FROM ProgrammingSubmission s
-            LEFT JOIN FETCH s.participation p
-        WHERE p.id = :participationId
-            AND s.commitHash = :commitHash
-        ORDER BY s.id DESC
-        """)
-List<ProgrammingSubmission> findByParticipationIdAndCommitHashOrderByIdDesc(
-    @Param("participationId") long participationId, 
-    @Param("commitHash") String commitHash);

+@Query("""
+        SELECT s
+        FROM ProgrammingSubmission s
+            LEFT JOIN FETCH s.participation p
+            LEFT JOIN FETCH CASE WHEN :includeFeedbacks = true THEN s.results END r
+            LEFT JOIN FETCH CASE WHEN :includeFeedbacks = true THEN r.feedbacks END f
+            LEFT JOIN FETCH CASE WHEN :includeFeedbacks = true THEN p.team END t
+            LEFT JOIN FETCH CASE WHEN :includeFeedbacks = true THEN t.students END
+        WHERE p.id = :participationId
+            AND s.commitHash = :commitHash
+        ORDER BY s.id DESC
+        """)
+List<ProgrammingSubmission> findByParticipationIdAndCommitHash(
+    @Param("participationId") long participationId,
+    @Param("commitHash") String commitHash,
+    @Param("includeFeedbacks") boolean includeFeedbacks);

172-174: Consider using Optional for null safety.

The method returns null when no submission is found. Consider using Optional to make this explicit in the method signature, consistent with other similar methods in this repository (e.g., findByResultId).

-default ProgrammingSubmission findFirstByParticipationIdAndCommitHashOrderByIdDesc(
-    long participationId, String commitHash) {
-    return findByParticipationIdAndCommitHashOrderByIdDesc(participationId, commitHash)
-        .stream().findFirst().orElse(null);
-}
+default Optional<ProgrammingSubmission> findFirstByParticipationIdAndCommitHashOrderByIdDesc(
+    long participationId, String commitHash) {
+    return findByParticipationIdAndCommitHashOrderByIdDesc(participationId, commitHash)
+        .stream().findFirst();
+}
src/main/java/de/tum/cit/aet/artemis/programming/web/localci/BuildJobQueueResource.java (2)

201-203: Consider using a DTO for the response

Instead of returning a raw ZonedDateTime, consider creating a dedicated DTO to encapsulate the queue duration estimation. This would provide more flexibility for adding additional metadata in the future without breaking API compatibility.

Example DTO:

public record QueueDurationEstimationDTO(
    ZonedDateTime estimatedStartTime,
    long estimatedDurationInSeconds,
    String status
) {}

195-200: Enhance JavaDoc with more details

The current JavaDoc could be more descriptive about:

  • What the estimated queue duration represents (start time, completion time?)
  • The return value format and timezone
  • Possible error responses

Example enhancement:

/**
 * Returns the estimated queue duration for a build job.
 *
 * @param participationId the id of the participation
 * @return ResponseEntity containing the estimated start time in UTC
 * @throws BadRequestException if participationId is invalid
 */
src/main/webapp/app/exercises/shared/result/updating-result.component.ts (1)

176-185: Consider decoupling CI profile check from timing updates

The timing info update being tied to getIsLocalCIProfile() might limit functionality if timing information becomes available in other CI environments.

Consider extracting the CI profile check to a more flexible configuration:

-  if (this.submissionService.getIsLocalCIProfile()) {
+  if (this.submissionService.getIsLocalCIProfile() || this.submissionService.supportsBuildTiming()) {
     this.updateBuildTimingInfo(submissionState, buildTimingInfo);
   }
src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.java (2)

88-93: Add documentation and validation for new fields.

The new fields lack documentation explaining their purpose and constraints. Consider:

  1. Adding Javadoc to explain the purpose and unit of measurement for each field
  2. Adding validation constraints (e.g., @Min(0)) to ensure non-negative values
+    /**
+     * The total duration of successful builds in seconds.
+     * This metric helps in estimating future build durations.
+     */
+    @Min(0)
     @Column(name = "build_duration_seconds")
     private long buildDurationSeconds = 0;

+    /**
+     * The total number of successful builds.
+     * Used in conjunction with buildDurationSeconds to calculate average build duration.
+     */
+    @Min(0)
     @Column(name = "successful_build_count")
     private long successfulBuildCount = 0;

303-318: Update toString() method to include new fields.

The new fields should be included in the toString() method to maintain consistency and aid in debugging.

     @Override
     public String toString() {
         return "BuildJobConfig{" + "id=" + getId() + ", sequentialTestRuns=" + sequentialTestRuns + ", branch='" + branch + '\'' + ", buildPlanConfiguration='"
                 + buildPlanConfiguration + '\'' + ", buildScript='" + buildScript + '\'' + ", checkoutSolutionRepository=" + checkoutSolutionRepository + ", checkoutPath='"
                 + testCheckoutPath + '\'' + ", timeoutSeconds=" + timeoutSeconds + ", dockerFlags='" + dockerFlags + '\'' + ", testwiseCoverageEnabled=" + testwiseCoverageEnabled
-                + ", theiaImage='" + theiaImage + '\'' + ", allowBranching=" + allowBranching + ", branchRegex='" + branchRegex + '\'' + '}';
+                + ", theiaImage='" + theiaImage + '\'' + ", allowBranching=" + allowBranching + ", branchRegex='" + branchRegex + '\''
+                + ", buildDurationSeconds=" + buildDurationSeconds + ", successfulBuildCount=" + successfulBuildCount + '}';
     }
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIServiceTest.java (1)

Line range hint 73-92: Enhance build status test assertions and DB performance tracking.

The test method testReturnCorrectBuildStatus could benefit from:

  1. More specific assertions about the timing information
  2. DB query count tracking as per coding guidelines

Consider enhancing the test:

+    @Test
+    @WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
+    @MonitorDBQueries // Add DB query monitoring
     void testReturnCorrectBuildStatus() {
         // ... existing setup ...
 
         // Add specific timing assertions
+        assertThat(job1.getJobTimingInfo())
+            .satisfies(timing -> {
+                assertThat(timing.estimatedCompletionDate()).isNotNull();
+                assertThat(timing.estimatedDuration()).isPositive();
+            });
 
         // ... existing assertions ...
     }
src/test/javascript/spec/component/exercises/shared/result.spec.ts (1)

226-233: Good test case, but consider enhancing it.

The test correctly verifies interval creation, but could be improved for better coverage and cleanup.

Consider these enhancements:

  1. Add interval cleanup in afterEach to prevent memory leaks:
 afterEach(() => {
     jest.restoreAllMocks();
+    if (component.estimatedDurationInterval) {
+        clearInterval(component.estimatedDurationInterval);
+    }
 });
  1. Add more assertions to verify interval behavior:
 it('should trigger Interval creation on estimatedCompletionDate change', () => {
     component.estimatedCompletionDate = dayjs().add(20, 'seconds');
     component.ngOnChanges({
         estimatedCompletionDate: { previousValue: undefined, currentValue: component.estimatedCompletionDate, firstChange: true, isFirstChange: () => true },
     });
     expect(component.estimatedDurationInterval).toBeDefined();
+    // Verify interval is cleared when estimatedCompletionDate is removed
+    component.ngOnChanges({
+        estimatedCompletionDate: { previousValue: component.estimatedCompletionDate, currentValue: undefined, firstChange: false, isFirstChange: () => false },
+    });
+    expect(component.estimatedDurationInterval).toBeUndefined();
 });
src/test/javascript/spec/component/shared/updating-result.component.spec.ts (2)

51-54: Consider adding edge cases to test data

While the current test data is good for happy path testing, consider adding edge cases such as:

  • Past estimated completion dates
  • Null or undefined dates
  • Very short/long duration estimates
 const buildTimingInfo: BuildTimingInfo = {
     buildStartDate: dayjs().subtract(10, 'second'),
     estimatedCompletionDate: dayjs().add(10, 'second'),
+    // Add more test cases:
+    // pastEstimation: {
+        buildStartDate: dayjs().subtract(20, 'second'),
+        estimatedCompletionDate: dayjs().subtract(10, 'second'),
+    },
+    // nullDates: {
+        buildStartDate: null,
+        estimatedCompletionDate: null,
+    },
 };

Line range hint 1-267: Overall test coverage is good but could be enhanced

The test suite effectively covers the new build queue functionality and timing updates. However, consider:

  1. Adding more edge cases for timing data
  2. Improving error scenario coverage
  3. Adding explicit cleanup verification
  4. Testing network error handling

These improvements would make the test suite more robust and comprehensive.

src/main/webapp/app/exercises/shared/result/result.component.ts (4)

58-58: LGTM! Consider adding JSDoc comments.

The new input properties are well-typed and follow Angular naming conventions. Consider adding JSDoc comments to document their purpose and expected values.

Example documentation:

/** Indicates if the build job is currently in queue */
@Input() isQueued = false;

/** Expected completion time of the build job */
@Input() estimatedCompletionDate?: dayjs.Dayjs;

/** Time when the build job started processing */
@Input() buildStartDate?: dayjs.Dayjs;

/** Controls the visibility of the progress bar */
@Input() showProgressBar = false;

Also applies to: 68-70


80-82: Initialize properties and add type annotations.

The new properties should be initialized to prevent undefined behavior and have explicit type annotations for better maintainability.

-estimatedRemaining: number;
-progressBarValue: number;
-estimatedDurationInterval: ReturnType<typeof setInterval>;
+/** Remaining time in seconds until estimated completion */
+estimatedRemaining = 0;
+/** Progress bar completion percentage (0-100) */
+progressBarValue = 0;
+/** Interval handle for updating estimated duration */
+estimatedDurationInterval?: ReturnType<typeof setInterval>;

Line range hint 188-213: Fix potential issues in progress calculation logic.

Several issues need to be addressed:

  1. Clear existing interval before setting up a new one to prevent memory leaks
  2. Add null check for buildStartDate
  3. Add protection against division by zero
  4. Extract magic number 100 to a constant
 if (changes.estimatedCompletionDate && this.estimatedCompletionDate) {
-    clearInterval(this.estimatedDurationInterval);
+    if (this.estimatedDurationInterval) {
+        clearInterval(this.estimatedDurationInterval);
+    }
+    
+    if (!this.buildStartDate) {
+        return;
+    }
+    
+    const PROGRESS_MAX = 100;
     this.estimatedDurationInterval = setInterval(() => {
         this.estimatedRemaining = Math.max(0, dayjs(this.estimatedCompletionDate).diff(dayjs(), 'seconds'));
         const estimatedDuration = dayjs(this.estimatedCompletionDate).diff(dayjs(this.buildStartDate), 'seconds');
-        this.progressBarValue = Math.round((1 - this.estimatedRemaining / estimatedDuration) * 100);
+        this.progressBarValue = estimatedDuration > 0 
+            ? Math.min(Math.round((1 - this.estimatedRemaining / estimatedDuration) * PROGRESS_MAX), PROGRESS_MAX)
+            : 0;
         if (this.estimatedRemaining <= 0) {
             clearInterval(this.estimatedDurationInterval);
         }
     }, 1000);
 }

Line range hint 1-349: Add unit tests for new functionality.

Consider adding unit tests to verify:

  1. Progress calculation logic
  2. State transitions between queued and building states
  3. Cleanup of intervals
  4. Edge cases in estimated time calculations

Would you like me to help generate the unit test cases?

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

197-197: Consider using builder pattern for JobTimingInfo creation.

The current constructor call with multiple null parameters reduces code readability and makes it harder to understand the purpose of each parameter. Consider implementing a builder pattern for JobTimingInfo to make the code more maintainable and self-documenting.

Consider creating a builder for JobTimingInfo:

public record JobTimingInfo(
    ZonedDateTime submissionDate,
    ZonedDateTime processingStartDate,
    ZonedDateTime processingEndDate,
    ZonedDateTime estimatedCompletionDate,
    long estimatedDuration
) {
    public static class Builder {
        private ZonedDateTime submissionDate;
        private ZonedDateTime processingStartDate;
        private ZonedDateTime processingEndDate;
        private ZonedDateTime estimatedCompletionDate;
        private long estimatedDuration;

        public Builder submissionDate(ZonedDateTime date) {
            this.submissionDate = date;
            return this;
        }

        public Builder estimatedDuration(long duration) {
            this.estimatedDuration = duration;
            return this;
        }

        public JobTimingInfo build() {
            return new JobTimingInfo(
                submissionDate,
                processingStartDate,
                processingEndDate,
                estimatedCompletionDate,
                estimatedDuration
            );
        }
    }
}

Then update the instantiation:

-        JobTimingInfo jobTimingInfo = new JobTimingInfo(submissionDate, null, null, null, estimatedDuration);
+        JobTimingInfo jobTimingInfo = new JobTimingInfo.Builder()
+            .submissionDate(submissionDate)
+            .estimatedDuration(estimatedDuration)
+            .build();
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (1)

98-99: Consider using Builder pattern for test data setup.

The current test data setup is verbose and could be hard to maintain. Consider implementing a Builder pattern for BuildJobQueueItem and BuildAgentInformation to make the test setup more readable and maintainable.

Example implementation:

public class BuildJobQueueItemBuilder {
    private String id = "default-id";
    private String name = "default-name";
    private BuildAgentDTO buildAgent;
    // ... other fields

    public static BuildJobQueueItemBuilder aJob() {
        return new BuildJobQueueItemBuilder();
    }

    public BuildJobQueueItemBuilder withId(String id) {
        this.id = id;
        return this;
    }

    public BuildJobQueueItem build() {
        return new BuildJobQueueItem(id, name, buildAgent, ...);
    }
}

// Usage in test:
job1 = BuildJobQueueItemBuilder.aJob()
    .withId("1")
    .withName("job1")
    .withBuildAgent(buildAgent)
    .build();
src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (1)

Line range hint 1-1: Consider adding timing metrics collection.

To further improve build status updates, consider:

  1. Collecting historical timing data for better estimations
  2. Adding metrics for queue wait times and processing times
  3. Implementing a feedback mechanism to adjust estimations based on actual completion times

Example metrics implementation:

@Service
public class BuildMetricsService {
    private final MeterRegistry registry;
    
    public void recordQueueTime(Duration duration) {
        registry.timer("build.queue.time").record(duration);
    }
    
    public void recordProcessingTime(Duration duration) {
        registry.timer("build.processing.time").record(duration);
    }
    
    public void recordEstimationAccuracy(Duration estimated, Duration actual) {
        registry.gauge("build.estimation.accuracy", 
            actual.getSeconds() - estimated.getSeconds());
    }
}
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java (1)

517-544: Enhance test readability and robustness.

While the test logic is sound, consider these improvements:

  1. Extract magic number 24 into a constant with a descriptive name explaining the calculation (20 seconds + 20% buffer).
  2. Add assertions to verify that buildStartDate is not null before using it in timing calculations.
  3. Consider adding comments explaining the timing calculations for better maintainability.

Here's a suggested refactor:

+    private static final int BUILD_DURATION_SECONDS = 20;
+    private static final double DURATION_BUFFER_FACTOR = 1.2;
+    private static final int EXPECTED_DURATION = (int) (BUILD_DURATION_SECONDS * DURATION_BUFFER_FACTOR);
+
     @Test
     @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER")
     void testBuildJobTimingInfo() {
         // Pause build agent processing
         sharedQueueProcessingService.removeListenerAndCancelScheduledFuture();
         ProgrammingExerciseBuildConfig buildConfig = programmingExercise.getBuildConfig();
-        buildConfig.setBuildDurationSeconds(20);
+        buildConfig.setBuildDurationSeconds(BUILD_DURATION_SECONDS);
         programmingExerciseBuildConfigRepository.save(buildConfig);

         ProgrammingExerciseStudentParticipation studentParticipation = localVCLocalCITestService.createParticipation(programmingExercise, student1Login);

         localVCServletService.processNewPush(commitHash, studentAssignmentRepository.originGit.getRepository());

         await().until(() -> queuedJobs.stream().anyMatch(buildJobQueueItem -> buildJobQueueItem.buildConfig().commitHashToBuild().equals(commitHash)
                 && buildJobQueueItem.participationId() == studentParticipation.getId()));

         BuildJobQueueItem item = queuedJobs.stream().filter(i -> i.buildConfig().commitHashToBuild().equals(commitHash) && i.participationId() == studentParticipation.getId())
                 .findFirst().orElseThrow();
-        assertThat(item.jobTimingInfo().estimatedDuration()).isEqualTo(24);
+        // Verify estimated duration includes buffer time
+        assertThat(item.jobTimingInfo().estimatedDuration()).isEqualTo(EXPECTED_DURATION);
         sharedQueueProcessingService.init();

         await().until(() -> processingJobs.values().stream().anyMatch(buildJobQueueItem -> buildJobQueueItem.buildConfig().commitHashToBuild().equals(commitHash)
                 && buildJobQueueItem.participationId() == studentParticipation.getId()));
         item = processingJobs.values().stream().filter(i -> i.buildConfig().commitHashToBuild().equals(commitHash) && i.participationId() == studentParticipation.getId())
                 .findFirst().orElseThrow();
-        assertThat(item.jobTimingInfo().estimatedDuration()).isEqualTo(24);
+        assertThat(item.jobTimingInfo().estimatedDuration()).isEqualTo(EXPECTED_DURATION);
+        // Verify buildStartDate is set
+        assertThat(item.jobTimingInfo().buildStartDate()).isNotNull();
+        // Verify estimated completion date is correctly calculated
         assertThat(item.jobTimingInfo().estimatedCompletionDate()).isCloseTo(item.jobTimingInfo().buildStartDate().plusSeconds(24), within(500, ChronoUnit.MILLIS));
     }
src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java (1)

241-242: Consider documenting the side effect.

The code sets the participation to null before creating the DTO. While this is intentional to reduce response size, it's a side effect that should be documented.

Add a more descriptive comment:

-        // Remove participation, is not needed in the response.
+        // Set participation to null to reduce response payload size since it's not needed in the client
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 745c7f7 and c9fcc6c.

⛔ Files ignored due to path filters (2)
  • src/main/resources/config/liquibase/changelog/20241101120000_changelog.xml is excluded by !**/*.xml
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (37)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildJobQueueItem.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/FinishedBuildJobDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/dto/JobTimingInfo.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/exercise/dto/SubmissionDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/dto/ResultDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/dto/SubmissionProcessingDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseBuildConfigRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingSubmissionRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingMessagingService.java (6 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIQueueWebsocketService.java (6 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (10 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCITriggerService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java (5 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java (5 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/web/localci/BuildJobQueueResource.java (2 hunks)
  • src/main/webapp/app/entities/programming/programming-submission.model.ts (1 hunks)
  • src/main/webapp/app/entities/programming/submission-processing-dto.ts (1 hunks)
  • src/main/webapp/app/exercises/programming/participate/code-editor-student-container.component.html (1 hunks)
  • src/main/webapp/app/exercises/programming/participate/programming-submission.service.ts (16 hunks)
  • src/main/webapp/app/exercises/shared/result/result.component.html (1 hunks)
  • src/main/webapp/app/exercises/shared/result/result.component.ts (6 hunks)
  • src/main/webapp/app/exercises/shared/result/result.utils.ts (3 hunks)
  • src/main/webapp/app/exercises/shared/result/updating-result.component.html (1 hunks)
  • src/main/webapp/app/exercises/shared/result/updating-result.component.ts (5 hunks)
  • src/main/webapp/app/overview/submission-result-status.module.ts (1 hunks)
  • src/main/webapp/i18n/de/editor.json (1 hunks)
  • src/main/webapp/i18n/en/editor.json (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java (6 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (5 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIServiceTest.java (1 hunks)
  • src/test/javascript/spec/component/exercises/shared/result.spec.ts (1 hunks)
  • src/test/javascript/spec/component/shared/updating-result.component.spec.ts (6 hunks)
  • src/test/javascript/spec/helpers/mocks/service/mock-programming-submission.service.ts (2 hunks)
  • src/test/javascript/spec/service/programming-submission.service.spec.ts (9 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/de/tum/cit/aet/artemis/programming/dto/SubmissionProcessingDTO.java
🧰 Additional context used
📓 Path-based instructions (35)
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildJobQueueItem.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/buildagent/dto/FinishedBuildJobDTO.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/buildagent/dto/JobTimingInfo.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/buildagent/service/SharedQueueProcessingService.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/core/config/Constants.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/exercise/dto/SubmissionDTO.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/domain/ProgrammingExerciseBuildConfig.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/dto/ResultDTO.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/repository/ProgrammingExerciseBuildConfigRepository.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/repository/ProgrammingSubmissionRepository.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/ProgrammingMessagingService.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/localci/LocalCIQueueWebsocketService.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/localci/LocalCIResultProcessingService.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/localci/LocalCITriggerService.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/localci/SharedQueueManagementService.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/web/ProgrammingExerciseParticipationResource.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/web/localci/BuildJobQueueResource.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/webapp/app/entities/programming/programming-submission.model.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/main/webapp/app/entities/programming/submission-processing-dto.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/main/webapp/app/exercises/programming/participate/code-editor-student-container.component.html (1)

Pattern src/main/webapp/**/*.html: @if and @for are new and valid Angular syntax replacing *ngIf and *ngFor. They should always be used over the old style.

src/main/webapp/app/exercises/programming/participate/programming-submission.service.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/main/webapp/app/exercises/shared/result/result.component.html (1)

Pattern src/main/webapp/**/*.html: @if and @for are new and valid Angular syntax replacing *ngIf and *ngFor. They should always be used over the old style.

src/main/webapp/app/exercises/shared/result/result.component.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/main/webapp/app/exercises/shared/result/result.utils.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/main/webapp/app/exercises/shared/result/updating-result.component.html (1)

Pattern src/main/webapp/**/*.html: @if and @for are new and valid Angular syntax replacing *ngIf and *ngFor. They should always be used over the old style.

src/main/webapp/app/exercises/shared/result/updating-result.component.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/main/webapp/app/overview/submission-result-status.module.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/main/webapp/i18n/de/editor.json (1)

Pattern src/main/webapp/i18n/de/**/*.json: German language translations should be informal (dutzen) and should never be formal (sietzen). So the user should always be addressed with "du/dein" and never with "sie/ihr".

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.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

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.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

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIServiceTest.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

src/test/javascript/spec/component/exercises/shared/result.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

src/test/javascript/spec/component/shared/updating-result.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

src/test/javascript/spec/helpers/mocks/service/mock-programming-submission.service.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

src/test/javascript/spec/service/programming-submission.service.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

🪛 Biome
src/test/javascript/spec/service/programming-submission.service.spec.ts

[error] 151-151: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)


[error] 170-170: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)

🔇 Additional comments (44)
src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingMessagingService.java (3)

55-65: Proper use of constructor injection for ParticipationRepository.

Injecting ParticipationRepository via the constructor aligns with dependency injection best practices and improves testability.


170-172: getSubmissionProcessingTopicForTAAndAbove is correctly implemented.

The method correctly constructs the topic string for TA and above, ensuring notifications are sent to the appropriate recipients.


87-88: Ensure consistent usage of notifyUserAboutSubmission methods.

The addition of the isProcessing parameter and overloading notifyUserAboutSubmission ensures clarity in notifications. Verify that all calls to notifyUserAboutSubmission pass the correct isProcessing value to maintain consistent behavior.

To confirm consistent usage, run the following script to find all invocations of notifyUserAboutSubmission:

✅ Verification successful

Let me analyze the results from the rg command to verify the consistent usage of notifyUserAboutSubmission.

The search results show:

  1. Two method definitions in ProgrammingMessagingService.java:
    • One with two parameters that delegates to the three-parameter version with false
    • One with three parameters (including isProcessing)
  2. All other invocations across the codebase use the two-parameter version, which correctly defaults to isProcessing=false

The usage is consistent across the codebase.

All calls to notifyUserAboutSubmission either:

  • Use the two-parameter version, which internally sets isProcessing=false
  • Or would explicitly pass the isProcessing parameter using the three-parameter version if needed
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all calls to notifyUserAboutSubmission methods

# Search for method calls to notifyUserAboutSubmission with or without the new parameter
rg --no-heading --line-number 'notifyUserAboutSubmission\(' -A 1

Length of output: 3635

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (2)

269-269: Good practice: Changed saveFinishedBuildJob visibility to private

Making the saveFinishedBuildJob method private restricts its access to within the class, adhering to the principle of least privilege. This enhances encapsulation and reduces the potential for misuse outside this class.


97-97: Appropriate use of constructor injection for dependencies

Assigning programmingExerciseBuildConfigRepository via constructor injection in line 97~ follows dependency injection best practices, improving the testability and maintainability of the service.

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

346-352: ⚠️ Potential issue

Replace getLast() with get(participationBuildJobIds.size() - 1) to avoid compilation error

In the method getIdOfQueuedJobFromParticipation, using getLast() on a List may lead to a compilation error since List does not have a getLast() method in Java. You should use get(participationBuildJobIds.size() - 1) instead to retrieve the last element.

Apply this diff to fix the issue:

-        return participationBuildJobIds.getLast();
+        return participationBuildJobIds.get(participationBuildJobIds.size() - 1);

Likely invalid or redundant comment.

src/main/webapp/app/exercises/programming/participate/programming-submission.service.ts (4)

856-857: Ensure all subscriptions are properly unsubscribed in unsubscribeAllWebsocketTopics

In the unsubscribeAllWebsocketTopics method, make sure that all active subscriptions, especially those related to the queue estimate timers, are properly unsubscribed to prevent memory leaks.


16-19: Ensure correct module imports and paths

The added imports should be reviewed to ensure that the modules exist and the paths are correct. Also, verify that these imports are necessary and used within the service.


184-187: Verify usage of fetchQueueReleaseDateEstimationByParticipationId

The method fetchQueueReleaseDateEstimationByParticipationId is added but not used within the provided code. Ensure that it is utilized where necessary or remove it if it's not needed.

Run the following script to find usages of the method:

#!/bin/bash
# Description: Search for usages of `fetchQueueReleaseDateEstimationByParticipationId` in the codebase.

# Find all occurrences of the method name
rg 'fetchQueueReleaseDateEstimationByParticipationId\('

448-451: Initialize buildTimingInfo when emitting queued submission

In the emitQueuedSubmission method, the buildTimingInfo property is not set, which might lead to issues when subscribers expect this information. Consider initializing buildTimingInfo appropriately.

Run the following script to check for usages of emitQueuedSubmission and ensure buildTimingInfo is handled correctly:

src/main/webapp/app/entities/programming/submission-processing-dto.ts (1)

1-1: LGTM! Proper ESM import for dayjs.

The ESM import is correctly used, which enables better tree-shaking for optimal bundle size.

src/main/webapp/app/exercises/shared/result/updating-result.component.html (1)

7-7: LGTM! Queue status property enhances user awareness.

The addition of the [isQueued] property aligns perfectly with the PR objective to differentiate between queued and processing states, improving transparency for users.

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/JobTimingInfo.java (1)

13-14: Verify usage of new timing fields across the codebase

Let's verify that all constructors and factory methods are updated to handle the new fields correctly.

✅ Verification successful

Based on the search results, I can now provide a final response as all constructors and factory methods have been found and analyzed:

All JobTimingInfo instantiations are properly handling the fields

The verification shows that all usages of JobTimingInfo correctly handle all five fields (submissionDate, buildStartDate, buildCompletionDate, estimatedCompletionDate, estimatedDuration) across the codebase:

  • LocalCITriggerService initializes with null values for dates except submissionDate
  • SharedQueueProcessingService properly copies all fields and updates buildCompletionDate
  • BuildJobQueueItem correctly handles all fields in its factory methods
  • Test classes demonstrate proper initialization with various combinations of dates
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for JobTimingInfo instantiations
echo "Searching for JobTimingInfo constructors usage..."
rg "new JobTimingInfo\(" -A 2

# Search for methods that might need updates for the new fields
echo "Searching for methods handling JobTimingInfo..."
ast-grep --pattern 'class $_ {
  $$$
  $retType $method($_) {
    $$$
    JobTimingInfo
    $$$
  }
}'

Length of output: 6712

src/main/webapp/app/overview/submission-result-status.module.ts (2)

7-7: LGTM! Import statement follows Angular style guide.

The import statement follows proper naming conventions and module organization patterns.


10-10: Verify shared components for build status updates.

The addition of ArtemisSharedComponentModule aligns with the PR objectives for improving build status updates. Let's verify the required components are available.

✅ Verification successful

Build status components are correctly integrated through module dependencies

The verification confirms that build status functionality is properly integrated:

  • ArtemisProgrammingExerciseActionsModule provides the build status components (trigger build buttons and submission state)
  • ArtemisSharedComponentModule provides necessary UI components for actions and buttons
  • Both modules are correctly imported in the SubmissionResultStatusModule
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the shared components module contains necessary UI components for build status updates

# Check the shared component module for relevant components
ast-grep --pattern 'export class $status extends Component {
  $$$
}' src/main/webapp/app/shared/components/**/*.ts

# Look for build status related templates
rg -g '*.html' -A 5 'build.*status|queue.*status' src/main/webapp/app/shared/components/

Length of output: 983


Script:

#!/bin/bash
# Let's try a different approach to verify build status components

# Check for build status related components in shared module
rg -l "BuildStatus|QueueStatus" src/main/webapp/app/shared/

# Check the shared module definition
cat src/main/webapp/app/shared/shared.module.ts

# Look for build status components in the overview module
rg -l "BuildStatus|QueueStatus" src/main/webapp/app/overview/

# Check the submission result status module
cat src/main/webapp/app/overview/submission-result-status.module.ts

Length of output: 5926


Script:

#!/bin/bash
# Let's check the shared component module and related components

# Check the shared component module definition
cat src/main/webapp/app/shared/components/shared-component.module.ts

# Look for build status related components in programming exercise actions
rg -l "BuildStatus|QueueStatus" src/main/webapp/app/exercises/programming/shared/actions/

# Check the programming exercise actions module
cat src/main/webapp/app/exercises/programming/shared/actions/programming-exercise-actions.module.ts

Length of output: 7193

src/main/webapp/app/entities/programming/programming-submission.model.ts (2)

9-11: LGTM! The new properties align well with the PR objectives.

The added properties effectively support the differentiation between queued and processing states while enabling build duration estimation. The implementation follows Angular style guidelines correctly.


Line range hint 22-23: Consider removing the TODO comment.

The TODO comment suggests this method could be removed after implementing websocket-based submission fetching. Since this PR implements websocket communication for build status updates, we should verify if this method is still needed.

Would you like me to help implement the websocket-based solution to remove this method?

src/test/javascript/spec/helpers/mocks/service/mock-programming-submission.service.ts (1)

3-3: LGTM: Import statement is correctly placed and necessary.

The dayjs import is required for the new method's return type signature.

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/FinishedBuildJobDTO.java (1)

39-39: Verify the purpose of the third null parameter

The third parameter passed to SubmissionDTO.of() is not clear from the context. Let's verify its purpose and usage.

✅ Verification successful

The third parameter is buildStartDate and its usage is verified

From the codebase analysis, the third and fourth parameters of SubmissionDTO.of() are buildStartDate and estimatedCompletionDate respectively. In FinishedBuildJobDTO, passing null for both parameters is correct because:

  1. The build is already finished, so we don't need a build start date
  2. An estimated completion date is not applicable for completed builds

This is consistent with other usages in the codebase, where these parameters are only populated for active builds, such as in ProgrammingExerciseParticipationResource and LocalCIQueueWebsocketService.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for SubmissionDTO.of() method definition to understand parameters
ast-grep --pattern 'record SubmissionDTO {
  $$$
  static $$ of($$$) {
    $$$
  }
  $$$
}'

# Search for other usages of SubmissionDTO.of() for comparison
rg "SubmissionDTO\.of\(" -A 2

Length of output: 3468


Script:

#!/bin/bash
# Search for SubmissionDTO record definition to understand its parameters
ast-grep --pattern 'record SubmissionDTO($$$)'

# Search for any documentation or comments above SubmissionDTO.of method
rg -B 5 "static \w+ of\(" src/main/java/de/tum/cit/aet/artemis/programming/dto/SubmissionDTO.java || true

Length of output: 391


Script:

#!/bin/bash
# Find the SubmissionDTO file first
fd "SubmissionDTO.java"

# Then try to find any references to buildStartDate or estimatedCompletionDate in DTOs
rg "buildStartDate|estimatedCompletionDate" --type java

Length of output: 10197

src/main/java/de/tum/cit/aet/artemis/programming/dto/ResultDTO.java (2)

Line range hint 1-73: Implementation follows best practices and guidelines

The implementation demonstrates excellent adherence to coding guidelines:

  • Uses Java Records for immutable DTOs
  • Follows single responsibility principle
  • Implements minimal DTO pattern
  • Maintains clear separation between domain and DTO
  • Uses constructor injection

66-66: Verify the impact of null parameters in SubmissionDTO.of()

The updated method call includes false and two null parameters. While this aligns with the PR's objective to improve build status updates, we should verify that these null values don't cause issues.

✅ Verification successful

Based on the shell script results, I can now generate the final response:

Null parameters in SubmissionDTO.of() are used consistently across the codebase

The codebase shows consistent usage of null parameters in SubmissionDTO.of() calls across different services:

  • ProgrammingMessagingService: SubmissionDTO.of(submission, isProcessing, null, null)
  • ResultDTO: SubmissionDTO.of(result.getSubmission(), false, null, null)
  • FinishedBuildJobDTO: SubmissionDTO.of(result.getSubmission(), false, null, null)

The pattern of passing null for the last two parameters is standard practice in the codebase, and the implementation in SubmissionDTO is designed to handle these null values appropriately.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all usages of SubmissionDTO.of to understand the parameter handling
ast-grep --pattern 'SubmissionDTO.of($_)'

# Search for null checks in SubmissionDTO
rg -A 5 "SubmissionDTO" | rg -A 5 "null"

Length of output: 7513

src/main/webapp/app/exercises/programming/participate/code-editor-student-container.component.html (2)

Line range hint 2-2: LGTM: Consistent usage of new Angular syntax

The template correctly uses the new @if directive instead of *ngIf throughout the file, following the coding guidelines.

Also applies to: 5-5, 11-11, 23-23, 28-28, 38-38, 76-76, 96-96


Line range hint 77-82: Verify integration with new timing properties

The <jhi-updating-result> component should be receiving and utilizing the new timing properties mentioned in the AI summary (isQueued, estimatedCompletionDate, buildStartDate) to properly display the progress bar and queue status.

✅ Verification successful

Let me generate another script to check the component implementation since we found the template usage but need to verify the property definitions.


Let me try one more search to specifically find the UpdatingResultComponent implementation:


Based on the code review and search results, I can now provide a final response:

The timing properties are correctly integrated in the UpdatingResultComponent

The component properly handles and utilizes the new timing properties:

  • isQueued is set based on submission state
  • estimatedCompletionDate and buildStartDate are updated in updateBuildTimingInfo() method
  • The template correctly binds these properties to the result component
  • The progress bar display is controlled via the showProgressBar input property

The implementation matches the expected behavior for displaying queue status and build progress.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the UpdatingResultComponent implements the new timing properties

# Check for the property definitions in the component
ast-grep --pattern 'class UpdatingResultComponent {
  $$$
  @Input() $property: $type
  $$$
}'

# Check for the template usage of these properties
rg -A 5 'isQueued|estimatedCompletionDate|buildStartDate' --type html

Length of output: 10060


Script:

#!/bin/bash
# Search for the UpdatingResultComponent class implementation
rg -U "export class UpdatingResultComponent.*?\{.*?}" -A 50

# Also check for any interfaces or types that might define these properties
rg "interface.*?(Result|Timing|Queue)" -A 10

Length of output: 11955


Script:

#!/bin/bash
# Search for the component file directly
fd "updating-result.component.ts" --type f --exec cat {}

# Backup search with ripgrep
rg -l "UpdatingResultComponent" --type ts | xargs cat

Length of output: 223441

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIQueueWebsocketService.java (2)

3-3: LGTM: Appropriate imports added

The new imports align with the coding guidelines and support the enhanced build status update functionality:

  • Using ZonedDateTime ensures proper timezone handling
  • Using a dedicated DTO (SubmissionProcessingDTO) follows the minimal DTO principle

Also applies to: 25-26


154-157: LGTM: Well-structured notification method

The new method follows good practices:

  • Single responsibility principle
  • Clear naming
  • Appropriate access level
  • Proper delegation to messaging service
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingSubmissionRepository.java (1)

162-174: Verify the impact on build status updates.

These new methods appear to be part of the build status update enhancement. Please ensure:

  1. The lighter fetch joins are sufficient for the build status update use case
  2. The ordering by ID (instead of submission date) is intentional for this use case
✅ Verification successful

Let me gather more information about the build status update context and fetch joins.


Let me check one more aspect to understand how these methods are used in the build status context.


Based on the gathered information, I can now provide the final response:

The new methods are safe for build status updates

The methods are used in ProgrammingSubmissionService for submission creation and retrieval, with two variants:

  • A lighter version with basic fetch joins (participation only)
  • An extended version with additional fetch joins (feedbacks and team students)

The ordering by ID is appropriate as it ensures consistent retrieval of the latest submission when multiple submissions exist for the same commit hash, as timestamps might be identical in such cases.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if these methods are used in the context of build status updates
# and verify the consistency of ordering and fetch joins across similar use cases

# Check for usages of these methods in the codebase
echo "Searching for direct usages of the new methods..."
rg "findByParticipationIdAndCommitHashOrderByIdDesc|findFirstByParticipationIdAndCommitHashOrderByIdDesc"

# Check for similar patterns of submission retrieval
echo "Searching for similar submission retrieval patterns..."
ast-grep --pattern 'SELECT s FROM ProgrammingSubmission s WHERE s.participation.id = $_ AND s.commitHash = $_'

Length of output: 2422


Script:

#!/bin/bash
# Check the service methods using these repository methods
echo "Checking service methods context..."
rg -A 10 "findFirstByParticipationIdAndCommitHashOrderByIdDescWithFeedbacksAndTeamStudents" src/main/java/de/tum/cit/aet/artemis/programming/service/

# Check for other similar queries with different fetch joins
echo "Checking other similar queries with fetch joins..."
ast-grep --pattern $'@Query("""
            SELECT s
            FROM ProgrammingSubmission s
                LEFT JOIN FETCH $$$
            WHERE $$$
            """)'

# Look for build status related code
echo "Checking build status related code..."
rg -l "BuildStatus|build.*status" src/main/java/de/tum/cit/aet/artemis/programming/

Length of output: 5282


Script:

#!/bin/bash
# Check how these methods are used in build-related services
echo "Checking build-related service usage..."
rg -B 5 -A 10 "findFirstByParticipationIdAndCommitHash" src/main/java/de/tum/cit/aet/artemis/programming/service/localci/ src/main/java/de/tum/cit/aet/artemis/programming/service/jenkins/ src/main/java/de/tum/cit/aet/artemis/programming/service/gitlabci/

# Check the ProgrammingSubmissionService for build status related code
echo "Checking submission service build status context..."
rg -B 5 -A 10 "BuildStatus|build.*status" src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingSubmissionService.java

# Check other similar queries in the repository
echo "Checking other submission queries..."
rg "@Query.*ProgrammingSubmission.*ORDER BY" src/main/java/de/tum/cit/aet/artemis/programming/repository/

Length of output: 782

src/main/webapp/i18n/de/editor.json (1)

34-36: LGTM! The translations are consistent and follow guidelines.

The new German translations for build queue status and ETA information:

  • Follow the informal language requirement
  • Maintain consistency with existing translations
  • Align with the PR's objective of improving build status visibility
src/main/java/de/tum/cit/aet/artemis/programming/web/localci/BuildJobQueueResource.java (2)

32-32: LGTM: Imports follow best practices

The new imports are properly organized and follow Java best practices by avoiding star imports.

Also applies to: 35-35


201-211: Verify integration with client-side updates

The endpoint implementation aligns with the PR objectives for improving build status updates. However, let's verify the integration with client-side code that displays the queue status.

✅ Verification successful

Integration with client-side code is properly implemented

The endpoint is correctly integrated with the client-side code:

  • The endpoint is consumed in programming-submission.service.ts for fetching queue duration estimations
  • It's part of a broader build queue management system with comprehensive client-side components:
    • BuildQueueComponent for displaying queue status
    • BuildQueueService for managing queue-related operations
    • Integration with programming submission workflow
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for corresponding client-side code that consumes this endpoint

# Look for API calls to this endpoint in frontend code
rg -t js -t ts "queued-jobs/queue-duration-estimation"

# Look for queue status display components
rg -t ts "QueuedStatus|BuildQueue" --type ts

Length of output: 13702

src/main/webapp/app/exercises/shared/result/updating-result.component.ts (2)

7-7: LGTM: New properties align with feature requirements

The new properties and imports are well-structured and follow Angular naming conventions:

  • showProgressBar for UI control
  • isQueued for queue state tracking
  • estimatedCompletionDate and buildStartDate for timing management

Also applies to: 38-38, 49-51


141-141: Verify websocket status update implementation

The PR objectives mention websocket notifications for status updates, but let's verify the complete implementation.

Also applies to: 179-179

✅ Verification successful

Websocket implementation is properly integrated

The code correctly implements websocket status updates through the ParticipationWebsocketService. The component:

  • Injects and uses the websocket service for real-time updates
  • Properly handles submission state changes via updateSubmissionState
  • Updates build queue status and timing information
  • Manages different states (queued, building, failed) appropriately
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for websocket status update implementations
rg -l "websocket.*status.*update" --type ts

# Search for related service implementations
ast-grep --pattern 'class $_ implements $_ {
  $$$
  updateStatus($_, $_) {
    $$$
  }
  $$$
}'

Length of output: 268


Script:

#!/bin/bash
# Let's try a broader search for websocket-related code and status updates
rg -l "websocket" --type ts

# Search for the specific component and its dependencies
rg -l "updating-result.component" --type ts

# Look for the actual implementation of updateSubmissionState
ast-grep --pattern 'updateSubmissionState($_, $_) {
  $$$
}'

# Search for any submission state update patterns
rg "submissionState.*update" --type ts

Length of output: 12954


Script:

#!/bin/bash
# Let's examine the updating-result.component.ts implementation
rg -A 10 "updateSubmissionState" src/main/webapp/app/exercises/shared/result/updating-result.component.ts

# Check for websocket service usage in the component
rg "websocket" src/main/webapp/app/exercises/shared/result/updating-result.component.ts

# Look for participation websocket service implementation
rg -A 10 "class ParticipationWebsocketService" src/main/webapp/app/overview/participation-websocket.service.ts

Length of output: 3019

src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.java (2)

113-114: LGTM!

The initialization of new fields is consistent with the existing pattern and maintains proper encapsulation by using setter methods.


88-93: Verify database migration for new columns.

The addition of new columns requires a database migration script. Please ensure that:

  1. A migration script exists to add these columns
  2. Default values are handled for existing rows
  3. The migration has been tested in a staging environment
✅ Verification successful

Database migration is properly handled

The changes are properly managed through Liquibase migration:

  • Migration script 20241101120000_changelog.xml adds both columns to programming_exercise_build_config table
  • Default values (0) are correctly set for both columns
  • The migration is included in the master changelog
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for database migration files related to the new columns

# Look for migration files that might contain the new column definitions
rg -l "build_duration_seconds|successful_build_count" --type sql

Length of output: 215


Script:

#!/bin/bash
# First, let's find all SQL migration files regardless of their location
fd -e sql

# Then, let's also check for Liquibase/Flyway migration files which might have different extensions
fd -e xml -e yaml -e yml | grep -i "migration\|changelog"

# Additionally, let's check for recent changes in migration-related files
git log -p --since="3 months ago" | grep -A 10 -B 10 "build_duration_seconds\|successful_build_count"

# Let's also check the entity class usage to understand if this is a new class or modification
rg -l "ProgrammingExerciseBuildConfig"

Length of output: 5328

src/test/javascript/spec/component/shared/updating-result.component.spec.ts (1)

7-12: LGTM: Well-organized imports

The new imports are properly grouped and aligned with the testing requirements for build timing and submission states.

src/main/webapp/app/exercises/shared/result/result.component.ts (2)

173-175: LGTM! Proper cleanup of interval.

The cleanup of estimatedDurationInterval prevents memory leaks and follows Angular best practices.


220-220: LGTM! Proper integration of queued state.

The addition of isQueued parameter to evaluateTemplateStatus is consistent with the existing pattern and properly integrates the new queued state handling.

src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java (1)

67-70: LGTM! Consider adding documentation for clarity.

The constants follow the established naming and structural patterns. They align well with the PR's objective of improving build status updates via websocket communication.

Consider adding Javadoc comments to document the purpose and usage context of these constants, similar to other documented constants in this file. Example:

+    /**
+     * Constants for submission processing status updates via websockets.
+     * Used to differentiate between queued and processing states of build jobs.
+     */
     public static final String SUBMISSION_PROCESSING = "/submissionProcessing";

     public static final String SUBMISSION_PROCESSING_TOPIC = "/topic" + SUBMISSION_PROCESSING;

Let's verify the consistent usage of these constants:

✅ Verification successful

Constants are properly used and integrated

The verification shows:

  • The constants are correctly imported and used in ProgrammingMessagingService
  • No hardcoded values found that should be using these constants
  • Websocket configuration properly supports the topic prefix used in SUBMISSION_PROCESSING_TOPIC
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of the new constants in websocket/messaging related code

# Search for direct usage of the constants
echo "Checking direct usage of constants..."
rg "SUBMISSION_PROCESSING[^_]" --type java

# Search for hardcoded values that should use these constants
echo "Checking for potential hardcoded values..."
rg '"/submissionProcessing"' --type java
rg '"/topic/submissionProcessing"' --type java

# Search for related websocket configuration
echo "Checking websocket configuration..."
rg "configureMessageBroker|enableSimpleBroker|setApplicationDestinationPrefixes" --type java

Length of output: 1672

src/main/webapp/app/exercises/shared/result/result.utils.ts (3)

32-36: LGTM! Well-documented enum value addition.

The new IS_QUEUED status is well-placed and properly documented, clearly indicating its purpose for programming exercises.


158-158: LGTM! Backward-compatible parameter addition.

The new isQueued parameter is well-placed and maintains backward compatibility with its default value of false.


221-223: Verify handling of concurrent queue and build states.

While the implementation is correct, please verify the behavior when both isQueued and isBuilding are true. The current implementation will show the queued state, which seems logical, but it would be good to confirm this is the intended behavior.

Let's verify if this edge case is handled consistently across the codebase:

✅ Verification successful

Let me search for more context about the handling of queued and building states.


Let me try a different approach to find the evaluateTemplateStatus function implementation.


Let me try one more search with a different pattern to find the implementation.


The handling of concurrent queue and build states is implemented correctly

The implementation is consistent with the intended behavior. The code explicitly checks isQueued before isBuilding and returns ResultTemplateStatus.IS_QUEUED when a submission is queued, regardless of the build state. This is the correct approach because:

  1. The enum definition shows these are distinct states for programming exercises
  2. The queued state is logically checked first as it represents an earlier stage in the processing pipeline
  3. The implementation ensures a clear, deterministic state display to users
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other places where isQueued and isBuilding are used together
# to ensure consistent handling of concurrent states

# Search for patterns where both flags might be used
rg -A 5 "isQueued.*isBuilding|isBuilding.*isQueued"

# Search for related test cases
rg -A 5 "test.*['\"]queue.*build|test.*['\"]build.*queue"

Length of output: 287030


Script:

#!/bin/bash
# Search for isQueued and isBuilding usage in result.utils.ts and related files
rg -A 5 "isQueued.*isBuilding|isBuilding.*isQueued" src/main/webapp/app/exercises/shared/result/

# Search for the evaluateTemplateStatus function implementation
ast-grep --pattern $'function evaluateTemplateStatus($$$) {
  $$$
}'

Length of output: 1203


Script:

#!/bin/bash
# Search for the evaluateTemplateStatus function and its implementation
rg -A 30 "export function evaluateTemplateStatus" src/main/webapp/app/exercises/shared/result/result.utils.ts

Length of output: 111


Script:

#!/bin/bash
# Search for the evaluateTemplateStatus function with more context
rg -B 5 -A 30 "isQueued\)" src/main/webapp/app/exercises/shared/result/result.utils.ts

# Also search for any ResultTemplateStatus enum definition
rg -A 10 "enum ResultTemplateStatus" src/main/webapp/app/exercises/shared/result/

Length of output: 2795

src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (1)

396-397: LGTM: Comprehensive job timing tracking.

The implementation correctly captures both actual and estimated timing information, providing valuable data for future estimation improvements.

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java (2)

98-100: LGTM: Field declarations follow best practices.

The new fields are appropriately declared as private and their types clearly indicate their purpose in managing build job queues.


132-133: LGTM: Proper initialization in BeforeEach.

The fields are correctly initialized in the setup method using the hazelcastInstance, ensuring clean state for each test.

src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java (1)

97-98: LGTM: Constructor injection follows best practices.

The addition of SharedQueueManagementService as an Optional dependency is well-implemented using constructor injection, which is the recommended approach for dependency injection.

Also applies to: 103-104, 118-118

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: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c9fcc6c and 06b4e01.

📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingMessagingService.java (6 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingMessagingService.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 (5)
src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingMessagingService.java (5)

9-10: LGTM: Clean dependency injection and imports.

The new dependencies are properly injected via constructor injection, and the field is correctly marked as final. The imports are well-organized and follow Java conventions.

Also applies to: 28-28, 55-56, 58-59, 65-65


87-87: LGTM: Updated SubmissionDTO creation with processing state.

The modification correctly implements the new submission state tracking by explicitly setting isProcessing to false for new submissions, aligning with the PR's objective to differentiate between queued and processing states.


159-161: LGTM: Well-structured topic helper method.

The new helper method follows the established pattern for topic generation and maintains consistency with other similar methods in the class.


188-196: LGTM: Well-documented method signature.

The method's documentation clearly describes its purpose and parameters, making it easy to understand and maintain.


198-198: Verify repository method usage.

The repository method findWithProgrammingExerciseWithBuildConfigById eagerly loads the build config. Let's verify if this is necessary and if it could cause N+1 query issues.

✅ Verification successful

Let me gather more information to understand if the build config is actually used after being loaded.


Let me try one more search to find the query definition:


Based on the analysis of the code, I can now generate the final response:

The build config eager loading is necessary in this context

The repository method findWithProgrammingExerciseWithBuildConfigById is used in two critical flows:

  1. In ProgrammingMessagingService for notifying users about submission processing, where the build config is needed for proper message handling
  2. In LocalCIResultProcessingService for processing build results, where the build config is explicitly used for:
    • Updating exercise build duration statistics
    • Processing programming exercise results
    • Handling build notifications
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if build config is actually used in the notification flow
# and look for similar repository methods to ensure consistent usage

# Check if build config is used in the notification flow
rg -A 5 "findWithProgrammingExerciseWithBuildConfigById" --type java

# Look for similar repository methods to compare usage patterns
ast-grep --pattern 'interface $_ extends $_ {
  $$$
  find$_WithBuildConfig$_($_) {
    $$$
  }
  $$$
}'

Length of output: 3172


Script:

#!/bin/bash
# Check how the participation object is used after fetching with build config
rg -B 5 -A 15 "findWithProgrammingExerciseWithBuildConfigById" src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingMessagingService.java

# Check the repository query to understand what's being loaded
rg "@Query.*findWithProgrammingExerciseWithBuildConfigById" --type java -A 5

Length of output: 1740


Script:

#!/bin/bash
# Search for the query definition in repository files
rg -l "findWithProgrammingExerciseWithBuildConfigById" --type java | xargs cat

# Alternative search for the query
fd -e java | xargs grep -l "findWithProgrammingExerciseWithBuildConfigById" | xargs grep -A 10 "findWithProgrammingExerciseWithBuildConfigById"

Length of output: 40468

Copy link

coderabbitai bot commented Nov 18, 2024

Walkthrough

The pull request introduces significant modifications across multiple classes to enhance the management of build job timing information. Key changes include updates to constructors and methods in BuildJobQueueItem, JobTimingInfo, and SubmissionDTO, allowing for more detailed tracking of job processing metrics such as estimated completion dates and durations. New fields and methods are added to various service and repository classes to support these enhancements, along with updates to the frontend components for improved user feedback on job statuses.

Changes

File Change Summary
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildJobQueueItem.java Updated constructors to include estimatedCompletionDate and estimatedDuration in JobTimingInfo.
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/FinishedBuildJobDTO.java Modified ResultDTO.of(Result result) to include additional parameters when creating SubmissionDTO.
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/JobTimingInfo.java Added fields ZonedDateTime estimatedCompletionDate and long estimatedDuration to the JobTimingInfo record.
src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java Updated methods to accommodate the new BuildJobQueueItem constructor and enhanced job timing information handling.
src/main/java/de/tum/cit/aet/artemis/core/config/Constants.java Added new constants SUBMISSION_PROCESSING and SUBMISSION_PROCESSING_TOPIC.
src/main/java/de/tum/cit/aet/artemis/exercise/dto/SubmissionDTO.java Enhanced with new fields for processing state and timing, and modified the constructor and static method of accordingly.
src/main/java/de/tum/cit/aet/artemis/programming/domain/ProgrammingExerciseBuildConfig.java Added properties buildDurationSeconds and successfulBuildCount with corresponding getters and setters.
src/main/java/de/tum/cit/aet/artemis/programming/dto/ResultDTO.java Updated method to create SubmissionDTO with additional parameters.
src/main/java/de/tum/cit/aet/artemis/programming/dto/SubmissionProcessingDTO.java Introduced a new record to encapsulate submission processing data.
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseBuildConfigRepository.java Added method findByProgrammingExerciseIdElseThrow(Long programmingExerciseId) for improved error handling.
src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingSubmissionRepository.java Introduced methods for querying submissions by participation ID and commit hash.
src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingMessagingService.java Enhanced to manage submission notifications with new parameters and methods.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIQueueWebsocketService.java Added dependency on ProgrammingMessagingService and new method for notifying users about build processing.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java Updated processing logic to include new timing information and modified method visibility.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCITriggerService.java Modified triggerBuild method to include estimated duration in JobTimingInfo.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java Introduced methods for estimating queue duration and managing build agents.
src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java Updated method to return SubmissionDTO instead of ProgrammingSubmission.
src/main/java/de/tum/cit/aet/artemis/programming/web/localci/BuildJobQueueResource.java Added endpoint for estimating build job queue duration.
src/main/webapp/app/entities/programming/programming-submission.model.ts Introduced new optional properties for tracking build processing states.
src/main/webapp/app/entities/programming/submission-processing-dto.ts Added a new TypeScript class to encapsulate submission processing data.
src/main/webapp/app/exercises/programming/participate/code-editor-student-container.component.html Added property binding for progress bar display during updates.
src/main/webapp/app/exercises/programming/participate/programming-submission.service.ts Enhanced service with new properties and methods for managing submission states and queue estimates.
src/main/webapp/app/exercises/shared/result/result.component.html Updated to include progress bar and estimated duration display for building results.
src/main/webapp/app/exercises/shared/result/result.component.ts Added new input properties for managing submission states and updating UI based on timing information.
src/main/webapp/app/exercises/shared/result/result.utils.ts Introduced new enumeration value for queued submissions and updated status evaluation logic.
src/main/webapp/app/exercises/shared/result/updating-result.component.html Added new input properties for managing submission states and timing information.
src/main/webapp/app/exercises/shared/result/updating-result.component.ts Enhanced to handle new timing information and submission states effectively.
src/main/webapp/app/overview/submission-result-status.module.ts Updated module imports to include new shared components.
src/main/webapp/i18n/de/editor.json Added new localization entries for build queue status and estimated time.
src/main/webapp/i18n/en/editor.json Added new localization entries for build queue status and estimated time.
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java Enhanced test class to validate timing information for build jobs.
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java Updated tests to reflect new job timing information and added a new test case for build jobs.
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIServiceTest.java Modified tests to accommodate changes in JobTimingInfo instantiation.
src/test/javascript/spec/component/exercises/shared/result.spec.ts Added new test case to verify interval creation on estimated completion date change.
src/test/javascript/spec/component/shared/updating-result.component.spec.ts Enhanced tests to cover new scenarios involving build timing and queue states.
src/test/javascript/spec/helpers/mocks/service/mock-programming-submission.service.ts Added mock methods for testing submission processing.
src/test/javascript/spec/service/programming-submission.service.spec.ts Enhanced tests to cover submission processing events and timing information.

Possibly related PRs

Suggested labels

ready for review, feature, component:integrated code lifecycle

Suggested reviewers

  • BBesrour
  • SimonEntholzer
  • krusche
  • az108
  • JohannesStoehr

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 pmd
src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildJobQueueItem.java

The following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/FinishedBuildJobDTO.java

The following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.

src/main/java/de/tum/cit/aet/artemis/buildagent/dto/JobTimingInfo.java

The following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.

  • 18 others
🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/main/webapp/app/entities/programming/programming-submission.model.ts

Oops! Something went wrong! :(

ESLint: 9.14.0

TypeError: Error while loading rule '@typescript-eslint/no-unused-expressions': Cannot read properties of undefined (reading 'allowShortCircuit')
Occurred while linting /src/main/webapp/app/entities/programming/programming-submission.model.ts
at Object.create (/node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint/lib/rules/no-unused-expressions.js:75:13)
at create (/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unused-expressions.js:28:32)
at Object.create (/node_modules/@typescript-eslint/utils/dist/eslint-utils/RuleCreator.js:31:20)
at createRuleListeners (/node_modules/eslint/lib/linter/linter.js:943:21)
at /node_modules/eslint/lib/linter/linter.js:1068:84
at Array.forEach ()
at runRules (/node_modules/eslint/lib/linter/linter.js:999:34)
at #flatVerifyWithoutProcessors (/node_modules/eslint/lib/linter/linter.js:1911:31)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/node_modules/eslint/lib/linter/linter.js:1992:49)
at Linter._verifyWithFlatConfigArray (/node_modules/eslint/lib/linter/linter.js:2081:21)


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: 2

🧹 Outside diff range and nitpick comments (3)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (3)

176-181: Consider caching the programming exercise.

Loading the exercise from the repository within a finally block could impact performance if called frequently. Consider caching the exercise or moving this logic outside the finally block.

-                if (programmingExerciseParticipation != null && programmingExerciseParticipation.getExercise() == null) {
-                    ProgrammingExercise exercise = programmingExerciseRepository.getProgrammingExerciseWithBuildConfigFromParticipation(programmingExerciseParticipation);
-                    programmingExerciseParticipation.setExercise(exercise);
-                    programmingExerciseParticipation.setProgrammingExercise(exercise);
-                }
+                if (programmingExerciseParticipation != null && programmingExerciseParticipation.getExercise() == null) {
+                    // Cache the exercise to avoid repeated database calls
+                    programmingExerciseParticipation.setProgrammingExercise(
+                        Optional.ofNullable(programmingExerciseParticipation.getProgrammingExercise())
+                            .orElseGet(() -> programmingExerciseRepository.getProgrammingExerciseWithBuildConfigFromParticipation(programmingExerciseParticipation))
+                    );
+                    programmingExerciseParticipation.setExercise(programmingExerciseParticipation.getProgrammingExercise());
+                }

61-61: Add documentation for the BUILD_STATISTICS_UPDATE_THRESHOLD constant.

Add a Javadoc comment explaining the purpose and impact of this threshold value.

+    /**
+     * The minimum number of new successful builds required before updating build statistics.
+     * This helps reduce database load by limiting update frequency.
+     */
     private static final int BUILD_STATISTICS_UPDATE_THRESHOLD = 10;

295-302: Simplify the boolean logic for update condition.

The current boolean expressions can be simplified for better readability.

-            boolean hasSuccessfulBuildJobs = successfulBuildJobCountByExerciseId > 0;
-            boolean exceedsUpdateThreshold = buildStatistics == null
-                    || successfulBuildJobCountByExerciseId - buildStatistics.getBuildCountWhenUpdated() >= BUILD_STATISTICS_UPDATE_THRESHOLD;
-
-            boolean shouldUpdate = hasSuccessfulBuildJobs && exceedsUpdateThreshold;
-            if (!shouldUpdate) {
-                return;
-            }
+            if (successfulBuildJobCountByExerciseId == 0) {
+                return;
+            }
+            
+            if (buildStatistics != null && 
+                successfulBuildJobCountByExerciseId - buildStatistics.getBuildCountWhenUpdated() < BUILD_STATISTICS_UPDATE_THRESHOLD) {
+                return;
+            }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 65db0c7 and bf61b8c.

📒 Files selected for processing (4)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (10 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java (5 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java
🧰 Additional context used
📓 Path-based instructions (3)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.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/web/ProgrammingExerciseParticipationResource.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/icl/LocalCIResourceIntegrationTest.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 (6)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIResultProcessingService.java (2)

61-64: LGTM! Clean dependency injection and constant definitions.

The changes follow the coding guidelines for constructor injection and constant naming conventions.

Also applies to: 77-78, 93-94, 103-103


Line range hint 275-284: LGTM! Good encapsulation.

The change to private visibility aligns with the least access principle from the coding guidelines.

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (2)

87-89: Previous feedback about TestClock usage still applies.

Also applies to: 284-284


376-408: 🛠️ Refactor suggestion

Enhance test documentation and coverage.

The test implementation aligns well with the PR objectives for queue duration estimation, but could benefit from:

  1. Clear documentation explaining the test scenario and expectations
  2. Helper methods for test data setup
  3. Additional test cases for edge scenarios

Consider this improved structure:

     @Test
     @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER")
+    // Test that queue duration estimation considers:
+    // - Currently processing jobs (2 jobs, 24s each)
+    // - Queued jobs before the target job
+    // Expected: Target job (job4) should start after ~48s (2 processing jobs * 24s)
     void testBuildJob() throws Exception {
+        // Given: A build agent processing 2 jobs and 3 queued jobs
         var now = ZonedDateTime.now();
-        JobTimingInfo jobTimingInfo1 = new JobTimingInfo(now, now, null, now.plusSeconds(24), 24);
+        var jobs = createTestJobs(now);
+        setupBuildAgent(jobs);
 
-        // ... (current setup code)
+        // When: Estimating queue duration for job4
         var queueDurationEstimation = sharedQueueManagementService.getBuildJobEstimatedQueueDuration(job4.participationId());
 
+        // Then: Expected start time should be after current jobs finish
         assertThat(queueDurationEstimation).isCloseTo(now.plusSeconds(48), within(1, ChronoUnit.SECONDS));
     }
+
+    private List<BuildJobQueueItem> createTestJobs(ZonedDateTime baseTime) {
+        // Helper method to create test jobs with timing info
+    }
+
+    private void setupBuildAgent(List<BuildJobQueueItem> jobs) {
+        // Helper method to setup build agent state
+    }

Additionally, consider adding test cases for:

  • Empty queue scenarios
  • Maximum queue capacity scenarios
  • Multiple build agents with different processing states

Likely invalid or redundant comment.

src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java (2)

98-99: LGTM! Constructor injection and immutability properly implemented.

The changes follow best practices by:

  • Using constructor injection for dependency management
  • Using Optional for the optional service
  • Maintaining immutability with final field

Also applies to: 104-105, 119-119


226-240: LGTM! Proper null handling and clean DTO transformation.

The code:

  • Properly handles null cases for Optional
  • Correctly checks buildTimingInfo for null before accessing
  • Cleanly transforms to DTO without unnecessary references

Also applies to: 246-250

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 26, 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: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bf61b8c and 1c0469b.

⛔ Files ignored due to path filters (1)
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.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 (5)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java (5)

391-411: LGTM! Well-structured listener implementation

The BuildAgentListener implementation properly handles all agent lifecycle events and maintains the build agent capacity.


425-435: LGTM! Well-implemented submission processing check

The implementation properly handles the processing status check and uses Java records effectively for immutable data transfer.


79-81: ⚠️ Potential issue

Ensure thread safety for shared state

The fields buildAgentsCapacity and runningBuildJobCount are accessed from multiple threads through the BuildAgentListener. They should be made thread-safe.

Apply this diff to make the fields thread-safe:

-    private int buildAgentsCapacity;
-    private int runningBuildJobCount;
+    private final AtomicInteger buildAgentsCapacity = new AtomicInteger();
+    private final AtomicInteger runningBuildJobCount = new AtomicInteger();

335-336: ⚠️ Potential issue

Update Java version compatibility for takeWhile

The use of takeWhile requires Java 9 or higher.

Apply this diff for better compatibility:

-        List<BuildJobQueueItem> jobsQueuedBefore = queue.stream().sorted(new LocalCIPriorityQueueComparator()).takeWhile(job -> !job.id().equals(buildJobId)).toList();
+        List<BuildJobQueueItem> sortedQueue = queue.stream()
+                .sorted(new LocalCIPriorityQueueComparator())
+                .collect(Collectors.toList());
+        List<BuildJobQueueItem> jobsQueuedBefore = new ArrayList<>();
+        for (BuildJobQueueItem job : sortedQueue) {
+            if (job.id().equals(buildJobId)) {
+                break;
+            }
+            jobsQueuedBefore.add(job);
+        }

364-364: ⚠️ Potential issue

Update Java version compatibility for getLast()

The getLast() method was introduced in Java 21.

Apply this diff for better compatibility:

-        return participationBuildJobIds.getLast();
+        return participationBuildJobIds.get(participationBuildJobIds.size() - 1);

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 28, 2024
…-build-notification

# Conflicts:
#	src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java
#	src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIQueueWebsocketService.java
#	src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java
#	src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java
coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 1, 2024
Copy link
Contributor

@iyannsch iyannsch left a comment

Choose a reason for hiding this comment

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

Wow that's some extensive changes, good job! I've left a couple of review comments but really like the code quality overall 🚀

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: 0

🧹 Outside diff range and nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java (1)

338-343: Improve method documentation.

The method documentation should include:

  1. How the estimation is calculated
  2. Edge cases and assumptions
  3. Return value interpretation

Apply this diff:

     /**
-     * Estimates how long the job will be queued for on the participation ID.
+     * Estimates when a build job will start processing based on:
+     * - Current queue position
+     * - Build agent capacity
+     * - Processing time of jobs ahead in queue
      *
      * @param participationId the ID of the participation for which the queue release date is estimated
-     * @return the estimated queue release date as a {@link ZonedDateTime}
+     * @return {@link ZonedDateTime} representing the estimated start time. Returns current time if:
+     *         - Queue is empty
+     *         - Sufficient build agents are available
+     *         - No queued job found for the participation
      */
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 7b86c54 and 6640a0e.

📒 Files selected for processing (3)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java (5 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/web/localci/BuildJobQueueResource.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/programming/web/localci/BuildJobQueueResource.java
🧰 Additional context used
📓 Path-based instructions (2)
src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.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

src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.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/service/localci/SharedQueueManagementService.java (6)

387-397: LGTM!

The implementation efficiently calculates the next job's queue duration using a priority queue.


411-431: LGTM!

The listener implementation correctly handles build agent lifecycle events and updates capacity accordingly.


355-355: ⚠️ Potential issue

Ensure Java version compatibility when using takeWhile.

The use of takeWhile requires Java 9 or higher.


379-385: ⚠️ Potential issue

Update Java version compatibility for List.getLast().

The getLast() method was introduced in Java 21.


433-436: ⚠️ Potential issue

Ensure atomic updates and improve method name.

  1. Use atomic operations for thread safety
  2. Rename method to better reflect its purpose

79-81: ⚠️ Potential issue

Use AtomicInteger for thread-safe field access.

The fields are accessed from multiple threads via Hazelcast listeners. Use AtomicInteger to ensure thread safety.

Apply this diff:

-    private int buildAgentsCapacity;
-    private int runningBuildJobCount;
+    private final AtomicInteger buildAgentsCapacity = new AtomicInteger();
+    private final AtomicInteger runningBuildJobCount = new AtomicInteger();

Likely invalid or redundant comment.

src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java (2)

395-427: Enhance test documentation and structure.

While the test implementation is correct, it could benefit from:

  1. Clear documentation explaining the test scenario
  2. Helper methods for test data setup
  3. More flexible assertion tolerance

87-89: 🛠️ Refactor suggestion

Consider using relative time differences for more robust tests.

Using hardcoded time values can make tests brittle.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 3, 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: 0

🧹 Outside diff range and nitpick comments (2)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java (2)

413-433: Enhance logging for better observability.

Consider adding more detailed logging:

  1. Include the delta in capacity changes
  2. Log the new total capacity after updates
     @Override
     public void entryAdded(com.hazelcast.core.EntryEvent<String, BuildAgentInformation> event) {
-        log.debug("Build agent added: {}", event.getValue());
+        var agent = event.getValue();
+        log.debug("Build agent added: {}. Capacity: +{}", agent.buildAgent().name(), 
+            agent.maxNumberOfConcurrentBuildJobs());
         updateBuildAgentCapacity();
     }

435-438: Optimize capacity calculation performance.

The current implementation makes two separate passes over the build agent information. Consider combining the calculations:

     private void updateBuildAgentCapacity() {
-        buildAgentsCapacity = getBuildAgentInformation().stream().mapToInt(BuildAgentInformation::maxNumberOfConcurrentBuildJobs).sum();
-        runningBuildJobCount = getBuildAgentInformation().stream().mapToInt(BuildAgentInformation::numberOfCurrentBuildJobs).sum();
+        var agents = getBuildAgentInformation();
+        buildAgentsCapacity = agents.stream().mapToInt(BuildAgentInformation::maxNumberOfConcurrentBuildJobs).sum();
+        runningBuildJobCount = agents.stream().mapToInt(BuildAgentInformation::numberOfCurrentBuildJobs).sum();
     }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 6640a0e and 778cdfc.

📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.java (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/SharedQueueManagementService.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/service/localci/SharedQueueManagementService.java (3)

101-102: LGTM! Proper initialization sequence.

The initialization sequence correctly sets up the BuildAgentListener and updates the initial capacity.


447-457: LGTM! Clean implementation of submission processing check.

The implementation correctly uses Java records and provides clear timing information.


344-379: 🛠️ Refactor suggestion

Consider edge cases in queue estimation logic.

The estimation logic assumes that all jobs have valid timing information. Consider handling these edge cases:

  1. When jobTimingInfo().estimatedDuration() returns null or 0
  2. When multiple jobs have the same participationId but different priorities

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
buildagent Pull requests that affect the corresponding module client Pull requests that update TypeScript code. (Added Automatically!) core Pull requests that affect the corresponding module database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. exercise Pull requests that affect the corresponding module programming Pull requests that affect the corresponding module ready for review server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

8 participants