|
| 1 | +ADR: API Endpoint for User Exam Due Dates in the Mobile App |
| 2 | +########################################################### |
| 3 | + |
| 4 | +Status |
| 5 | +****** |
| 6 | + |
| 7 | +Proposed |
| 8 | + |
| 9 | +Context |
| 10 | +******* |
| 11 | + |
| 12 | +To improve the Open edX mobile experience, we need to provide learners with a fast, accurate list of upcoming exam and assignment due dates across all of their enrolled courses. This is critical for enabling mobile-first learning workflows, proactive planning, and push notifications. |
| 13 | + |
| 14 | +The current approach, which relies on ``get_course_date_blocks()`` and ``modulestore`` traversal, is inefficient, especially for multi-course scenarios. Furthermore, the Open edX community has committed to limiting ``modulestore`` usage in runtime systems (as per ADR 0011) and modularizing content and date management. |
| 15 | + |
| 16 | +Decision |
| 17 | +******** |
| 18 | + |
| 19 | +We will reuse and extend the ``edx-when`` application as the unified backend for both course-level and user-level due dates. |
| 20 | + |
| 21 | +Key Implementation Details |
| 22 | +========================== |
| 23 | + |
| 24 | +* **Data Storage**: |
| 25 | + * Use ``edx-when.ContentDate`` to store canonical due dates published from course metadata. |
| 26 | + * Use ``edx-when.UserDate`` to store user-specific overrides, including personalized schedules (self-paced) and instructor-granted extensions. |
| 27 | +* **Service Layer**: Implement a dedicated Python service layer within ``edx-when`` to resolve dates. This service will merge ``ContentDate`` and ``UserDate`` records and apply visibility filtering. This ensures the logic is reusable by the LMS, background tasks, and the REST API. |
| 28 | +* **API Endpoint**: Create a new REST API endpoint (proposed at ``/api/edx_when/v1/user-dates/``) that returns a merged, filtered, and sorted list of upcoming due dates for the authenticated user across all enrollments. |
| 29 | +* **Encapsulation**: The REST API will reside within ``edx-when`` to keep it co-located with the models, provided that it does not require circular dependencies on ``edx-platform``. |
| 30 | + |
| 31 | +Scope Limitations |
| 32 | +================= |
| 33 | + |
| 34 | +* **CCX Courses**: Custom Courses for edX (CCX) are excluded from this implementation due to their unique override structure and management complexity. |
| 35 | + |
| 36 | +Consequences |
| 37 | +************ |
| 38 | + |
| 39 | +Positive |
| 40 | +======== |
| 41 | + |
| 42 | +* **Performance**: Replaces slow runtime block traversal with indexed database queries. |
| 43 | +* **Consistency**: Centralizes date management into a single canonical system for LMS, MFE, and Mobile. |
| 44 | +* **Scalability**: Reduces the load on the ``modulestore`` and aligns with the platform's long-term goal of removing MongoDB dependencies. |
| 45 | +* **Maintainability**: Avoids the creation of redundant data models for "exam dates" specifically. |
| 46 | + |
| 47 | +Negative/Risks |
| 48 | +============== |
| 49 | + |
| 50 | +* **Dependency Management**: We must ensure ``edx-when`` does not import code from ``edx-platform`` to maintain clean encapsulation. If complex platform logic is required, a thin wrapper API may need to be hosted in ``edx-platform`` instead. |
| 51 | + |
| 52 | +Rejected Alternatives |
| 53 | +********************* |
| 54 | + |
| 55 | +1. **Continue Using XBlock Metadata** |
| 56 | + * *Description*: Store all start, due, and grace period fields in ``modulestore``. |
| 57 | + * *Reason for Rejection*: No support for user-level overrides without course republishing; cannot support dynamic scheduling or extensions effectively. |
| 58 | + |
| 59 | +2. **Use Only the 'Schedules' App** |
| 60 | + * *Description*: Centralize all date logic through ``schedules.Schedule``. |
| 61 | + * *Reason for Rejection*: Not designed for block-level (exam-specific) due dates; would require significant refactoring of upstream APIs. |
| 62 | + |
| 63 | +3. **Compute Dates On-the-Fly at Runtime** |
| 64 | + * *Description*: Dynamically calculate due dates based on enrollment and pacing without persistence. |
| 65 | + * *Reason for Rejection*: Degrades performance at scale and provides no audit trail for extension history. |
| 66 | + |
| 67 | +4. **Separate Microservice** |
| 68 | + * *Description*: Introduce a new service for exam dates. |
| 69 | + * *Reason for Rejection*: Adds unnecessary operational overhead and duplicates functionality already available in ``edx-when``. |
0 commit comments