openedx / openedx-learning

GNU Affero General Public License v3.0
5 stars 8 forks source link

Changes for v2 content libs #143

Closed ormsbee closed 7 months ago

ormsbee commented 7 months ago

Work to support https://github.com/openedx/edx-platform/pull/34066

This bumps the version for openedx-learning to 0.5.0.

Some highlights:

Squashed commit message:

This commit adds a number of features needed to accomodate content
libraries. These are all collected together because this work was done
while iteratively making more and more of libraries functional, and it
was difficult to properly separate out later.

This bumps the version to 0.5.0.

New publishing API functions:

* Learning Packages
    * get_learning_package
    * get_learning_package_by_key,
    * update_learning_package

* Publishable Entities
    * get_publishable_entity and
    * get_publishable_entity_by_key

* Draft/Publishing
    * get_last_publish
    * get_all_drafts
    * get_entities_with_unpublished_changes
    * get_entities_with_unpublished_deletes
    * get_published_version
    * set_draft_version
    * soft_delete_draft
    * reset_drafts_to_published

New Components API functions:

* create_next_version
* get_component_by_key
* component_exists_by_key
* get_components

PublishableEntityMixin improvements:

* New property methods: latest, has_unpublished_changes
* Existing methods were improved to use model-cached values.

Encoding fixes:

* collations for multiple fields were changed to be case insensitive in
  order to better support simple text searches.

Model optimizations:

* created the WithRelationsManager to more easily define querysets that
  involve adding select_related fields. This was used to elininate a
  number of n+1 queries that came up during libraries development.
* PublishableEntityVersion.version_num was reduced to a 4-byte
  PositiveIntegerField instead of using the 8-byte default for
  openedx_learning apps (it's assumed we will never make more than 2
  billion versions of a particular PublishableEntity). This was done to
  help reduce the size of indexes.

Typing:

* type annotations were added to many functions and test functions.
ormsbee commented 7 months ago

Okay, I think I've gotten all the basic changes in there. Now to fix old tests and add new ones for the new functionality. Then a final re-base and version bump.

ormsbee commented 7 months ago

Old tests are fixed, added a few new ones, still some more to go. I'll deal with mypy last.

ormsbee commented 7 months ago

@kdmccormick, @bradenmacdonald: If you have some time, please give this a review pass. The tests aren't fully there yet, but I'd appreciate your thoughts on the API additions especially.

ormsbee commented 7 months ago

Okay, I wrote the tests, made changes based on the review comments, and the linters are appeased. I'm going to do the _pk refactoring now, but with any luck I'm hoping this can merge today.

ormsbee commented 7 months ago

Okay, slight delay because I noticed that it's always doing the work of loading all components no matter the pagination params in the REST API. I think this is a problem on the edx-platform side, but I'm looking into it to be sure.

ormsbee commented 7 months ago

Okay, I wrote the tests, made changes based on the review comments, and the linters are appeased. I'm going to do the _pk refactoring now, but with any luck I'm hoping this can merge today.

I went back and forth on _id vs. _pk for a bit and then decided to punt entirely by making these arguments positional-only for the moment. >_<

ormsbee commented 7 months ago

Also, I tracked down the query issue to something in edx-platform, and I'll have an update for that PR with the fix later. Part of it points to an issue that our internal APIs have with QuerySets and pagination. Namely, the pattern for DRF and Django in general is QuerySet -> Pagination -> Serialization. So it gets awkward when we're returning something from an API that we want to be QuerySet-like in that it's filterable and pageable, but also presents something that is not actually a model. I hacked up something before that wrapped the __iter()__ call and did serialization that seemed to work, but I feel like that's probably too much hackery to want to support in the longer term.

Anyhow, I'll discuss it more on the other PR.

ormsbee commented 7 months ago

It occurred to me while looking at some recent comments in the wiki w.r.t. library content needs that we probably want to have ComponentType represented as its own model. Partly for saving space, but mostly because it gives us something to later hang policy off of on a per-type basis, e.g. "videos are okay to show in libraries, SGA blocks are experimental for library use".

I implemented that this evening. It was pleasantly straightforward, and it also gets rid of our having to tell pylint to ignore our use of type as a variable name. Tests already pass, so hopefully I can just do it as a fast-follow to this PR tomorrow if this merges.

ormsbee commented 7 months ago

BTW, the only reason this build isn't green is because I was a doofus and mis-spelled a couple of conventional commit messages. Please know that it's ready for final review, and I'll squash it at the end.

bradenmacdonald commented 7 months ago

Question that's not directly related: Can you use add_content_to_component_version to modify a ComponentVersion that has already been published?

ormsbee commented 7 months ago

Thanks folks! I squashed my commits and made a decent commit message out of it. Will merge once things are green.

ormsbee commented 7 months ago

Question that's not directly related: Can you use add_content_to_component_version to modify a ComponentVersion that has already been published?

Yes, you can. 95% of the time you shouldn't, but some real use cases came up where doing so seems like it would be beneficial: