Skip to content

Lectures: Integrate slide visibility scheduling into ScheduleService #10705

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

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

Conversation

eceeeren
Copy link
Contributor

@eceeeren eceeeren commented Apr 18, 2025

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.

Motivation and Context

This pull request assigns a distinct name to each scheduled task to improve clarity in debug logs, making it easier to identify and trace specific tasks during execution. It also exposes the scheduling information through an admin REST API via AdminScheduleResource, allowing for better visibility and management of scheduled tasks.

Description

To enable this implementation, the following changes are made:

  1. SlideLifecycle is created to represent the lifecycle events of a Slide
  2. SlideLifecycle is represented in the ScheduleService alongside the Exercise and Participation Events
  3. A mapping is created as "slide-schedules" in AdminScheduleResource to get a page of scheduled slide events

Steps for Testing

Prerequisites:

  • 1 Instructor
  1. Log in to Artemis
  2. Navigate to Course Administration > Lectures > Lectures Units
  3. Select a PDF file and add it as an Attachment Unit
  4. Hide a page for a short time (e.g. 2 minutes) and immediately save the Attachment Unit!
  5. The selected page and the Student Version should be updated automatically after 2 minutes (Slide will be visible again, if there are no hidden pages Student Version will disappear and if there are, Student Version should be updated)
  6. Create a Text Exercise with a Release Date and Due Date in a short time (e.g. 3 minutes)
  7. Get back to the Lecture Unit and hide a page using that exercise and immediately save the Attachment Unit!
  8. The selected page and the Student Version should be shown automatically after 3 minutes

Testserver States

You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.

Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Class/File Line Coverage Confirmation (assert/expect)
SlideUnhideScheduleService.java 100%
SlideUnhideExecutionService.java 100%
SlideLifecycleService.java 100%
SlideUnhideService.java 93%

Screenshots

Summary by CodeRabbit

  • New Features
    • Introduced scheduling, querying, and management of slide lifecycle tasks, including the ability to schedule, view, and cancel slide unhide events.
    • Added a new API endpoint to retrieve scheduled slide events with pagination.
  • Refactor
    • Updated slide unhide scheduling and execution to use a unified scheduling service, improving consistency and maintainability.
    • Streamlined slide unhide services to delegate scheduling and cancellation to centralized services.
  • Tests
    • Added comprehensive tests for slide unhide execution, scheduling, and service behavior to ensure reliability and correct integration.

@github-project-automation github-project-automation bot moved this to Work In Progress in Artemis Development Apr 18, 2025
@github-actions github-actions bot added server Pull requests that update Java code. (Added Automatically!) core Pull requests that affect the corresponding module lecture Pull requests that affect the corresponding module labels Apr 18, 2025
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed48m 59s 874ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure26s 580ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 48s 532ms

@github-actions github-actions bot added the tests label Apr 18, 2025
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed48m 50s 583ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure24s 618ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 47s 439ms

Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed49m 13s 595ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure24s 722ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 45s 578ms

Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed48m 40s 276ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure27s 90ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 46s 920ms

Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed50m 49s 443ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure24s 444ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 48s 633ms

Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed50m 1s 556ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 4s 222ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 44s 279ms

@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de April 19, 2025 21:22 Inactive
@eceeeren eceeeren marked this pull request as ready for review April 20, 2025 12:24
@eceeeren eceeeren requested review from a team and krusche as code owners April 20, 2025 12:24
Copy link
Contributor

coderabbitai bot commented Apr 20, 2025

Walkthrough

This change introduces a comprehensive scheduling framework for managing slide lifecycle events, particularly for handling the automatic unhiding of slides. A new SlideLifecycle enum and SlideLifecycleService provide the foundation for scheduling tasks based on slide lifecycle events. The ScheduleService is extended to support scheduling, tracking, querying, and canceling slide-related tasks, mirroring existing exercise and participation scheduling mechanisms. The REST API is expanded with endpoints for querying slide schedules. The slide unhide logic is refactored to directly use the scheduling service, removing previous messaging-based coordination. New and updated tests are included to verify the new scheduling and unhide logic.

Changes

File(s) Change Summary
src/main/java/de/tum/cit/aet/artemis/core/service/ScheduleService.java Extended to support scheduling, tracking, querying, and managing lifecycle tasks for slides; added new public methods, records, and internal data structures for slide scheduling.
src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminScheduleResource.java Renamed exercise schedule listing method and added a new REST endpoint for retrieving scheduled slide events.
src/main/java/de/tum/cit/aet/artemis/lecture/domain/SlideLifecycle.java Introduced new enum SlideLifecycle with an abstract method for retrieving lifecycle dates from slides.
src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideLifecycleService.java Added new service for scheduling slide lifecycle tasks using a TaskScheduler.
src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideScheduleService.java Refactored to delegate scheduling and cancellation to ScheduleService and SlideUnhideService, removing direct scheduling logic.
src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideService.java Refactored to directly manage scheduling and execution of slide unhiding tasks using ScheduleService, replacing messaging-based approach.
src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideExecutionServiceTest.java Added new test class to verify slide unhide execution under various scenarios.
src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideScheduleServiceTest.java Added new test class to verify slide unhide scheduling and cancellation logic.
src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideServiceTest.java Refactored tests to verify interactions with scheduling and execution services, reflecting new service dependencies and behaviors.

Sequence Diagram(s)

sequenceDiagram
    participant Admin as AdminScheduleResource
    participant Schedule as ScheduleService
    participant Slide as Slide
    participant SlideLife as SlideLifecycleService
    participant UnhideSvc as SlideUnhideService
    participant ExecSvc as SlideUnhideExecutionService

    Admin->>+Schedule: getAllSlideSchedules(pageable)
    Schedule-->>-Admin: Page<ScheduledSlideEvent>

    UnhideSvc->>+Schedule: cancelScheduledTaskForSlideLifecycle(slideId, UNHIDE)
    alt hidden date is null
        UnhideSvc-->>UnhideSvc: Log and return
    else hidden date in past
        UnhideSvc->>+ExecSvc: unhideSlide(slideId)
        ExecSvc-->>-UnhideSvc: (slide unhidden)
    else hidden date in future
        UnhideSvc->>+Schedule: scheduleSlideTask(slide, UNHIDE, task, "Slide Unhiding")
        Schedule->>+SlideLife: scheduleTask(slide, UNHIDE, task)
        SlideLife-->>-Schedule: ScheduledFuture
        Schedule-->>-UnhideSvc: (task scheduled)
    end

    UnhideSvc->>+Schedule: cancelScheduledTaskForSlideLifecycle(slideId, UNHIDE)
    UnhideSvc->>+ExecSvc: unhideSlide(slideId)
    ExecSvc-->>-UnhideSvc: (slide unhidden)
Loading

Suggested labels

ready for review

Suggested reviewers

  • krusche

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de9b452 and 3265e54.

📒 Files selected for processing (1)
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideExecutionServiceTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideExecutionServiceTest.java
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: client-tests
  • GitHub Check: client-style
  • GitHub Check: server-tests
  • GitHub Check: server-style
  • GitHub Check: Analyse

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.

❤️ 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 generate docstrings to generate docstrings for 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 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
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: 4

🧹 Nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/lecture/domain/SlideLifecycle.java (1)

10-18: Consider clarifying the Javadoc comment for UNHIDE.

The Javadoc comment states "The date when the slide becomes visible" but the implementation returns slide.getHidden(), which is when the slide was hidden. This might be confusing for future developers. Consider updating the comment to clarify that this returns the date when the slide should be unhidden (which is stored in the hidden field).

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 62da665 and 7dbd9ef.

📒 Files selected for processing (9)
  • src/main/java/de/tum/cit/aet/artemis/core/service/ScheduleService.java (10 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminScheduleResource.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/domain/SlideLifecycle.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideLifecycleService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideScheduleService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideService.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideExecutionServiceTest.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideScheduleServiceTest.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideServiceTest.java (6 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`src/main/java/**/*.java`: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,de...

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/lecture/domain/SlideLifecycle.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideLifecycleService.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideScheduleService.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideService.java
  • src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminScheduleResource.java
  • src/main/java/de/tum/cit/aet/artemis/core/service/ScheduleService.java
`src/test/java/**/*.java`: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_...

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/lecture/service/SlideUnhideScheduleServiceTest.java
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideExecutionServiceTest.java
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideServiceTest.java
🧬 Code Graph Analysis (2)
src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideScheduleServiceTest.java (1)
src/main/webapp/app/lecture/shared/entities/lecture-unit/slide.model.ts (1)
  • Slide (4-10)
src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideServiceTest.java (1)
src/main/webapp/app/lecture/shared/entities/lecture-unit/slide.model.ts (1)
  • Slide (4-10)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (41)
src/main/java/de/tum/cit/aet/artemis/core/web/admin/AdminScheduleResource.java (2)

45-45: LGTM! Renamed method improves clarity.

The method renaming from getAll to getAllExerciseSchedules enhances code readability by being more specific about what type of schedules are being retrieved.


51-62: LGTM! Well-implemented new endpoint.

The new slide schedules endpoint is nicely implemented, following the same pattern as the existing exercise schedules endpoint with proper pagination, HTTP response generation, and clear documentation.

src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideLifecycleService.java (3)

18-31: LGTM! Well-designed service with proper dependency injection.

The service is correctly configured with appropriate annotations and follows best practices with constructor injection for the TaskScheduler dependency.


44-48: LGTM! Well-implemented scheduling with appropriate logging.

The scheduleTask method correctly uses the TaskScheduler with proper error handling and appropriate debug logging. The implementation is clean and focused.


60-62: LGTM! Good method overloading pattern.

This overloaded method provides a convenient way to derive the execution time directly from the slide and lifecycle event, improving API usability.

src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideExecutionServiceTest.java (1)

26-161: LGTM! Comprehensive test coverage with well-structured test cases.

This test class provides excellent coverage of the SlideUnhideExecutionService functionality, testing both normal operation and various edge cases. The structure follows good testing practices with clear setup, execution, and verification phases in each test.

src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideScheduleServiceTest.java (10)

1-25: Good structure with proper imports and test setup.

The imports are well-organized, and the class appropriately extends AbstractSpringIntegrationIndependentTest. The test uses descriptive naming conventions and follows JUnit 5 best practices.


26-45: Well-structured test class with appropriate test repository usage.

The class follows good testing practices by:

  1. Using a descriptive unique test prefix for user context
  2. Properly mocking external dependencies
  3. Using Spring's DI for test utilities and repositories
  4. Creating a clear instance of the service under test with controllable dependencies

This approach isolates the service for proper unit testing while using real repositories for slide data.


46-65: Good test data initialization with varied test cases.

The setup method effectively initializes test data by:

  1. Setting up mock objects
  2. Instantiating the service under test with the right dependencies
  3. Creating test slides with different hidden timestamps
  4. Using both past and future dates to test different scenarios

This provides comprehensive coverage for scheduling logic based on different timestamp conditions.


67-80: Test effectively verifies scheduling of all hidden slides.

The test properly checks that scheduleAllHiddenSlides() triggers the slide unhide service for each hidden slide. This ensures the core functionality of finding and scheduling all hidden slides works correctly.


82-98: Test properly verifies scheduling by DTO with valid slide data.

This test correctly validates that when scheduling with a valid slide DTO:

  1. The service successfully finds the slide by ID
  2. The slide unhide service is properly invoked with the slide object

This ensures correct DTO-to-entity handling in the scheduling workflow.


100-111: Test appropriately handles null hidden date case.

The test correctly verifies that when a DTO has a null hidden date:

  1. The service properly handles this edge case
  2. No unhide operations are triggered

This ensures the service correctly handles optional or missing date values.


113-125: Test validates scheduling by valid slide ID.

The test confirms that when scheduling with a valid slide ID:

  1. The slide is correctly retrieved from the repository
  2. The unhide service is called with the expected slide object

This ensures proper ID-based scheduling flow.


127-138: Test verifies system stability with invalid ID input.

The test properly validates that when an invalid slide ID is provided:

  1. The service gracefully handles the non-existent ID
  2. No unhide operations are attempted

This prevents potential runtime errors from invalid inputs.


140-150: Test confirms correct cancellation of scheduled unhide tasks.

The test verifies that the cancellation flow:

  1. Properly delegates to the schedule service
  2. Passes the correct slide ID to the cancellation method

This ensures scheduled tasks can be properly cancelled.


152-163: Test confirms proper initialization on application startup.

Using a spy to verify method invocation is a good approach to test that the onApplicationReady event properly triggers scheduling of all hidden slides, ensuring automatic initialization of slide unhiding.

src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideService.java (7)

5-7: Appropriate imports for date handling and optional values.

The imports of ZonedDateTime and Optional are necessary for the updated implementation and follow the coding guidelines for Java imports.


13-16: Good imports for scheduling service and lifecycle domain model.

The ScheduleService import and SlideLifecycle enum import are appropriate for implementing the new scheduling infrastructure.


18-19: Improved service documentation.

The updated JavaDoc clearly describes the service's responsibility for slide unhiding business logic.


24-33: Good service setup with proper dependency injection.

The service now:

  1. Uses a proper logger for traceability
  2. Accepts an Optional to handle potential absence of the service
  3. Uses constructor injection for dependencies following best practices

This ensures clean dependency management and prevents NPEs when the schedule service isn't available.


35-42: Improved method documentation with comprehensive description.

The updated JavaDoc clearly describes all three scenarios for slide hidden property updates:

  1. Future date: Schedule unhiding
  2. Past date: Unhide immediately
  3. Null: Cancel existing tasks

This makes the method's behavior clear and helps with maintenance.


43-64: Well-implemented slide unhiding logic with proper error handling.

The handleSlideHiddenUpdate method:

  1. First cancels any existing scheduled tasks to prevent duplication
  2. Handles null hidden dates with early return
  3. Compares current time with hidden date to decide between immediate unhiding and scheduling
  4. Uses appropriate logging for each decision path
  5. Safely accesses the optional schedule service

The implementation is robust and handles all edge cases appropriately.


67-76: Enhanced unhide method with task cancellation.

The method now cancels any scheduled unhide tasks before performing the immediate unhide operation, which prevents potential race conditions where a scheduled unhide might occur after a manual unhide.

src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideServiceTest.java (8)

4-11: Updated imports for proper mock testing.

The additional imports for ArgumentCaptor, Mock, MockitoAnnotations, and SlideLifecycle support the updated testing approach that verifies service interactions rather than implementation details.


20-24: Appropriate service dependencies for testing.

The imports now include ScheduleService and SlideLifecycle, which are necessary for testing the updated implementation.


32-45: Proper test setup with mocked dependencies.

The test now:

  1. Mocks both ScheduleService and SlideUnhideExecutionService
  2. Maintains real repositories for slide data
  3. Sets up the service with explicit dependencies

This approach provides good isolation for testing while maintaining real data behavior.


48-55: Improved test initialization with proper mocking.

The updated initialization:

  1. Properly initializes all mocks with MockitoAnnotations
  2. Creates the service with explicit mocked dependencies
  3. Uses Optional.of for the schedule service to match the implementation

This setup enables precise verification of service interactions.


71-97: Well-structured test for future hidden date scenario.

The test effectively verifies that when a slide has a future hidden date:

  1. The scheduleSlideTask method is called with the correct arguments
  2. The slide, lifecycle event, and task name are correctly passed
  3. The service doesn't immediately unhide the slide

Using ArgumentCaptors is an effective approach to verify multiple arguments.


99-116: Good test coverage for past hidden date scenario.

The test properly verifies that when a slide has a past hidden date:

  1. The slide is immediately unhidden via the execution service
  2. No scheduling is performed

This ensures the service correctly handles slides that should already be unhidden.


132-138: Updated verification for null hidden date scenario.

The test now properly verifies that when a slide's hidden date is null:

  1. Any existing scheduled tasks are cancelled
  2. No new tasks are scheduled
  3. No immediate unhiding occurs

This ensures proper handling of slides that don't need unhiding.


151-155: Updated verification for manual unhide scenario.

The test now correctly verifies that when manually unhiding a slide:

  1. Any existing scheduled tasks are cancelled first
  2. The slide is immediately unhidden via the execution service

This ensures proper coordination between scheduled and manual unhiding.

src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideUnhideScheduleService.java (6)

14-17: Updated import for schedule service integration.

The import of ScheduleService is appropriate for integrating with the centralized scheduling system.


18-21: Improved class documentation.

The updated JavaDoc clearly explains the service's role in delegating to the integrated ScheduleService, which helps with understanding the design.


27-38: Simplified service with proper dependency injection.

The service now:

  1. Has appropriate dependencies for its responsibilities
  2. Uses constructor injection following best practices
  3. Delegates scheduling to SlideUnhideService and cancellation to ScheduleService

This refactoring promotes single responsibility principle and improves maintainability.


72-73: Simplified scheduling logic with proper delegation.

The method now properly delegates to SlideUnhideService for handling slide unhiding, removing duplication of scheduling logic and improving maintainability.


81-82: Consistent delegation pattern for slide unhiding.

This method follows the same pattern of delegating to SlideUnhideService, maintaining consistency in the codebase and centralizing the unhide logic.


90-91: Proper delegation of cancellation to ScheduleService.

The method delegates cancellation to ScheduleService and adds appropriate logging, centralizing the scheduling logic in the dedicated service.

src/main/java/de/tum/cit/aet/artemis/core/service/ScheduleService.java (4)

110-122: Inject a shared TaskScheduler bean instead of instantiating a new pool

Creating a dedicated ThreadPoolTaskScheduler here duplicates thread‑pool infrastructure that Spring already provides.
Drawbacks:

  1. Multiple schedulers = harder tracing & metrics, especially now that this service is the central hub for all lifecycle events (exercise + participation + slide).
  2. The pool size is hard‑coded to 1; with virtual threads enabled this partly defeats the purpose because a single carrier thread can still become a bottleneck for long‑running jobs.
  3. No explicit shutdown (scheduler.shutdown()) – the pool survives application context re‑starts in tests, leaking threads and producing flaky failures.

Consider constructor‑injecting the primary TaskScheduler (or a qualified bean) and removing the manual initialization:

-    private final TaskScheduler taskScheduler;
+    private final TaskScheduler taskScheduler;

@@
-    public ScheduleService(ExerciseLifecycleService exerciseLifecycleService, ParticipationLifecycleService participationLifecycleService,
-            SlideLifecycleService slideLifecycleService) {
+    public ScheduleService(ExerciseLifecycleService exerciseLifecycleService,
+                           ParticipationLifecycleService participationLifecycleService,
+                           SlideLifecycleService slideLifecycleService,
+                           TaskScheduler taskScheduler) {   // <-- inject shared bean
@@
-        // Initialize the TaskScheduler
-        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
-        scheduler.setPoolSize(1);
-        scheduler.setVirtualThreads(true);
-        scheduler.initialize();
-        this.taskScheduler = scheduler;
+        this.taskScheduler = taskScheduler;
     }

If a dedicated pool is still required, declare it as a separate @Bean in a configuration class so Spring can manage its lifecycle.
[ suggest_essential_refactor ]


118-122: Ensure proper shutdown of the scheduler to prevent thread leaks

When keeping the ad‑hoc ThreadPoolTaskScheduler, add a @PreDestroy‑annotated method to call taskScheduler.shutdown().
Without this, integration‑/unit‑tests that tear down and recreate the Spring context leave non‑daemon carrier threads running, producing “task already scheduled on shutdown executor” warnings.
[ flag_critical_issue ]


153-166: Guard against negative delays when computing scheduledTime

future.getDelay(TimeUnit.SECONDS) returns a negative value once the task is overdue, causing scheduledTime to be in the past and breaking chronologic ordering on the admin UI.

-            var scheduledTime = ZonedDateTime.now().plusSeconds(task.future().getDelay(TimeUnit.SECONDS));
+            long delaySeconds = Math.max(0, task.future().getDelay(TimeUnit.SECONDS));
+            var scheduledTime = ZonedDateTime.now().plusSeconds(delaySeconds);

(Optional) filter out already‑executed tasks altogether instead of showing a timestamp “now minus X”.
[ suggest_optional_refactor ]


341-346: Support multiple slide tasks per lifecycle (mirroring exercises)

scheduleSlideTask currently accepts only a single Runnable. For feature parity with exercises you may need overloads accepting:

  • Pair<ZonedDateTime, Runnable> – schedule at a specific point in time.
  • Set<Pair<ZonedDateTime, Runnable>> – schedule several runs.

This avoids downstream services having to loop and call scheduleSlideTask repeatedly.
[ suggest_optional_refactor ]

@github-project-automation github-project-automation bot moved this from Work In Progress to Ready For Review in Artemis Development Apr 20, 2025
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran197 passed3 skipped1 failed51m 431ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 2s 644ms

coderabbitai[bot]
coderabbitai bot previously approved these changes Apr 20, 2025
@eceeeren eceeeren force-pushed the feature/lectures/create-slide-lifecycle branch from de9b452 to 3265e54 Compare April 20, 2025 19:57
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed49m 57s 278ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 2s 951ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 44s 807ms

Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran197 passed3 skipped1 failed46m 11s 149ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 3s 453ms

@Anishyou
Copy link
Contributor

I am manually testing this. What do you mean by point no. 5 exactly? I have created an attachment unit as a PDF, then I hide it for 2 minutes.
I opened the course as a student, and I downloaded the PDF, but the page that I hid was not available. Is that the test?

@eceeeren
Copy link
Contributor Author

I am manually testing this. What do you mean by point no. 5 exactly? I have created an attachment unit as a PDF, then I hide it for 2 minutes. I opened the course as a student, and I downloaded the PDF, but the page that I hid was not available. Is that the test?

Hello, sorry for the confusion. When you hide it for 2 minutes, after 2 minutes the page should be available again. The idea here is to test if SlideUnhideService automatically makes the slides visible again. If you can't see the page again after 2 minutes (also as a student), something should be wrong.

@Anishyou
Copy link
Contributor

I am manually testing this. What do you mean by point no. 5 exactly? I have created an attachment unit as a PDF, then I hide it for 2 minutes. I opened the course as a student, and I downloaded the PDF, but the page that I hid was not available. Is that the test?

Hello, sorry for the confusion. When you hide it for 2 minutes, after 2 minutes the page should be available again. The idea here is to test if SlideUnhideService automatically makes the slides visible again. If you can't see the page again after 2 minutes (also as a student), something should be wrong.

I can see it ,after the specified time. But I have to download it again to check it.

Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran195 passed3 skipped3 failed53m 17s 896ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure2m 3s 735ms
e2e/exam/ExamDateVerification.spec.ts
ts.Exam date verification › Exam timing › Student can start after start Date❌ failure20s 589ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 45s 793ms

@Anishyou
Copy link
Contributor

Locally tested- Attached a PDF, hide it for a few minutes. On the student account, when I download the PDF file, the section is hidden for the time.
Also when aligned with the due date of an exercise, it is released parallely. As mentioned, on student side pdf needs to be downloaded
👍

@helios-aet helios-aet bot temporarily deployed to artemis-test5.artemis.cit.tum.de April 22, 2025 21:16 Inactive
Copy link

@HawKhiem HawKhiem left a comment

Choose a reason for hiding this comment

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

Tested on TS5. The hidden page doesn't automatically show after 2 minutes. As can be seen in the screenshot. The page supposed to show up at 23:49 but it didn't even though it was 23:51 at the time. Or did I make some mistakes?

image

@eceeeren
Copy link
Contributor Author

Tested on TS5. The hidden page doesn't automatically show after 2 minutes. As can be seen in the screenshot. The page supposed to show up at 23:49 but it didn't even though it was 23:51 at the time. Or did I make some mistakes?

image

Hello Khiem, thanks for your testing. Did you save the attachment unit after hiding the page? If not, the Slide Unhide Service is not triggered.

Copy link
Contributor

@Anishyou Anishyou left a comment

Choose a reason for hiding this comment

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

Locally tested- Attached a PDF, hide it for a few minutes. On the student account, when I download the PDF file, the section is hidden for the time.
Also when aligned with the due date of an exercise, it is released parallely. As mentioned, on student side pdf needs to be downloaded
👍

@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de April 23, 2025 20:01 Inactive
Copy link

@HawKhiem HawKhiem left a comment

Choose a reason for hiding this comment

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

Retest on TS3. Works as expected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Pull requests that affect the corresponding module lecture 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.

3 participants