Lab2: pre-load all level properties for lesson #70246
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Updates the Lab2 framework to pre-load all the level properties in a given lesson when first loading the page, instead of level-by-level like we do today. This reduces overall load times and aims to further reduce lab lifecycle loading inconsistencies.
This change is part of a few broader efforts we've discussed in the Lab2 team around improving and simplifying lab2 architecture. It does not fully solve all those issues (as that would require many more changes in each lab) but hopes to lay the groundwork for future improvements. Read more below on specifics, especially for Lab2/SL developers 🙂
Motivation
Every lab requires level properties to function. These are static, (**mostly) non user-specific properties such as instructions, validation conditions, whether to show/hide certain lab features, etc. Up until now, we've been loading each level's properties individually when the level changes. While this has worked fine, because each lab transition requires a network load before the lab can be mounted, we have scenarios where various bits of data that are meant to represent the same value have different values based on where we are in the loading lifecycle.
We addressed some of this previously by passing level properties as props to labs (as opposed to reading them from redux). This gives labs some guarantee that a) level properties are always defined (because they must be) and b) the level properties they receive as their props are indeed the properties for the current level (as opposed to before where the redux level properties could be briefly out of sync while the load was in progress). However, given that all this level data is mostly static and known beforehand anyway, we can get rid of these interim loads altogether if we load the all the level's properties up front.
Important: Note that we still do wait for the lab's sources to load before presenting the lab view. This is because labs currently expect level properties and sources to update at the same time, and before changing this, we'd need to go into each lab and update behavior accordingly. More on the future state of source management below.
**mostly: level properties as written currently require a
current_userwhich renders them non-cacheable. My thinking is to move any user-dependent properties out to a separate API, similar to or integrated withuser_app_options.Immediate Benefits
Long-term Benefits/Ideas
As stated above, this change doesn't really affect how project-backed lab views themselves process level properties, because they still receive them after their sources have loaded. Going forward, my thought here is that we move source management/loading into a wrapper like SourcesContainer and/or lab2ProjectRedux that labs can hook into. What this means is that lab views can go ahead and mount as soon as the level transitions (because their level properties are already available), and then call into the source management system to read their project sources and if the sources are still loading. This would, for example, allow labs to show parts of the UI immediately and only put up a loading spinner over the code workspace. Something like this:
Fully decoupling project source loading from level properties loading means that boundaries between lab transitions are much clearer, and less transition UI. We can consider a "no-fade" transition between levels that have the same lab and see UI elements update in place, if desired.
LevelPropertiesContext vs ProgressRedux vs Lab2Redux??
Important for SL/Lab2 engineers: one thing this does make more complicated is knowing what the different values in different systems refer to, now that we're introducing a LevelPropertiesContext. Again, the reason this is still fragmented is to avoid updating the logic in every lab, but hopefully this helps in the interim 🙂
state.progress.currentLevelId&useLevelProperties()update immediately upon level changestate.lab.levelProperties& level properties in lab props update after the level's project sources have loadedIn other words:
useLevelProperties()hook.Eventually (🤞) this will all be consolidated and all level properties will update immediately and consistently.
Video: static level change without loads
Lab2-no-load-static-levels.mov
Links
Testing story
Tested on various lab2 labs, level progressions, and standalone levels.