Skip to content

ADR: API Endpoint for User Exam Due Dates in the Mobile App #36787

Description

@SergiiKalinchuk

Context

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.

The current approach, which relies on get_course_date_blocks() and modulestore traversal, is inefficient, especially for multi-course scenarios. The Open edX community has committed to limiting modulestore usage in runtime systems (ADR 0011) and modularizing content and date management.

Solution Summary

We are going to reuse and extend the edx-when application as the unified backend for both course-level and user-level due dates:

  • Use ContentDate to store published due dates from course metadata
  • Use UserDate to store user-specific overrides, including:
    • Personalized schedules (self-paced)
    • Instructor-granted extensions
  • Create a new API endpoint to return a merged and filtered list of upcoming due dates for the authenticated user

Rejected Alternatives

The following approaches were considered during the design phase but ultimately rejected due to technical or architectural limitations:

1. Continue Using Only XBlock Metadata for Dates

  • Description: Store all start, due, and graceperiod fields in the modulestore within XBlock definitions.
  • Reason for Rejection:
    • No support for user-level overrides.
    • Requires course republishing for any change.
    • Cannot support dynamic scheduling, self-paced courses, or extensions.

2. Use Only the schedules App to Drive Dates

  • Description: Centralize all date logic through schedules.Schedule and schedules.CourseDateOverride.
  • Reason for Rejection:
    • Not designed for block-level (e.g., exam-specific) due dates.
    • Cannot serve instructor-paced or hybrid course modes.
    • Adds significant refactor requirements to upstream LMS and Mobile APIs.

3. Store Dates in a Separate Custom Table or External Service

  • Description: Introduce a new app or microservice for handling exam due dates independently of edx-when.
  • Reason for Rejection:
    • Duplicates functionality already available in edx-when.
    • Adds operational and architectural overhead.
    • Increases latency and coupling across services.

4. Compute Dates On-the-Fly at Runtime

  • Description: Dynamically calculate due/start dates based on enrollment and pacing without persisting them.
  • Reason for Rejection:
    • Degrades performance at scale.
    • No audit trail or persistence for extension history.
    • Makes date behavior inconsistent and hard to debug.

The final decision to use and extend the edx-when data model preserves flexibility, supports both default and override scenarios, and ensures consistent integration across all platform interfaces (LMS, MFE, Mobile).

Impact on Existing Functionality

Based on our review of the current Open edX codebase, the ContentDate and UserDate models from the edx-when module are not widely integrated into core platform components at this time. Their usage appears to be limited, with no direct dependencies from LMS rendering paths or block structure transformers in the default configuration of the platform.

As a result, the changes proposed in this ADR are not expected to impact existing functionality. The models in question do not currently serve as a critical path for date resolution in standard learner-facing APIs or courseware behavior.

Architecture Overview

✅ What We Reuse

Component Role
edx-when.ContentDate Stores canonical due dates published for each course content element
edx-when.UserDate Stores per-user overrides (e.g., extensions, personalized pacing)
Schedules Provides start_date for self-paced learners (used in overrides)

🆕 What We Add

Component Purpose
New API Returns all due dates visible to the user across their courses
Runtime logic Merges ContentDate and UserDate, applies filtering/visibility

Data Flow

  1. Studio authors define dates → written to ContentDate via publishing
  2. Overrides from instructors or learners → stored in UserDate
  3. Mobile client calls new API /api/user-due-dates/
  4. Backend logic:
    • Loads enrolled courses
    • Retrieves corresponding ContentDate and UserDate records
    • Applies overrides and visibility checks
    • Returns sorted, paginated results

API Responsibilities

The new API will:

  • Authenticate the user
  • Retrieve the list of enrolled courses
  • Fetch all related ContentDate and UserDate entries
  • Apply overrides and enforce content visibility
  • Return fields such as:
    • course_id
    • title
    • due_date
    • first_component_block_id
    • override_source (if applicable)

Scope Limitations

CCX courses (Custom Courses for EdX) are excluded from this implementation due to their unique override structure and management.

Benefits

  • Performance: Indexed queries instead of runtime block traversal
  • Consistency: All dates managed in one canonical system
  • Maintainability: No need to create redundant data models
  • Scalability: Reusable for LMS, mobile, and analytics
  • Forward-compatible: Aligned with plans to remove MongoDB and improve RBAC

Next Steps

  1. Ensure publishing pipeline writes dates to ContentDate
  2. Use UserDate to record instructor and learner overrides
  3. Build new endpoint /api/user-due-dates/
  4. Merge base and override dates at runtime
  5. Implement access control and visibility filtering
  6. Monitor for latency, accuracy, and correctness

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions