Skip to content

Commit 7694a68

Browse files
feat: update content libraries API to use events from openedx-core (#38437)
* chore: bump openedx-core to 0.46.0 * feat: update content libraries API to use events from openedx_content * fix: better dispatching/waiting for async library event handlers Now, the search index (and anything else that listens for events) will stay up to date regardless of whether one uses the content_libraries high-level API or the low-level openedx_content APIs to make changes to content. Co-Authored-By: Claude <[email protected]>
1 parent f6eda03 commit 7694a68

24 files changed

Lines changed: 928 additions & 1010 deletions

File tree

cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ def test_home_page_libraries_response(self):
329329
'can_edit': True,
330330
'is_migrated': True,
331331
'migrated_to_title': 'Test Library',
332-
'migrated_to_key': 'lib:name0:test-key',
332+
'migrated_to_key': str(self.lib_key_v2),
333333
'migrated_to_collection_key': 'test-collection',
334334
'migrated_to_collection_title': 'Test Collection',
335335
},
@@ -364,7 +364,7 @@ def test_home_page_libraries_response(self):
364364
'can_edit': True,
365365
'is_migrated': True,
366366
'migrated_to_title': 'Test Library',
367-
'migrated_to_key': 'lib:name0:test-key',
367+
'migrated_to_key': str(self.lib_key_v2),
368368
'migrated_to_collection_key': 'test-collection',
369369
'migrated_to_collection_title': 'Test Collection',
370370
}

cms/djangoapps/contentstore/views/tests/test_clipboard_paste.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""
66
import ddt
77
from opaque_keys.edx.keys import UsageKey
8+
from openedx_content.api import signals as content_signals
89
from openedx_events.content_authoring.signals import (
910
LIBRARY_BLOCK_DELETED,
1011
XBLOCK_CREATED,
@@ -405,6 +406,7 @@ class ClipboardPasteFromV2LibraryTestCase(OpenEdxEventsTestMixin, ImmediateOnCom
405406
Test Clipboard Paste functionality with a "new" (as of Sumac) library
406407
"""
407408
ENABLED_OPENEDX_EVENTS = [
409+
content_signals.ENTITIES_DRAFT_CHANGED.event_type, # Required for library events to work
408410
LIBRARY_BLOCK_DELETED.event_type,
409411
XBLOCK_CREATED.event_type,
410412
XBLOCK_DELETED.event_type,
@@ -491,7 +493,8 @@ def test_paste_from_library_read_only_tags(self):
491493
assert object_tag.is_copied
492494

493495
# If we delete the upstream library block...
494-
library_api.delete_library_block(self.lib_block_key)
496+
with self.captureOnCommitCallbacks(execute=True): # make event handlers fire now, within TestCase transaction
497+
library_api.delete_library_block(self.lib_block_key)
495498

496499
# ...the copied tags remain, but should no longer be marked as "copied"
497500
object_tags = tagging_api.get_object_tags(new_block_key)

cms/djangoapps/modulestore_migrator/tasks.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -895,13 +895,9 @@ def _migrate_container(
895895
).publishable_entity_version
896896

897897
# Publish the container
898-
# Call post publish events synchronously to avoid
899-
# an error when calling `wait_for_post_publish_events`
900-
# inside a celery task.
901898
libraries_api.publish_container_changes(
902899
container.container_key,
903900
context.created_by,
904-
call_post_publish_events_sync=True,
905901
)
906902
context.used_container_slugs.add(container.container_key.container_id)
907903
return container_publishable_entity_version, None

openedx/core/djangoapps/content/search/api.py

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -883,36 +883,27 @@ def upsert_library_collection_index_doc(collection_key: LibraryCollectionLocator
883883
If the Collection is not found or disabled (i.e. soft-deleted), then delete it from the search index.
884884
"""
885885
doc = searchable_doc_for_collection(collection_key)
886-
update_items = False
887-
888-
# Soft-deleted/disabled collections are removed from the index
889-
# and their components updated.
890-
if doc.get("_disabled"):
891-
_delete_index_doc(doc[Fields.id])
892-
893-
update_items = True
894-
895-
# Hard-deleted collections are also deleted from the index,
896-
# but their components are automatically updated as part of the deletion process, so we don't have to.
897-
elif not doc.get(Fields.type):
886+
# Soft-deleted/disabled/hard-deleted collections are removed from the index:
887+
# (If the collection is soft-deleted, searchable_doc_for_collection() sets `_disabled: True`)
888+
# (If the collection is hard-deleted, searchable_doc_for_collection() leaves all fields other than ID empty)
889+
if doc.get("_disabled") or not doc.get(Fields.type):
898890
_delete_index_doc(doc[Fields.id])
891+
return
899892

900-
# Otherwise, upsert the collection.
901-
# Newly-added/restored collection get their components updated too.
902-
else:
903-
already_indexed = _get_document_from_index(doc[Fields.id])
904-
if not already_indexed:
905-
update_items = True
906-
907-
_update_index_docs([doc])
908-
909-
# Asynchronously update the collection's components "collections" field
910-
if update_items:
911-
from .tasks import update_library_components_collections as update_components_task
912-
from .tasks import update_library_containers_collections as update_containers_task
893+
# Normal case - update the collection doc.
894+
_update_index_docs([doc])
913895

914-
update_components_task.delay(str(collection_key))
915-
update_containers_task.delay(str(collection_key))
896+
# We do NOT update the individual entities (components/containers) in the collection here.
897+
# This event can be called if a single entity is added or removed from the collection (to update the "# of items in
898+
# collection" field (Fields.num_children), and we don't want to re-index all entities in that case).
899+
#
900+
# If the collection is renamed, the COLLECTION_CHANGED signal will be emitted, and content_libraries will handle it
901+
# and emit CONTENT_OBJECT_ASSOCIATIONS_CHANGED for every entity in the collection, which will update their
902+
# "collections" field in the search index.
903+
#
904+
# If the collection is enabled/disabled/deleted, the COLLECTION_CHANGED signal will include all entities in the
905+
# collection as added or removed, which the same libraries signal handler will convert to
906+
# CONTENT_OBJECT_ASSOCIATIONS_CHANGED events, which will update them.
916907

917908

918909
def update_library_components_collections(

0 commit comments

Comments
 (0)