Skip to content

Conversation

jo-elimu
Copy link
Member

Issue Number

Purpose

Technical Details

Testing Instructions

Screenshots


Format Checks

Note

Files in PRs are automatically checked for format violations with mvn spotless:check.

If this PR contains files with format violations, run mvn spotless:apply to fix them.

@jo-elimu jo-elimu self-assigned this Jun 20, 2025
@jo-elimu jo-elimu requested a review from a team as a code owner June 20, 2025 08:04
@jo-elimu jo-elimu removed the request for review from a team June 20, 2025 08:04
@jo-elimu jo-elimu linked an issue Jun 20, 2025 that may be closed by this pull request
Copy link

codecov bot commented Jun 20, 2025

Codecov Report

Attention: Patch coverage is 0.59701% with 333 lines in your changes missing coverage. Please review.

Project coverage is 16.72%. Comparing base (2cc471c) to head (be55297).
Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
...ics/LetterSoundAssessmentEventImportScheduler.java 0.00% 41 Missing ⚠️
...ytics/LetterSoundLearningEventImportScheduler.java 0.00% 41 Missing ⚠️
.../analytics/NumberLearningEventImportScheduler.java 0.00% 41 Missing ⚠️
...alytics/StoryBookLearningEventImportScheduler.java 0.00% 41 Missing ⚠️
...s/analytics/VideoLearningEventImportScheduler.java 0.00% 41 Missing ⚠️
.../analytics/WordAssessmentEventImportScheduler.java 0.00% 41 Missing ⚠️
...ks/analytics/WordLearningEventImportScheduler.java 0.00% 41 Missing ⚠️
...udents/VideoLearningEventsCsvExportController.java 0.00% 7 Missing ⚠️
...ts/StoryBookLearningEventsCsvExportController.java 0.00% 6 Missing ⚠️
...tudents/WordLearningEventsCsvExportController.java 0.00% 6 Missing ⚠️
... and 8 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #2270      +/-   ##
============================================
+ Coverage     16.23%   16.72%   +0.49%     
- Complexity      434      444      +10     
============================================
  Files           252      252              
  Lines          7276     7324      +48     
  Branches        813      815       +2     
============================================
+ Hits           1181     1225      +44     
- Misses         6031     6044      +13     
+ Partials         64       55       -9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

coderabbitai bot commented Jun 20, 2025

## Walkthrough

The changes update several CSV export controllers to add "research_experiment" and "experiment_group" columns to CSV outputs for various student analytics events. Column order and headers are adjusted accordingly. Minor code formatting improvements and import cleanups are also made. No changes to public method signatures or control flow are introduced. Additionally, import cleanup and enhanced error handling with Discord notifications were added to analytics import schedulers.

## Changes

| File(s) | Change Summary |
|---------|---------------|
| pom-dependency-tree.txt | Updated project artifact version from `2.6.65-SNAPSHOT` to `2.6.66-SNAPSHOT`. |
| src/main/java/ai/elimu/web/analytics/students/LetterSoundAssessmentEventsCsvExportController.java<br>src/main/java/ai/elimu/web/analytics/students/WordAssessmentEventsCsvExportController.java | Added "research_experiment" and "experiment_group" columns to CSV export; updated record output to include enum ordinals. |
| src/main/java/ai/elimu/web/analytics/students/LetterSoundLearningEventsCsvExportController.java | Added "additional_data", "research_experiment", and "experiment_group" columns to CSV export; adjusted header and record order; removed duplicate "additional_data". |
| src/main/java/ai/elimu/web/analytics/students/NumberLearningEventsCsvExportController.java | Reordered CSV columns; added "research_experiment" and "experiment_group"; removed duplicate "learning_event_type". |
| src/main/java/ai/elimu/web/analytics/students/StoryBookLearningEventsCsvExportController.java<br>src/main/java/ai/elimu/web/analytics/students/VideoLearningEventsCsvExportController.java<br>src/main/java/ai/elimu/web/analytics/students/WordLearningEventsCsvExportController.java | Reordered and expanded CSV columns to include "research_experiment" and "experiment_group"; updated record output accordingly; moved CSV flush outside loop in VideoLearningEventsCsvExportController. |
| src/main/java/ai/elimu/web/analytics/students/StudentListController.java | Removed unused imports; no logic changes. |
| src/main/java/ai/elimu/web/analytics/students/StudentsCsvExportController.java | Code formatting: removed blank lines, compacted builder call; no logic changes. |
| src/main/java/ai/elimu/web/context/EnvironmentContextLoaderListener.java | Removed environment check for setting "discord.webhook.url"; added unconditional setting of "discord.analytics.webhook.url". |
| src/main/java/ai/elimu/rest/v2/applications/ApplicationVersionsRestController.java | Added Discord notifications on success or failure of publishing new application versions. |
| src/main/java/ai/elimu/tasks/analytics/*ImportScheduler.java (all) | Wrapped CSV import processing in try-catch blocks to log errors and send Discord error notifications on exceptions. |
| src/main/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelper.java | Added formatting changes and TODO comment for number assessment events; no functional changes. |
| src/test/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelperTest.java | Reordered test method for video learning events; added TODO comments for planned tests; no logic changes. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant Controller
    participant Event
    participant Response

    User->>Controller: Request CSV export
    Controller->>Event: Fetch event data
    Event-->>Controller: Return event list
    Controller->>Controller: Build CSV with new columns ("research_experiment", "experiment_group")
    Controller->>Response: Write CSV output

Assessment against linked issues

Objective Addressed Explanation
Add "research_experiment" and "experiment_group" fields to analytics CSV exports (#2260)
Add export support for research experiment group comparison (#2260)
Add relevant fields to all student analytics event CSV exports (#2260)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Unconditional setting of "discord.webhook.url" and addition of "discord.analytics.webhook.url" in EnvironmentContextLoaderListener.java This change relates to environment property loading and Discord webhook configuration, which is unrelated to adding research experiment fields to analytics CSV exports.
Addition of Discord notifications on application version publishing in ApplicationVersionsRestController.java This feature is unrelated to research experiment CSV export enhancements.
Addition of try-catch blocks with Discord error notifications in analytics import schedulers (various *ImportScheduler.java files) These changes improve error handling and notification but are unrelated to the research experiment CSV export requirements.
Formatting and TODO comments in CsvAnalyticsExtractionHelper.java and CsvAnalyticsExtractionHelperTest.java These are non-functional changes and placeholders unrelated to the issue objectives.

Possibly related PRs

Suggested reviewers

  • AshishBagdane
  • nya-elimu
  • tomaszsmy


<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=elimu-ai/webapp&utm_content=2270):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `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 explain this code block.`
  -	`@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 explain its main purpose.`
  - `@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.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

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 generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this 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` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link
Contributor

@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: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fea728f and 7d62069.

📒 Files selected for processing (10)
  • pom-dependency-tree.txt (1 hunks)
  • src/main/java/ai/elimu/web/analytics/students/LetterSoundAssessmentEventsCsvExportController.java (1 hunks)
  • src/main/java/ai/elimu/web/analytics/students/LetterSoundLearningEventsCsvExportController.java (1 hunks)
  • src/main/java/ai/elimu/web/analytics/students/NumberLearningEventsCsvExportController.java (1 hunks)
  • src/main/java/ai/elimu/web/analytics/students/StoryBookLearningEventsCsvExportController.java (1 hunks)
  • src/main/java/ai/elimu/web/analytics/students/StudentListController.java (0 hunks)
  • src/main/java/ai/elimu/web/analytics/students/StudentsCsvExportController.java (1 hunks)
  • src/main/java/ai/elimu/web/analytics/students/VideoLearningEventsCsvExportController.java (1 hunks)
  • src/main/java/ai/elimu/web/analytics/students/WordAssessmentEventsCsvExportController.java (1 hunks)
  • src/main/java/ai/elimu/web/analytics/students/WordLearningEventsCsvExportController.java (1 hunks)
💤 Files with no reviewable changes (1)
  • src/main/java/ai/elimu/web/analytics/students/StudentListController.java
⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: test_rest
  • GitHub Check: build (macos-latest, 21)
  • GitHub Check: build (macos-latest, 17)
  • GitHub Check: build (ubuntu-latest, 21)
  • GitHub Check: build (windows-latest, 17)
  • GitHub Check: build (ubuntu-latest, 17)
  • GitHub Check: build (windows-latest, 21)
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
🔇 Additional comments (17)
src/main/java/ai/elimu/web/analytics/students/NumberLearningEventsCsvExportController.java (3)

46-57: LGTM! Header structure is correctly updated.

The CSV header modifications are well-structured:

  • Duplicate "learning_event_type" column removed
  • New research experiment columns added in logical positions
  • Column ordering is consistent and clear

62-73: Data printing order correctly matches header structure.

The printRecord call maintains perfect alignment with the CSV header, ensuring data integrity in the exported file.


68-69: Verify null safety for enum ordinal calls.

The data printing order correctly matches the header structure. However, ensure that getResearchExperiment() and getExperimentGroup() cannot return null values, as calling .ordinal() on null will throw a NullPointerException.

#!/bin/bash
# Description: Check if ResearchExperiment and ExperimentGroup fields can be null
# Expected: Find field declarations and annotations to verify nullability

# Search for field declarations in NumberLearningEvent entity
ast-grep --pattern 'class NumberLearningEvent {
  $$$
  private $_ researchExperiment;
  $$$
}'

# Search for getter method annotations
rg -A 3 -B 1 "getResearchExperiment|getExperimentGroup" --type java

# Look for nullable annotations or validation constraints
rg "@(Nullable|NotNull|Column)" --type java -A 2 -B 2 | rg -A 5 -B 5 "(researchExperiment|experimentGroup)"
src/main/java/ai/elimu/web/analytics/students/WordAssessmentEventsCsvExportController.java (2)

53-54: LGTM! Header columns added correctly.

The new experimental metadata columns are appropriately positioned and follow consistent naming conventions.


57-57: Good formatting improvement.

Moving .build() to a new line improves readability of the CSVFormat configuration.

src/main/java/ai/elimu/web/analytics/students/WordLearningEventsCsvExportController.java (2)

51-56: LGTM! Header order updated correctly.

The CSV headers have been properly updated to include the new research experiment fields in the correct order.


65-70: Verify data order alignment with headers.

Please ensure that all similar CSV export controllers across the codebase maintain consistent column ordering for the new research experiment fields.

#!/bin/bash
# Description: Verify consistent header ordering across all CSV export controllers
# Expected: All controllers should have the same column order for research experiment fields

# Search for CSV headers containing research_experiment
rg -A 10 -B 5 'research_experiment' --type java
src/main/java/ai/elimu/web/analytics/students/StoryBookLearningEventsCsvExportController.java (1)

55-60: CSV header update looks good.

The new research experiment fields are properly positioned and maintain consistency with the data output order.

src/main/java/ai/elimu/web/analytics/students/VideoLearningEventsCsvExportController.java (3)

56-61: LGTM: Header structure looks correct.

The CSV header has been properly updated to include the new research experiment columns. The column order and alignment with the data records appears consistent.


78-78: Excellent performance optimization!

Moving csvPrinter.flush() outside the loop improves performance by reducing I/O operations. This avoids flushing after each record and instead flushes once after all records are written.


71-76: ```shell
#!/bin/bash

Locate the LearningEvent Java source file

rg -l "class LearningEvent" -t java

Show class declaration with context

rg -n -C5 "class LearningEvent" -t java

Inspect declarations of researchExperiment and experimentGroup

rg -n -C5 "researchExperiment" -t java
rg -n -C5 "experimentGroup" -t java


</details>
<details>
<summary>pom-dependency-tree.txt (1)</summary>

`1-1`: **Version update looks good.**

The project version increment from `2.6.65-SNAPSHOT` to `2.6.66-SNAPSHOT` appropriately reflects the feature enhancement to include research experiment data in CSV exports.

</details>
<details>
<summary>src/main/java/ai/elimu/web/analytics/students/StudentsCsvExportController.java (1)</summary>

`44-44`: **Good formatting cleanup.**

Removing the extra blank line improves code consistency and readability.

</details>
<details>
<summary>src/main/java/ai/elimu/web/analytics/students/LetterSoundAssessmentEventsCsvExportController.java (2)</summary>

`53-54`: **Research experiment columns added successfully.**

The new CSV headers "research_experiment" and "experiment_group" align with the PR objective to include research experiment data in CSV exports.

---

`70-71`: **Verify null safety for enum ordinal calls.**

The `.ordinal()` calls on `researchExperiment` and `experimentGroup` enums will throw `NullPointerException` if these fields are null. Consider adding null checks or ensure these fields are always populated.

Additionally, using `.ordinal()` exports numeric values instead of readable enum names, which may reduce CSV readability.


```shell
#!/bin/bash
# Verify if ResearchExperiment and ExperimentGroup enums can be null in LetterSoundAssessmentEvent
ast-grep --pattern 'class LetterSoundAssessmentEvent {
  $$$
  ResearchExperiment researchExperiment;
  $$$
}'

ast-grep --pattern 'class LetterSoundAssessmentEvent {
  $$$
  ExperimentGroup experimentGroup;
  $$$
}'

# Also check for any @Nullable annotations or validation
rg -A 3 -B 3 "ResearchExperiment.*researchExperiment"
rg -A 3 -B 3 "ExperimentGroup.*experimentGroup"
src/main/java/ai/elimu/web/analytics/students/LetterSoundLearningEventsCsvExportController.java (2)

50-52: Research experiment columns added with additional data field.

The CSV headers now include "additional_data", "research_experiment", and "experiment_group" which enhances the exported analytics data as required.


65-67: Address null safety and consider column consistency.

Same concern as in the assessment events controller - the .ordinal() calls on enum fields may throw NullPointerException if the fields are null.

Also note that the column ordering differs from LetterSoundAssessmentEventsCsvExportController where "additional_data" appears before the research experiment columns, while here all three are grouped together.

Consider standardizing the column order across all CSV export controllers for consistency:

#!/bin/bash
# Check column ordering consistency across all CSV export controllers
rg -A 10 "setHeader" src/main/java/ai/elimu/web/analytics/students/*CsvExportController.java

# Verify enum null safety for LetterSoundLearningEvent
ast-grep --pattern 'class LetterSoundLearningEvent {
  $$$
  ResearchExperiment researchExperiment;
  $$$
}'

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d62069 and 808c97b.

⛔ Files ignored due to path filters (5)
  • src/main/config/centos-stream-9/opt/jetty-base/webapps/webapp-HIN.xml is excluded by !**/*.xml
  • src/main/config/centos-stream-9/opt/jetty-base/webapps/webapp-TGL.xml is excluded by !**/*.xml
  • src/main/config/centos-stream-9/opt/jetty-base/webapps/webapp-THA.xml is excluded by !**/*.xml
  • src/main/config/centos-stream-9/opt/jetty-base/webapps/webapp-VIE.xml is excluded by !**/*.xml
  • src/main/config/centos-stream-9/opt/jetty-base/webapps/webapp.xml is excluded by !**/*.xml
📒 Files selected for processing (1)
  • src/main/java/ai/elimu/web/context/EnvironmentContextLoaderListener.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: build (windows-latest, 21)
  • GitHub Check: build (ubuntu-latest, 17)
  • GitHub Check: build (windows-latest, 17)
  • GitHub Check: build (macos-latest, 21)
  • GitHub Check: test_rest
  • GitHub Check: build (ubuntu-latest, 21)
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
🔇 Additional comments (1)
src/main/java/ai/elimu/web/context/EnvironmentContextLoaderListener.java (1)

125-126: LGTM - New analytics webhook property aligns with CSV export enhancements.

The addition of the analytics webhook URL property supports the research experiment data tracking mentioned in the PR objectives. This property will likely be used by the updated CSV export controllers to send notifications about analytics data exports.

Copy link
Contributor

@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

♻️ Duplicate comments (3)
src/main/java/ai/elimu/tasks/analytics/WordLearningEventImportScheduler.java (1)

57-117: Consistent error handling pattern with same null safety concerns.

This follows the same excellent error handling pattern as other schedulers in this PR. The same null safety improvements mentioned for StoryBookLearningEventImportScheduler apply here as well.

The listFiles() calls should be null-checked to prevent potential NullPointerExceptions when directories don't exist or aren't accessible.

src/main/java/ai/elimu/tasks/analytics/LetterSoundAssessmentEventImportScheduler.java (1)

57-117: Consistent error handling implementation.

This scheduler follows the same error handling pattern as the other schedulers in this PR, which ensures consistent behavior across all analytics import tasks.

The same null safety considerations for listFiles() calls apply here as mentioned in the other scheduler reviews.

src/main/java/ai/elimu/tasks/analytics/NumberLearningEventImportScheduler.java (1)

54-114: Systematic error handling improvement completed.

This completes the consistent error handling enhancement across all analytics import schedulers. The implementation maintains the same reliable pattern for exception handling and Discord notifications.

The same null safety recommendations for listFiles() operations apply here to prevent potential runtime exceptions when directories are inaccessible.

🧹 Nitpick comments (1)
src/main/java/ai/elimu/tasks/analytics/StoryBookLearningEventImportScheduler.java (1)

57-117: Good error handling addition, but consider null safety improvements.

The try-catch wrapper effectively prevents scheduler crashes and provides Discord notifications for failures. However, consider these improvements:

  1. Null safety for directory operations: listFiles() can return null if the path doesn't exist or isn't a directory.
  2. Exception specificity: Consider catching more specific exceptions rather than generic Exception to avoid masking programming errors.

Apply this diff to improve null safety:

-      for (File analyticsDirFile : analyticsDir.listFiles()) {
+      File[] analyticsFiles = analyticsDir.listFiles();
+      if (analyticsFiles != null) {
+        for (File analyticsDirFile : analyticsFiles) {
           if (analyticsDirFile.getName().startsWith("android-id-")) {
             File androidIdDir = new File(analyticsDir, analyticsDirFile.getName());
-            for (File androidIdDirFile : androidIdDir.listFiles()) {
+            File[] androidIdFiles = androidIdDir.listFiles();
+            if (androidIdFiles != null) {
+              for (File androidIdDirFile : androidIdFiles) {
                 Long studentId = null;
                 Integer eventImportCount = 0;
                 if (androidIdDirFile.getName().equals("storybook-learning-events")) {
                   File storyBookLearningEventsDir = new File(androidIdDir, androidIdDirFile.getName());
-                  for (File csvFile : storyBookLearningEventsDir.listFiles()) {
+                  File[] csvFiles = storyBookLearningEventsDir.listFiles();
+                  if (csvFiles != null) {
+                    for (File csvFile : csvFiles) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0d726e and a4a539e.

📒 Files selected for processing (10)
  • src/main/java/ai/elimu/rest/v2/applications/ApplicationVersionsRestController.java (2 hunks)
  • src/main/java/ai/elimu/tasks/analytics/LetterSoundAssessmentEventImportScheduler.java (1 hunks)
  • src/main/java/ai/elimu/tasks/analytics/LetterSoundLearningEventImportScheduler.java (1 hunks)
  • src/main/java/ai/elimu/tasks/analytics/NumberLearningEventImportScheduler.java (1 hunks)
  • src/main/java/ai/elimu/tasks/analytics/StoryBookLearningEventImportScheduler.java (1 hunks)
  • src/main/java/ai/elimu/tasks/analytics/VideoLearningEventImportScheduler.java (1 hunks)
  • src/main/java/ai/elimu/tasks/analytics/WordAssessmentEventImportScheduler.java (1 hunks)
  • src/main/java/ai/elimu/tasks/analytics/WordLearningEventImportScheduler.java (1 hunks)
  • src/main/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelper.java (4 hunks)
  • src/test/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelperTest.java (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelper.java
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: test_rest
  • GitHub Check: build (ubuntu-latest, 17)
  • GitHub Check: test_rest
  • GitHub Check: build (windows-latest, 21)
  • GitHub Check: build (ubuntu-latest, 21)
  • GitHub Check: build (windows-latest, 17)
  • GitHub Check: build (macos-latest, 17)
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
🔇 Additional comments (11)
src/test/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelperTest.java (2)

23-23: TODO comments align with expanded CSV functionality.

The TODO comments indicate planned test coverage for letter-sound assessment events, number assessment events, and number learning events, which aligns with the PR's objective to enhance CSV export functionality with research experiment data.

Also applies to: 46-46, 48-48


162-184: Test method relocation is appropriate.

Moving the testExtractVideoLearningEvents_v3001018() method to the end of the class improves organization without affecting functionality. The test logic remains unchanged and valid.

src/main/java/ai/elimu/rest/v2/applications/ApplicationVersionsRestController.java (3)

11-13: Proper imports for Discord functionality.

The imports for DiscordHelper, DomainHelper, and Channel are correctly added to support the new notification features.


171-171: Effective success notification implementation.

The Discord notification for successful application version publishing provides valuable monitoring information with a direct link to the application edit page.


179-179: Appropriate error notification with exception details.

The Discord notification for exceptions includes the exception class and message, which aids in debugging and monitoring application version distribution failures.

src/main/java/ai/elimu/tasks/analytics/VideoLearningEventImportScheduler.java (2)

57-117: Excellent error handling implementation.

The comprehensive try-catch block around the entire CSV processing logic provides robust error handling. This prevents the scheduler from failing silently and ensures monitoring through Discord notifications.


114-117: Appropriate error reporting and logging.

The exception handling includes proper logging and Discord notification with exception details, which aids in monitoring and debugging import failures.

src/main/java/ai/elimu/tasks/analytics/LetterSoundLearningEventImportScheduler.java (2)

57-117: Consistent error handling across schedulers.

The comprehensive try-catch block implementation follows the same pattern as other analytics import schedulers, providing consistent error handling and monitoring across the codebase.


114-117: Proper error reporting mechanism.

The exception handling includes both logging and Discord notification, ensuring that import failures are properly monitored and can be debugged effectively.

src/main/java/ai/elimu/tasks/analytics/WordAssessmentEventImportScheduler.java (2)

57-117: Consistent and comprehensive error handling.

The try-catch block implementation maintains consistency with other analytics import schedulers while providing comprehensive error handling for the entire CSV processing workflow.


114-117: Effective error monitoring and logging.

The exception handling properly logs errors and sends Discord notifications, ensuring that word assessment event import failures are monitored and can be addressed promptly.

Copy link
Contributor

@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

🧹 Nitpick comments (1)
src/test/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelperTest.java (1)

26-27: TODO comments indicate incomplete test coverage.

The TODO comments suggest that tests for letter-sound assessment events, number assessment events, and number learning events are still missing.

Would you like me to help generate the missing test methods for these event types to ensure comprehensive test coverage?

Also applies to: 71-73

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4a539e and be55297.

⛔ Files ignored due to path filters (5)
  • src/test/resources/ai/elimu/util/csv/5b7c682a12ecbe2e_3005009_letter-sound-learning-events_2025-06-18.csv is excluded by !**/*.csv, !**/*.csv
  • src/test/resources/ai/elimu/util/csv/5b7c682a12ecbe2e_3005009_storybook-learning-events_2025-06-20.csv is excluded by !**/*.csv, !**/*.csv
  • src/test/resources/ai/elimu/util/csv/5b7c682a12ecbe2e_3005009_video-learning-events_2025-06-18.csv is excluded by !**/*.csv, !**/*.csv
  • src/test/resources/ai/elimu/util/csv/5b7c682a12ecbe2e_3005009_word-assessment-events_2025-06-19.csv is excluded by !**/*.csv, !**/*.csv
  • src/test/resources/ai/elimu/util/csv/5b7c682a12ecbe2e_3005009_word-learning-events_2025-06-18.csv is excluded by !**/*.csv, !**/*.csv
📒 Files selected for processing (2)
  • src/main/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelper.java (11 hunks)
  • src/test/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelperTest.java (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelper.java
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: build (windows-latest, 21)
  • GitHub Check: build (windows-latest, 17)
  • GitHub Check: build (ubuntu-latest, 21)
  • GitHub Check: build (ubuntu-latest, 17)
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
  • GitHub Check: test_rest
🔇 Additional comments (8)
src/test/java/ai/elimu/util/csv/CsvAnalyticsExtractionHelperTest.java (8)

4-4: Import addition looks good.

The assertNull import is appropriately added to support the new null checks in the test methods.


21-22: Research experiment enum imports are correctly added.

These imports are necessary for the new test assertions that validate research experiment and experiment group fields.


48-68: Letter-sound learning events test for v3005009 is well-structured.

The test correctly validates the new research experiment fields and follows the established pattern. The timestamp calculation using multiplication by 1_000L is consistent with other v3005009 tests.


99-122: Word assessment events test updated correctly.

The test properly validates the new research experiment fields (ResearchExperiment.WORD_EMOJIS and ExperimentGroup.TREATMENT) and maintains consistency with the existing assertion pattern.


146-168: Word learning events test includes proper null validation.

The test correctly uses assertNull for the additionalData field and validates the research experiment fields appropriately.


237-260: Storybook learning events test is comprehensive.

The test validates all the new fields including null checks for additionalData and proper assertion of research experiment and experiment group values.


263-308: Video learning events tests are properly organized.

Both the v3001018 and v3005009 tests are correctly structured. The v3005009 test includes the new research experiment field validations while maintaining the existing test patterns.


48-308: Let’s search the entire repo for those CSVs to locate the test‐resources directory (or confirm absence):

#!/bin/bash
# Search for each referenced CSV file anywhere in the repo
csv_files=(
    "5b7c682a12ecbe2e_3005009_letter-sound-learning-events_2025-06-18.csv"
    "5b7c682a12ecbe2e_3005009_word-assessment-events_2025-06-19.csv"
    "5b7c682a12ecbe2e_3005009_word-learning-events_2025-06-18.csv"
    "5b7c682a12ecbe2e_3005009_storybook-learning-events_2025-06-20.csv"
    "5b7c682a12ecbe2e_3005009_video-learning-events_2025-06-18.csv"
)

echo "Looking for CSV test files in the repo..."
for file in "${csv_files[@]}"; do
  echo "--- $file ---"
  find . -type f -name "$file" -print || echo "Not found"
done

@jo-elimu jo-elimu merged commit a8965f8 into main Jun 20, 2025
17 of 20 checks passed
@jo-elimu jo-elimu deleted the 2260-analytics-research-experiments branch June 20, 2025 10:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add research experiments
1 participant