Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: numerous updates and elaborations regarding data model and entities.

...

Anchor
_GoBack
_GoBack
Data Model


Image RemovedImage Added Diagram note:

Entities

...

Entities

Program

The Program represents the collection of multiple Course Runs into a group.Course Codes in an ordered sequence.  Each Course Code in turn collects Course Run Modes; learners must complete one course run mode for each course code in order to satisfy the completion requirement of the program. 

Attributes:

  • name: a user-facing name for the Program, which must be unique.
  • descriptionsubtitle: an optional brief text string describing the Programa brief, descriptive subtitle for the Program (text only).
  • category: an optional a string which can be used to organize Programs for presentation / classification. For XSeries-based programs, the category will be 'XSeriesxseries'.
  • certificate_type: an optional string describing the type of certificate required to satisfy completion for Courses in the Program.  For XSeries-based programs, the certificate type will be 'verified'.
  • status: an enum indicating the current lifecycle state of the Program.  This is discussed further below in the "Program Lifecycle" section. 

...

Organization

This represents the partner Organization that entity is publishing a given Program.

For the XSeries MVP, only one Organization per Program will be supported; this entity is modeled as many-to-many for future extensibility.

ProgramCourse

This represents an association between a Program and a Course (independent of specific Runs of that Course). The ProgramCourse has a 'position' attribute which is used to present a Course's Programs in a user-defined order.

Not all Runs of a Course are automatically associated with a Program. Associating the Course provides the ability to select and link/unlink individual Runs of that Course with the Program.

For the XSeries MVP, a Course may only be associated with a single Program.  This is in order to simplify the learner dashboard implementation planned for MVP.  In a future iteration, a Course and its runs may appear in multiple Programs.

ProgramCourseRun

This represents a specific Course Run linked to a Program. A Course Run should not be linked to a Program until it has been published to the participating LMS. (To avoid consistency problems, logic may be added to modify, remove, or invalidate Programs when a related Course Run stops being available in the LMS, though this is not part of XSeries MVP.)

ProgramUser

This represents a User's association with / registration into a Program, and captures any state relevant to that association. For the XSeries MVP, this state consists of a required 'status' enum attribute which will be used to track whether the User is "active", "completed", or "deleted" in that Program.  "Deleted" will be an internal-only status to support soft-deletion; API consumers will not see registrations with this status.

For the XSeries MVP, we are eschewing an explicit user interaction to make this association.  Instead, learners will be automatically and lazily associated with Programs:

  • If a learner is enrolled in a course run that is part of an (active) Program, she will be considered to be associated with that Program.
  • The following learner-specific events will trigger a call to the enrollment API to check in which course runs the learner is actively enrolled:
    • When calling the API to fetch a listing of Programs for that user.
    • When handling a notification that a certificate has been earned by that user.
  • Based on the results of the enrollment check, the ProgramUser table will be updated (using a get-or-create semantic).
  • This heavy usage of the Enrollment API will almost certainly necessitate performance optimizations.  Measurement and optimization of these interactions will be part of our implementation work.

Program Lifecycle

The following sequential lifecycle is envisioned for Programs, based on known/anticipated use cases:

  1. unpublished - an initial status during which the Program is being constructed but should not yet be made available to Learners.  Unpublished Programs are invisible to non-admins and learners cannot be associated with them.
  2. active – this status is set when the Author/Admin has finished building the Program and wants to make it available to Learners in the participating LMS.
    1. When a Program has been set to active, Course Runs cannot be removed from the Program.
    2. A Program can only be reverted from active to unpublished if no Users have yet been associated with the Program.
  3. retired – this status is set when the Program should no longer be offered to new Learners. It may still be displayed as a historical item if that makes sense in a given context (e.g. viewing a Learner's past achievements).
  4. deleted – used to support soft-deletion of Programs where needed. Programs with this status will not be visible to API consumers.

Replication of LMS Entities

The Org, Course, and Course Run entities are pointers to entities replicated from the authoritative source for those data (i.e. the participating LMS). They are replicated to this service in order to be able to create foreign key constraints from Program-related tables.

Following an initial backpopulation of these tables, subsequent changes will be replicated to the Programs application using Django signals / event hooks installed in the LMS.

Presently, the LMS implements publish and delete signals for Course Runs in the modulestore. The planned behavior for the XSeries MVP is to fire asynchronous, idempotent requests to PUT or DELETE against a Course Run endpoint in the Programs service, triggered by these signals. That endpoint will, internally, use the opaque_keys shared library to derive Course and Org IDs from the Course Run IDs, and insert data in those tables if none yet exist.

With the recent deployment of edx-organizations (part of the automated certificates work), we now have an authoritative source of truth for Organizations hosted in the LMS, so our tools for backpopulation will use this source for Orgsa reference to an organization as known to the platform.  It maps to the first component in an LMS course_key, and exists in this model in order to enforce relational integrity at the physical (database) level.

Attributes:

  • key: the "org" part occurring in course keys, for example, "ANUx" in "course-v1:ANUx+ASTRO2X+2B3T2015".
  • display_name: a user-facing display name for the organization, for example "Australian National University"

CourseCode

This entity represents the notion of a certain course offering independent of run.  This concept does not exist in edx-platform, but can generally be inferred by comparing the first two components (org and course) in course keys; for example two course runs with course keys "course-v1:ANUx+ASTRO2X+2B3T2015" and "course-v1:ANUx+ASTRO2X+2B4T2015" would be associated with a single Course Code whose key is "ASTRO2X" and is associated with an Organization whose key is "ANUx".

  • key: the "course" part occurring in course keys, for example, "ASTRO2X" in "course-v1:ANUx+ASTRO2X+2B3T2015".
  • display_name: a user-facing display name for the course, for example "Astrophysics: Exploring Exoplanets"
  • org: a reference to the Organization associated with this Course Code

ProgramOrganization

This represents the partner Organization that is publishing a given Program.

For the XSeries MVP, only one Organization per Program will be supported; this entity is modeled as many-to-many for future extensibility.

ProgramCourseCode

This represents an association between a Program and a CourseCode. The ProgramCourse has a 'position' attribute which is used to present CourseCodes within a Program in a user-defined order.

For the XSeries MVP, a CourseCode may only be associated with a single Program.  This is in order to simplify the learner dashboard implementation planned for MVP.  In a future iteration, a CourseCode and its runs / modes may appear in multiple Programs.

ProgramCourseRunMode

This represents a specific run of a course, and a "mode" of that course, linked to a Program (via ProgramCourseCode).  Runs and modes cannot be associated with Programs until they have been published to the participating LMS. (To avoid consistency problems, logic may be added to modify, remove, or invalidate Programs when a related run / mode stops being available in the LMS, though this is not part of XSeries MVP.)

ProgramUser

This represents a User's association with / registration into a Program, and captures any state relevant to that association. For the XSeries MVP, this state consists of a required 'status' enum attribute which will be used to track whether the User is "active", "completed", or "deleted" in that Program.  "Deleted" will be an internal-only status to support soft-deletion; API consumers will not see registrations with this status.

For the XSeries MVP, we are eschewing an explicit user interaction to make this association.  Instead, learners will be automatically and lazily associated with Programs:

  • If a learner is enrolled in a course run that is part of an (active) Program, she will be considered to be associated with that Program.
  • The following learner-specific events will trigger a call to the enrollment API to check in which course runs the learner is actively enrolled:
    • When calling the API to fetch a listing of Programs for that user.
    • When handling a notification that a certificate has been earned by that user.
  • Based on the results of the enrollment check, the ProgramUser table will be updated (using a get-or-create semantic).
  • This heavy usage of the Enrollment API will almost certainly necessitate performance optimizations.  Measurement and optimization of these interactions will be part of our implementation work.

Program Lifecycle

The following sequential lifecycle is envisioned for Programs, based on known/anticipated use cases:

  1. unpublished - an initial status during which the Program is being constructed but should not yet be made available to Learners.  Unpublished Programs are invisible to non-admins and learners cannot be associated with them.
  2. active – this status is set when the Author/Admin has finished building the Program and wants to make it available to Learners in the participating LMS.
    1. When a Program has been set to active, Course Runs cannot be removed from the Program.
    2. A Program can only be reverted from active to unpublished if no Users have yet been associated with the Program.
  3. retired – this status is set when the Program should no longer be offered to new Learners. It may still be displayed as a historical item if that makes sense in a given context (e.g. viewing a Learner's past achievements).
  4. deleted – used to support soft-deletion of Programs where needed. Programs with this status will not be visible to API consumers.

Population of Organizations

Organizations are pointers to related data for which the authoritative source is presently Studio (as part of the Certificate administration feature).  The existence, key and display name of each Organization has to be copied from Studio.  This can be done using a combination of strategies:

  • A management command which copies the entire list of Organizations known to Studio and creates them using the Programs API.   This management command, and the API calls it uses, must be idempotent.  It will be used to initially populate the Organizations, and can be used in the future to manually re-sync the data if necessary to recover from an outage or interruption.
  • A Django signal added to Studio, which listens for additions or changes to the list of Organizations in Studio, and makes Programs API calls to ensure the data is incrementally updated.
    • Organizations are not frequently changed.  A signal-triggered API call to update an Organization would ideally be performed asynchronously, but in practice this may be overkill provided we use short HTTP timeouts, handle failures gracefully, and monitor failures judiciously.
    • The signals should be disabled for bulk operations on the Organization list in Studio, which would present a more serious bottleneck.  If such a need arises, we would instead use the management command (as described above) for bulk resyncing.

Population of CourseCodes

CourseCodes have no equivalent entity in edx-platform.  They are instead derived from the set of course runs that are published into the LMS using Studio.  To generate this data in the Programs service, its API will expose and endpoint that accepts POST (or DELETE) requests containing information about a course run, and will generate CourseCode (and if needed, Organization) records.  

This endpoint will be used in a way similar to the way Organizations are synced:

  • An idempotent management command which iterates over the list of course runs, POSTing each course key and title to the endpoint, for initial sync and manual re-sync as needed.
  • A Django signal in the Studio publish operation (this signal already exists) which will incrementally update the data as it changes.
    • The signal handler which replicates individual changes to the Programs API should be performed asynchronously.

Internally, the API endpoint for course runs will parse the course_key into its component parts (org, course, run).  A get-or-create operation will ensure that records exist corresponding to the org (in Organization) and course (in CourseCode).  If the CourseCode is being created for the first time, the course run's title should be used for the display_name of the CourseCode.  If the Organization is being created for the first time (which should happen rarely, if ever, assuming Organizations are synced first), the org part will be used for both the key and the display_name.

 

Selection of Course Run Modes

Course runs themselves are not duplicated in the service.  Administrative tools used to build Programs will use our enrollment API to fetch listings of available runs and modes, filtered by an organization and course code selected using Admin interfaces.  (Support for these filters needs to be added to the enrollment API.)  When selections are made, the selected course key, mode (slug), and SKU (if used) will be used to create ProgramCourseRunMode records in the service. 

API

General notes

Unless otherwise specified in endpoint details,

...