Convert from Storage-centric runtimes to Application-centric runtimes

Problem Statement

The core XBlock library is built around the assumption that Runtimes will be implemented for each application. Because of that design intention, there are methods on Runtimes such as handler_url and local_resource_url which really only make sense to be implemented by the hosting application. Unfortunately, in the existing edx-platform implementation, some of the XBlock runtimes are actually supplied by the Modulestore (upon construction of XBlocks and XModuleDescriptors), rather than being supplied by the runtime. This leads to a number of workarounds for those application specific methods, as well as an amount of trickery and juggling so that XBlocks, XModules, and XModuleDescriptors are provided with both the appropriate Runtime and appropriate FieldData for the Application context that they are being used in.

Current State of the System

Class Hierarchies

In Editing Context

In Student Context

Proposal 1: Application-centric Runtimes

In this proposal, we would make two fundamental changes to the platform, while preserving backwards compatibility with XModules.

  1. Create Application level runtimes (for LMS, Studio, and Studio live-preview).
  2. Bind ModuleSystem and DescriptorSystem to those runtimes as XBlock services, rather than as runtimes themselves.

In order for these changes to be successful would need the following:

  1. Move all XBlock-runtime methods out of ModuleSystem and DescriptorSystem
  2. Change Modulestore and bind_for_children to attach services, rather than modifying runtimes
  3. Change XModules and XModuleDescriptors to always use self.system to access ModuleSystem and DescriptorSystem
  4. Change self.system to read either ModuleSystem or DescriptorSystem out of the runtime as services, depending on whether self is an XModule or an XModuleDescriptor
  5. Make Modulestore use the application-supplied XBlock runtime to construct XBlocks, rather than building runtimes to construct XBlocks

Some possible gotchas in the proposal are

  1. Caching: Currently this is done in the DescriptorSystem constructed by the Modulestore. Will that still work in the new proposal?
  2. Runtime multiplicity: Currently, we construct one ModuleSystem per XBlock, and depending on the Modulestore, construct one or many DescriptorSystems. How will these be bound onto the Application runtime in order to preserve the current properties, once we switch to having them as XBlock services.
  3. How do we build this in an incremental fashion? Does it become an unwieldy long-running branch as we iron out all of the issues above?

Proposal 2: Clean-room XBlock Implementation

In this proposal, we would create an XBlock-only runtime that LMS and Studio could use for courses that contain only pure XBlocks.

Pros

  • No backwards compatibility required
  • Incremental approach, once we complete the basic runtime, as we migrate existing XModules over to be pure XBlocks

Cons

  • Large delta before the new functionality is usable by courses
    • Need a minimal set of pure XBlocks before one could actually run a course
    • Need to write data bindings for FieldData
      • This could be a port of SplitModuleStore
      • This could be a new data storage format
  • Need to update all places in LMS and Studio that use Modulestore to use the new pure runtime
    • Unclear whether all modulestore functionality can even be supported yet by a pure XBlock system

Glossary

XModule

The precursor to XBlock. This class is responsible for generating a student-facing HTML rendering of course content. It is bound to a particular student on instantiation.

XModuleDescriptor

The second half of the precursor to XBlock. This class is responsible for generating an HTML rendering for editing course content. It has no associated student information. As part of the backwards-compatibility layer between XModules and XBlocks in edx-platform, this class will actually proxy a number of attributes through to an instantiated XModule, so that edx-platform only has a single object that responds to methods/attributes for both XModule and XModuleDescriptor (this provides an interface consistent with XBlock, which is only a single object for both responsibilities).

DescriptorSystem

This class provides an interface between XModuleDescriptors and the rest of edx-platform. The intention is to abstract the XModuleDescriptor away from the details about how external systems are implemented.

ModuleSystem

As with DescriptorSystem, this class exists to provide an interface between the XModule and the rest of the LMS. It has become a dumping ground for many responsibilities, which will in the future be abstracted as XBlock services instead.

"Pure" XBlock

This is used to mean an XBlock that doesn't inherit from XModule or XModuleDescriptor, and accesses none of the DescriptorSystem or ModuleSystem interfaces to access edx-platform.