-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat: upstream-downstream entity linking #36111
base: master
Are you sure you want to change the base?
feat: upstream-downstream entity linking #36111
Conversation
Thanks for the pull request, @navinkarkera! This repository is currently maintained by @openedx/wg-maintenance-edx-platform. Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.
|
e3e8965
to
54565b7
Compare
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 mostly working :) But when I import a course, the links don't get updated, and I'm not sure why not.
Most of my comments are nits about reducing unneeded log volume, or making logs more informative.
@@ -26,6 +26,8 @@ | |||
IMPORT_COURSE_DETAILS = Signal() | |||
# providing_args=["courserun_key"] | |||
DELETE_COURSE_DETAILS = Signal() | |||
# providing_args=["courserun_key", "old_name", "new_name"] | |||
COURSE_NAME_CHANGED = Signal() |
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.
Hmm.. I think we're supposed to put new signals in https://github.com/openedx/openedx-events so they can be used outside of the platform? But no worries if this is beyond the scope of this PR.
# update_course_name_in_upstream_links.delay( | ||
# str(previous_course_overview.id), | ||
# updated_course_overview.display_name_with_default | ||
# ) |
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.
TODO: remove commented-out code
Create or update upstream->downstream link in database for given xblock. | ||
""" | ||
if not xblock.upstream: | ||
log.info(f"No upstream found for xblock: {xblock.usage_key}") |
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.
nit: this will generate a lot of log messages when people change course names, because most course blocks aren't upstream-linked.
log.info(f"No upstream found for xblock: {xblock.usage_key}") |
except ObjectDoesNotExist: | ||
log.exception("Library block not found!") | ||
lib_component = None | ||
authoring_api.update_or_create_entity_link( |
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.
If we're returning None
when we do nothing, shouldn't this return something truthy?
@receiver(XBLOCK_CREATED) | ||
@receiver(XBLOCK_UPDATED) | ||
def create_or_update_upstream_downstream_link_handler(**kwargs): | ||
""" | ||
Automatically create or update upstream->downstream link in database. | ||
""" | ||
xblock_info = kwargs.get("xblock_info", None) | ||
if not xblock_info or not isinstance(xblock_info, XBlockData): | ||
log.error("Received null or incorrect data for event") | ||
return | ||
|
||
create_or_update_xblock_upstream_link.delay(str(xblock_info.usage_key)) |
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 expected that this handler would take care of creating links when importing a course, but it didn't! I only saw a log message for the top-level course block:
No upstream or upstream_version found for xblock: block-v1:OpenCraft+DemoX+1+type@course+block@course
I had to run the management command to set my imported course links.
ensure_cms("create_or_update_xblock_upstream_link may only be executed in a CMS context") | ||
xblock = modulestore().get_item(UsageKey.from_string(usage_key)) | ||
if not xblock.upstream or not xblock.upstream_version: | ||
TASK_LOGGER.info(f"No upstream or upstream_version found for xblock: {xblock.usage_key}") |
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.
ditto nit: this will generate a lot of log messages when people update their blocks -- I think we should remove this line.
TASK_LOGGER.info(f"No upstream or upstream_version found for xblock: {xblock.usage_key}") |
try: | ||
lib_component = get_component_from_usage_key(upstream_usage_key) | ||
except ObjectDoesNotExist: | ||
log.exception("Library block not found!") |
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 don't think we need a log.exception
here, because this could happen as part of normal operation, e.g if the lib component gets deleted. But it would be good to know a bit more about what it means:
log.exception("Library block not found!") | |
log.error(f"Library component not found for {upstream_usage_key} -- removing from upstream link") |
try: | ||
course_name = CourseOverview.get_from_id(xblock.course_id).display_name_with_default | ||
except CourseOverview.DoesNotExist: | ||
TASK_LOGGER.exception(f'Could not find course: {xblock.course_id}') |
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.
Do we need to log the whole exception? I think an error is enough:
TASK_LOGGER.exception(f'Could not find course: {xblock.course_id}') | |
TASK_LOGGER.error(f'Could not find course: {xblock.course_id}') |
try: | ||
course_name = CourseOverview.get_from_id(course_key).display_name_with_default | ||
except CourseOverview.DoesNotExist: | ||
TASK_LOGGER.exception(f'Could not find course: {course_key_str}') |
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.
ditto nit: do we need to log the whole exception? I don't think it will tell us much more than the error message does.
And shouldn't we mark the task as failed?
TASK_LOGGER.exception(f'Could not find course: {course_key_str}') | |
TASK_LOGGER.error(f'Could not find course: {course_key_str}') | |
course_status.status = CourseLinksStatusChoices.FAILED | |
course_status.save() |
updated_time = datetime.now(timezone.utc) | ||
get_entity_links({"downstream_context_key": course_key_str}).update( | ||
downstream_context_title=new_course_name, | ||
updated=updated_time |
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.
nit: if updated
becomes an auto-now
field, we don't have to specify it here.
@pomegranited Thanks for the review! About the course imports, I am working on it (I did mention it in the description but it was probably after you started reviewing it). |
54565b7
to
60b4f43
Compare
Description
Adds tasks, signal handlers and api's for adding, updating and deleting upstream->downstream links in database.
Supporting information
Private-ref
: FAL-4004Testing instructions
tutor images build openedx-dev && tutor dev launch -I --skip-build
in your tutor nightly setup.tutor dev exec cms ./manage.py cms recreate_upstream_links --all
for creating upstream links for all courses.tutor dev exec cms ./manage.py cms recreate_upstream_links --course <course-id>
for creating upstream links for a course.--force
argument to recreate upstream links for already indexed courses.Library content
orProblem bank
component or Copy-pasting any library content in any course. The corresponding links should be created in database.Advanced Settings
page.Deadline
"None" if there's no rush, or provide a specific date or event (and reason) if there is one.
Other information
Include anything else that will help reviewers and consumers understand the change.