-
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
[WIP] feat: implement sketch models and api for interactions based on 0017/18 #254
base: main
Are you sure you want to change the base?
Conversation
Thanks for the pull request, @mariajgrimaldi! What's next?Please work through the following steps to get your changes ready for engineering review: 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. 🔘 Update the status of your PRYour PR is currently marked as a draft. After completing the steps above, update its status by clicking "Ready for Review", or removing "WIP" from the title, as appropriate. 🔘 Let us know that your PR is ready for review:Who will review my changes?This repository is currently maintained by Where can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:
When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
new_user_defined_list = create_entity_list_with_rows( | ||
entity_pks=publishable_entities_pk, | ||
draft_version_pks=[None] * len(publishable_entities_pk), | ||
published_version_pks=[None] * len(publishable_entities_pk), | ||
) | ||
container_version = ContainerEntityVersion.objects.create( | ||
publishable_entity_version=publishable_entity_version, | ||
container_id=container_pk, | ||
defined_list=new_user_defined_list, | ||
initial_list=last_version.initial_list, | ||
frozen_list=last_version.defined_list, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a naive approach to the implementation for the sake of simplicity. Now, I'll modify it to comply with the requirements I've compiled in the cover letter, so the code will probably be different when you see this.
Still, I have some questions about the requirements:
The defined_list is the EntityList that the author defines. This should never change, even if the things it references get soft-deleted (because we'll need to maintain it for reverts).
Questions
How do we ensure this doesn't change even if references get soft deleted?Because soft-deletion is removing references in the draft log for a version, so it's not deleted nor removed.- Is the discard operation (made changes that created a new draft version) different from revert?
initial_list is an EntityList where all the versions are pinned, to show what the exact versions of the children were at the time that the Container was created. We could technically derive this, but it would be awkward to query.
Questions
Let's say a version for a container is created referencing the latest versions for all members. Then, we manually pin all members when creating this list. Pinning a version would mean pointing the EntityListRow draft/published version to the latest versions at the time for this particular case, am I right?YES!
frozen_list is mutable if and only if there are unpinned references in defined_list. In that case, frozen_list should start as None, and be updated to pin references when another version of this Container becomes the Draft version. But if this version ever becomes the Draft again (e.g. the user hits "discard changes" or some kind of revert happens), then we need to clear this back to None.
Questions
Even if there's an unpinned reference, should frozen_list start as None?YES!When a new version is created and frozen_list is None, then we should pin all references from the defined_list when creating the new frozen_list?YES!Should we explicitly check when a version becomes draft again, so we can clear the frozen list? How could we detect a version becomes a draft again?Solved in a sync discussion!
return ContainerEntity.objects.get(pk=pk) | ||
|
||
|
||
def get_defined_list_for_container_version( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
I wonder whether we should provide this kind of API method or whether users of the containers API should be unaware of EntityListRows' existence.
# TODO: how can we enforce that publishable entities must be components? | ||
# This currently allows for any publishable entity to be added to a unit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question
Should we enforce the fact that publishable entities added to a unit are components here? Or should this be flexible enough to provide methods to do so but not explicitly enforce it?
unit_version_pk: The unit version ID. | ||
""" | ||
unit_version = UnitVersion.objects.get(pk=unit_version_pk) | ||
return container_api.get_defined_list_for_container_version(unit_version.container_entity_version) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self:
I have the same question here about whether to return entity lists or publishable entities. I'm guessing the latter, but I'd like to confirm.
60fdb44
to
1f10aec
Compare
Hey @ormsbee! I’ve been making progress on this and left some comments in the code where I could use some guidance. Thanks a ton for the help! I'm pushing changes as I go, so I'm sorry if some comments seem out of date, questions are still relevant, though. Code itself might not be ready for review, so I'd hold off on a review for now. |
publishable_entities_pk: list[int], | ||
draft_version_pks: list[int | None], | ||
published_version_pks: list[int | None], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
Should the draft/published versions be derived somehow from the publishable entities?
This is still under discussion in the ADR, so we'll probably use a single reference to the versions.
new_user_defined_list = create_entity_list_with_rows( | ||
entity_pks=publishable_entities_pk, | ||
draft_version_pks=draft_version_pks, | ||
published_version_pks=published_version_pks, | ||
) | ||
new_frozen_list = copy_rows_to_new_entity_list( | ||
rows=get_defined_list_rows_for_container_version(last_version) | ||
) | ||
|
||
container_version = ContainerEntityVersion.objects.create( | ||
publishable_entity_version=publishable_entity_version, | ||
container_id=container_pk, | ||
defined_list=new_user_defined_list, | ||
initial_list=last_version.initial_list, | ||
frozen_list=new_frozen_list, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self:
Here, I'm creating a new defined_list
(with new rows) for each new version and also copying things over from the previously defined_list
into a new frozen_list
(also, with new rows). This is done to comply with:
defined_list
should never change for a given ContainerEntityVersion to simplify reasoning.- The defined_list is the EntityList that the author defines. This should never change, even if the things it references get soft-deleted (because we'll need to maintain it for reverts).
But we also have this requirement:
- Ordering should be treated as immutable–if the ordering needs to change, we create a new EntityList and copy things over.
So no new entity list rows for defined_lists
should be created if the ordering doesn't change or versions are not pinned, but new members are added. Which I'm currently not considering.
I remember discussing this with Dave a couple of weeks ago too, so implementing it seems like the right approach here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm testing my changes out before pushing, I'm hoping I can do it today.
new_frozen_list = copy_rows_to_new_entity_list( | ||
rows=get_defined_list_rows_for_container_version(last_version) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self:
This is pinning references for the next version of the container instead of pinning versions for the previous version. Which is what should happen according to this comment: https://github.com/openedx/openedx-learning/pull/254/files#diff-6f2c589dc4ba5960e91d39f6488eb5e2e2e63ddaff63a75909091c760b877802R142-R147
So, when have two scenarios when creating a new version:
The author defined list has unpinned references
- The frozen_list of the current container is updated to pin specific versions of the members
- The next version frozen state points to None
The author defined list has pinned references
- The current version frozen list points to the current defined list
- The next version frozen list points to the new defined list
And any other combination between the two in case defined_list can pin/unpin references
Description
This implementation is based on the high-level decisions made in #251
Unit tests are now the way I'm testing this out.