-
Notifications
You must be signed in to change notification settings - Fork 11
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
ADR for Units and Containers #240
Comments
High Level Requirements (non-exhaustive)UnitsThe first concrete use case for a more generalized Container capability is to model Units for Libraries and eventually Courses. Dynamic ContentWe must support permutations of content in containers that is customized for a group of people or even an individual learner. Examples of this:
ExtensiblePlugin authors must be able to create their own container types, as well as their own dynamic content types. Course HierarchyCourses currently have a hierarchy of Course → Section → Subsection → Unit, and we must be able to represent this in Learning Core. This representation does not have to be represented as nested Containers as it is today in ModuleStore, but we must have some plan for how these larger groupings will work. Fast QueriesA drawback of XBlock-based dynamic children has been poor performance. The system should be created so that queries to get the content for a given user are predictable and fast. While invoking plugin code may be unavoidable for assigning a user to a particular variant of dynamic content, the system should be able to read these assignments without invoking plugin code. Independent of XBlockWe must support current XBlocks that have dynamic children (LibraryContentBlock, SplitTestBlock, and RandomizeBlock), but nothing in Learning Core should require or assume XBlocks. Learning Core should hold the primitives that are needed to build these XBlocks on top of, but should be more broadly usable for Components that are not XBlocks. HistoryContainers should be able to differentiate between changes in the metadata of the container itself (e.g. title, ordering of contents, adding or removing content), vs. changes to the contents (e.g. a component in a Unit is updated with new text). Efficient StorageThe Split ModuleStore system for storing course content has the unfortunate property that even minor changes require large writes of the entire structure, resulting in a lot of wasted space. Changes to the content of a Container should ideally not require rewriting a new version of the Container. ScaleAn individual Container must scale to at least 100 items, though ideally it should work for up to a 1000 (TBD how much of a requirement this is). The median size of Containers will be much smaller, say ~10, give or take. |
Sketch of ModelsThese are the models that I've sketched out to try to capture:
Note that we could implement
|
Impact on PublishingRight now, this is sketched out with
Most of these edge cases are to avoid the case where we have an unpinned reference from a Container and expect a published version of a child element to exist, but find that it does not. The thing is that we could try to accommodate this by moving containers entirely into publishing. And it's possible that would be clearer/more concise. But in general we've tried to make apps really narrowly scoped, and I think that's been generally good for reasoning about things. I also suspect that But in any case, something to talk about in the ADR (or multiple ADRs if we want to split this out). |
Separate app for Learner composition of UnitsWe're going to eventually need a model that maps Learners to a unique(Selector + Variant), maybe with version information. That doesn't belong in the
|
Rejected AlternativesThings we discussed at various points... Use content groups to handle all dynamic content.Modulestore content uses the idea of content groups and user partitions in order to limit what the user sees from a superset of content. For instance, a Component might be marked to be in the "licensed" content group that an institution may legally only show to its own on-campus students. The LMS checks to see if the user is in a user partition that has access to the "licensed" content group and filters it out if they are not. While this approach works well when certain groups see a little more or less content than other groups, it requires us to encode every possible permutation of the components into a Unit. This becomes prohibitively expensive when there is a very large space of possibilities, e.g. "randomly pick 10 problems from a set of 100, in random order". The expectation is that we will see more dynamic behavior like this as learning content presentations built on Learning Core grow more sophisticated over time. We still intend to use content groups for things like enrollment tracks. Fully materialize the tree for each student.We could have a much simpler structure to read from if we wrote out the container parent-child relationships for each user. In this scenario, every user would have their own customized set of rows for every Unit that had dynamic content. The disadvantage of this approach is that it can use substantially more space, and it scales poorly when content changes. For instance, let's say that a Unit has a SplitTest with two different sets of Components. Then 100K view this content, resulting in half the users getting components Container-type-specific models.Instead of having a general model for capturing parent-child relationships, we could have different models for each relation type (Units, Subsections, Sections, etc.) and utilize some mixin for shared logic. Having a centralized model makes it easier to write and maintain tricky common logic (like handling member deletion and publishing events), and makes it easier to make recursive queries. |
Generalizability of SelectorsOne of the properties of this design that I would really like to keep and explore is the idea that Selectors can be both generalizable and performant. The backend code to run a I'm not sure if this generalizes all the way up to truly adaptive, "show me the next thing" functionality. You could emulate that by constantly updating the Variant that a student sees and making new versions of Units, but it seems like it would waste a lot of space. |
Impact on PruningI described an early attempt at sketching pruning functionality here: One of the assumptions of the pruning plan I had is that we could delete all content associated with a I hope there's a simpler way to think about this. |
@ormsbee: I can't attend Friday's sync meeting, so I'll leave my updates here. Here are some high-level decisions for the container capability based on what I've compiled from #38, this issue, and Dave's input in these last few days. I'm working on the container definitions first and then being more specific with units. The ADRs are far from being done, but I hope to add more details while implementing a POC. I'll let you know once I make further progress. Thanks. |
Here's where I've been implementing the model sketches and some API methods to test some of the operations on containers and units: #254 I'll make sure to add a better cover letter to the draft PRs, both 254 and 251. Also, I'll continue working on the ADRs WIP sections :) |
I'm still working on the implementation in #254 and have left a few comments there where I need some guidance. I've also been updating the ADR with a few comments for you to review: PR #251. Also, a review of the content is very welcome so we know we're on the right path! While that moves forward, I'll start a discussion on publishing to gather input for the ADRs. |
We currently have 3 ADRs addressing what was discussed #251:
Over the past couple of weeks, we've moved forward in discussing these high-level decisions, focusing on the proposal and its implications. In the meantime, I've opened the PR for review as we continue these discussions. |
We need to write an ADR (or multiple ADRs) describing Learning Core's approach to modeling Units in particular and Containers in general.
A lot of this is informed by discussions in:
The text was updated successfully, but these errors were encountered: