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

Iris: Proactive Event System #9558

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

Conversation

kaancayli
Copy link
Contributor

@kaancayli kaancayli commented Oct 21, 2024

⚠️ Contains Database Migration - Only deploy to 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 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 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.

Motivation and Context

Implements the feature proposal described in #8800

Description

  • Added a new proactivity feature to Iris
  • Added PyrisEventService that dispatches the detected events to their handler methods
  • Added eventVariant to pipeline execution parameters
  • Defined 3 event types Iris can react to (jol, build_failed, progress_stalled)
  • Build failed event gets triggered when the a submission fails to build
  • Progress stalled event is triggered, when the student's score is not increasing after at least 3 subsequent submissions
  • Added proactivity settings in Iris chat settings for the new proactivity feature
  • Added event payloads to pipeline execution DTOs

Steps for Testing

Prerequisites:

  1. Log in to Artemis

  2. Navigate to the programming exercise with Iris enabled

  3. Make sure the proactive event options under Iris Chat Settings are enabled in all levels:

    • Global
    • Course
    • Exercise
  4. Testing events:

    1. Build failed event:

      • Make a programming exercise submission with a failing build
      • Verify that Iris reacted and sent a proactive message related to the error
    2. Progress stalled event:

      • Make 3 consequent programming exercise submissions
      • Make sure the scores after each submission are not increasing (e.g., you can submit the initial repository 3 times)
      • Verify that Iris reacted and sent a proactive message related to the error

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

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Client

Class/File Line Coverage Confirmation (assert/expect)
iris-sub-settings.model.ts 100%
exercise-chatbot-button.component.ts 87.3%
iris-chat.service.ts 89.04%
iris-common-sub-settings-update.component.ts 88.88%

Server

Class/File Line Coverage Confirmation (assert/expect)
IrisCourseSettings.java 100%
IrisExerciseSettings.java 94%
IrisGlobalSettings.java 100%
IrisSettings.java 100%
IrisSubSettings.java 100%
IrisSubSettingsType.java 100%
IrisCombinedSettingsDTO.java 100%
IrisSettingsRepository.java 100%
IrisCompetencyGenerationService.java 82%
PyrisConnectorService.java 79%
PyrisEventService.java 100%
PyrisPipelineService.java 80%
PyrisEventDTO.java 100%
PyrisCourseChatPipelineExecutionDTO.java 100%
NewResultEvent.java 100%
PyrisEvent.java 100%
IrisCourseChatSessionService.java 68%
IrisExerciseChatSessionService.java 91%
IrisTextExerciseChatSessionService.java 86%
IrisSettingsService.java 91%
IrisSubSettingsService.java 91%
IrisExerciseChatSessionResource.java 91%

Screenshots

Proactivity Settings

Screenshot 2024-11-21 at 23 41 00
Screenshot 2024-11-21 at 23 31 23

Proactive responses

ScreenRecording2024-11-21at23 37 59-ezgif com-video-to-gif-converter

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new event handling system with IrisEventType for proactive event management.
    • Added methods for managing proactive settings in the chat interface, allowing users to enable or disable specific events.
    • Enhanced the IrisExerciseChatSessionService and IrisCourseChatSessionService to handle new event types and improve chat session management.
    • Added new methods to the ProgrammingExerciseRepository for retrieving comprehensive data related to programming exercises.
    • Implemented a new PyrisEventService for managing events within the Iris application.
    • Introduced new exception classes for better error handling during event processing.
    • Enhanced the IrisChatSubSettings to manage disabledProactiveEvents and integrated these settings into the UI.
    • Added a new message bubble feature in the chatbot interface for improved user interaction.
  • Bug Fixes

    • Improved error handling for unsupported events and refined logging for better traceability.
  • Documentation

    • Updated documentation to reflect new settings and event handling capabilities.
  • Style

    • Enhanced UI elements for the chatbot interface, including new CSS styles for message bubbles and improved animations.
  • Tests

    • Expanded test coverage for new features, including proactive event settings and chat session management.
    • Added tests for the new event handling logic and proactive settings updates.

@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. atlas Pull requests that affect the corresponding module core Pull requests that affect the corresponding module exercise Pull requests that affect the corresponding module iris Pull requests that affect the corresponding module programming Pull requests that affect the corresponding module labels Oct 21, 2024
Copy link

There hasn't been any activity on this pull request recently. Therefore, this pull request has been automatically marked as stale and will be closed if no further activity occurs within seven days. Thank you for your contributions.

@github-actions github-actions bot removed the stale label Nov 5, 2024
sebastianloose
sebastianloose previously approved these changes Nov 29, 2024
Copy link
Contributor

@sebastianloose sebastianloose left a comment

Choose a reason for hiding this comment

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

The code looks good to me! I tested on TS3 and everything worked as expected

Copy link

⚠️ Unable to deploy to test servers ⚠️

Testserver "artemis-test3.artemis.cit.tum.de" is already in use by PR #9898.

@github-actions github-actions bot added the deployment-error Added by deployment workflows if an error occured label Nov 29, 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 (1)
src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisExerciseChatSessionService.java (1)

214-252: Simplify complex conditional logic in onNewResult

The method contains nested conditions and multiple responsibility branches. Consider extracting the score analysis logic.

Extract the score analysis logic into a separate method:

+    private void handleProgressStallCheck(ProgrammingExerciseStudentParticipation participation, List<Submission> submissions) {
+        var successfulSubmission = submissions.stream()
+                .anyMatch(submission -> submission.getLatestResult() != null && 
+                         submission.getLatestResult().getScore() == getSuccessThreshold());
+                         
+        if (!successfulSubmission && submissions.size() >= 3) {
+            processNonSuccessfulSubmissions(participation, submissions);
+        }
+    }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 31151e3 and f8952bb.

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

264-296: LGTM! Well-structured helper methods

The implementation is clean, well-documented, and includes proper input validation. The methods follow single responsibility principle and have clear, focused logic.


328-328: Add JavaDoc for createSession method

The method is missing JavaDoc documentation.

Add JavaDoc similar to other methods in the class:

/**
 * Creates a new Iris session for the given exercise and user.
 * Validates user acceptance and authorization before creating the session.
 *
 * @param exercise           The exercise the session belongs to
 * @param user              The user the session belongs to
 * @param sendInitialMessage Whether to send an initial message from Iris
 * @return The created session
 * @throws AccessForbiddenException if the user doesn't have required permissions
 */

307-354: LGTM! Well-implemented session management

The session management methods are well-structured with proper validation, error handling, and async operations where needed.


79-82: 🛠️ Refactor suggestion

Externalize configuration constants

The SUCCESS_THRESHOLD and INTERVAL_SIZE are hardcoded with TODO comments. These should be moved to the Iris settings for better configurability.

Consider moving these values to the Iris settings configuration:

-    private final double SUCCESS_THRESHOLD = 100.0; // TODO: Retrieve configuration from Iris settings
-    private final int INTERVAL_SIZE = 3; // TODO: Retrieve configuration from Iris settings
+    private double getSuccessThreshold() {
+        return irisSettingsService.getCombinedIrisSettingsFor(exercise, false).getSuccessThreshold();
+    }
+    private int getIntervalSize() {
+        return irisSettingsService.getCombinedIrisSettingsFor(exercise, false).getIntervalSize();
+    }

186-207: 🛠️ Refactor suggestion

Enhance error handling in onBuildFailure

The async operation should handle potential exceptions to prevent silent failures.

Apply this improvement:

-                CompletableFuture.runAsync(() -> requestAndHandleResponse(session, Optional.of("build_failed")));
+                CompletableFuture.runAsync(() -> {
+                    try {
+                        requestAndHandleResponse(session, Optional.of("build_failed"));
+                    } catch (Exception e) {
+                        log.error("Failed to process build failure event for user {}: {}", user.getName(), e.getMessage(), e);
+                    }
+                });

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 29, 2024
@kaancayli kaancayli removed the deployment-error Added by deployment workflows if an error occured label Nov 29, 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: 2

🧹 Outside diff range and nitpick comments (3)
src/main/webapp/i18n/en/iris.json (1)

98-100: Consider a more descriptive message for chat bubble expansion.

While the message is clear, it could be more descriptive to help users understand what "full message" means.

Consider updating the message to be more specific:

             "chatBubble": {
-                "seeFull": "See full message"
+                "seeFull": "Click to expand full message"
             },
src/test/java/de/tum/cit/aet/artemis/core/connector/IrisRequestMockProvider.java (2)

150-177: Add JavaDoc documentation for the new methods

According to the coding guidelines, all methods should have JavaDoc documentation explaining their purpose, parameters, and expected behavior.

Add JavaDoc for each new method:

/**
 * Mocks a response for the build failed event in the tutor chat pipeline.
 * Allows for a maximum of two expectations.
 *
 * @param responseConsumer Consumer to process the request body
 */
public void mockBuildFailedRunResponse(Consumer<PyrisExerciseChatPipelineExecutionDTO> responseConsumer) {
    // existing implementation
}

/**
 * Mocks a response for the progress stalled event in the tutor chat pipeline.
 * Allows for a maximum of two expectations.
 *
 * @param responseConsumer Consumer to process the request body
 */
public void mockProgressStalledEventRunResponse(Consumer<PyrisCourseChatPipelineExecutionDTO> responseConsumer) {
    // existing implementation
}

/**
 * Mocks a response for the JOL event in the course chat pipeline.
 *
 * @param responseConsumer Consumer to process the request body
 */
public void mockJolEventRunResponse(Consumer<PyrisCourseChatPipelineExecutionDTO> responseConsumer) {
    // existing implementation
}

150-177: Consider refactoring duplicated response handling logic

The response handling logic is duplicated across all mock methods. Consider extracting it into a reusable helper method.

private <T> ResponseCreator createAcceptedResponse(MockClientHttpRequest request, Class<T> dtoClass, Consumer<T> responseConsumer) throws IOException {
    var dto = mapper.readValue(request.getBodyAsString(), dtoClass);
    responseConsumer.accept(dto);
    return MockRestResponseCreators.withRawStatus(HttpStatus.ACCEPTED.value()).createResponse(request);
}

Then use it in the mock methods:

 public void mockBuildFailedRunResponse(Consumer<PyrisExerciseChatPipelineExecutionDTO> responseConsumer) {
     mockServer.expect(ExpectedCount.max(2), requestTo(pipelinesApiURL + "/tutor-chat/default/run?event=build_failed"))
         .andExpect(method(HttpMethod.POST))
-        .andRespond(request -> {
-            var mockRequest = (MockClientHttpRequest) request;
-            var dto = mapper.readValue(mockRequest.getBodyAsString(), PyrisExerciseChatPipelineExecutionDTO.class);
-            responseConsumer.accept(dto);
-            return MockRestResponseCreators.withRawStatus(HttpStatus.ACCEPTED.value()).createResponse(request);
-        });
+        .andRespond(request -> createAcceptedResponse((MockClientHttpRequest) request, 
+            PyrisExerciseChatPipelineExecutionDTO.class, responseConsumer));
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f8952bb and 6d0caeb.

📒 Files selected for processing (5)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisConnectorService.java (3 hunks)
  • src/main/webapp/i18n/de/iris.json (2 hunks)
  • src/main/webapp/i18n/en/iris.json (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/core/connector/IrisRequestMockProvider.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/iris/PyrisConnectorServiceTest.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisConnectorService.java
  • src/test/java/de/tum/cit/aet/artemis/iris/PyrisConnectorServiceTest.java
🧰 Additional context used
📓 Path-based instructions (2)
src/main/webapp/i18n/de/iris.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/core/connector/IrisRequestMockProvider.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/webapp/i18n/en/iris.json (2)

35-42: LGTM! But JOL event settings are still missing.

The proactivity event settings for build failures and progress stalling are well-defined with clear labels and tooltips.

As noted in previous reviews, the JOL (Judgment of Learning) event settings are still missing from this configuration.


43-47: LGTM! Clear and informative proactivity settings.

The proactivity settings section provides clear context and explanations for the feature's behavior, including inheritance rules.

src/main/webapp/i18n/de/iris.json (3)

35-38: Make translations more informal and personal (dutzen)

The translations should use informal language (dutzen) as per coding guidelines.

                    "proactivityBuildFailedEventEnabled": {
-                        "label": "Build-Fehler überwachen",
-                        "tooltip": "Wenn aktiviert, wird Iris proaktiv Hilfe-Nachrichten senden, wenn der Build einer Abbgabe fehlschlägt."
+                        "label": "Deine Build-Fehler überwachen",
+                        "tooltip": "Wenn du dies aktivierst, sendet dir Iris proaktiv Hilfe-Nachrichten, wenn dein Build fehlschlägt."
                    },

39-42: Make translations more informal and personal (dutzen)

The translations should use informal language (dutzen) as per coding guidelines.

                    "proactivityProgressStalledEventEnabled": {
-                        "label": "Übungsleistung überwachen",
-                        "tooltip": "Wenn aktiviert, wird Iris proaktiv Hilfe-Nachrichten senden, wenn sich die Übungsleistung des Studenten nicht verbessert."
+                        "label": "Deinen Lernfortschritt überwachen",
+                        "tooltip": "Wenn du dies aktivierst, sendet dir Iris proaktiv Hilfe-Nachrichten, wenn sich deine Übungsleistung nicht verbessert."
                    },

98-100: Chat bubble translation is acceptable

The current translation uses an imperative form which is neither strictly formal nor informal. While it could be made more informal as suggested in past reviews, the current form is acceptable for this context.

src/test/java/de/tum/cit/aet/artemis/core/connector/IrisRequestMockProvider.java (1)

150-168: Verify the ExpectedCount.max(2) usage

Both mockBuildFailedRunResponse and mockProgressStalledEventRunResponse use ExpectedCount.max(2) while other methods use ExpectedCount.once(). Please verify if this is intentional.

✅ Verification successful

Let me check the test file that uses these mock methods to understand the usage pattern.


ExpectedCount.max(2) is appropriate for these event handlers

The usage of ExpectedCount.max(2) in both mockBuildFailedRunResponse and mockProgressStalledEventRunResponse is correct. The test cases show that these mocks are used in scenarios where:

  1. The main test case verifies the event firing (testShouldFireProgressStalledEvent, testShouldFireBuildFailedEvent)
  2. Additional test cases verify when these events should not fire (testShouldShouldNotFireProgressStalledEventWithExistingSuccessfulSubmission)

Setting max(2) allows the mock to be used across multiple test methods while ensuring the mock expectations aren't too strict, which is appropriate for event-based testing scenarios.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for test cases that use these mock methods to understand the expected count

# Search for test files using these methods
rg -l "mockBuildFailedRunResponse|mockProgressStalledEventRunResponse" --type java

# Search for ExpectedCount usage patterns in test files
rg "ExpectedCount\." --type java

Length of output: 7320


Script:

#!/bin/bash
# Get the content of the test file that uses these mock methods
rg -A 10 -B 10 "mockBuildFailedRunResponse|mockProgressStalledEventRunResponse" src/test/java/de/tum/cit/aet/artemis/iris/PyrisEventSystemTest.java

Length of output: 3586

src/main/webapp/i18n/de/iris.json Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
atlas 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 iris 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