Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
43a31b0
feat: update content libraries API to use upstream collection events
bradenmacdonald Apr 21, 2026
c957e71
feat: update content libraries API to use upstream entity changed events
bradenmacdonald Apr 22, 2026
b9cde35
feat: update content libraries API to use upstream entity published e…
bradenmacdonald Apr 23, 2026
0b7f39e
temp: use openedx-core 0.45-preview with new events
bradenmacdonald Apr 23, 2026
594a845
feat: more sophisticated handling of sync-vs-async for library edits
bradenmacdonald Apr 23, 2026
4554ade
chore: fix lint issues
bradenmacdonald Apr 23, 2026
488aa01
refactor: rename the new signals for more clarity
bradenmacdonald Apr 24, 2026
49f7555
test: fix test cases that weren't calling on_commit hooks
bradenmacdonald Apr 24, 2026
eaead7d
test: fix test cases that weren't calling on_commit hooks
bradenmacdonald Apr 24, 2026
3627c41
feat: improve how collection events work (to be more targeted)
bradenmacdonald Apr 24, 2026
dc2472a
test: update search indexing tests
bradenmacdonald Apr 24, 2026
0a51690
fix: correct logic for container events, update search index tests
bradenmacdonald Apr 25, 2026
f3961bf
refactor: simplify the logic in check_container_content_changes
bradenmacdonald Apr 25, 2026
d067ae1
chore: fix lint
bradenmacdonald Apr 25, 2026
a08e1cd
test: fix unrelated test isolation bug
bradenmacdonald Apr 25, 2026
d3e7fcd
docs: "a lot of" -> "multiple"
bradenmacdonald Apr 25, 2026
f3fcb8f
docs: clarify misleading comment
bradenmacdonald Apr 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def test_home_page_libraries_response(self):
'can_edit': True,
'is_migrated': True,
'migrated_to_title': 'Test Library',
'migrated_to_key': 'lib:name0:test-key',
'migrated_to_key': str(self.lib_key_v2),
'migrated_to_collection_key': 'test-collection',
'migrated_to_collection_title': 'Test Collection',
},
Expand Down Expand Up @@ -364,7 +364,7 @@ def test_home_page_libraries_response(self):
'can_edit': True,
'is_migrated': True,
'migrated_to_title': 'Test Library',
'migrated_to_key': 'lib:name0:test-key',
'migrated_to_key': str(self.lib_key_v2),
'migrated_to_collection_key': 'test-collection',
'migrated_to_collection_title': 'Test Collection',
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""
import ddt
from opaque_keys.edx.keys import UsageKey
from openedx_content.api import signals as content_signals
from openedx_events.content_authoring.signals import (
LIBRARY_BLOCK_DELETED,
XBLOCK_CREATED,
Expand Down Expand Up @@ -405,6 +406,7 @@ class ClipboardPasteFromV2LibraryTestCase(OpenEdxEventsTestMixin, ImmediateOnCom
Test Clipboard Paste functionality with a "new" (as of Sumac) library
"""
ENABLED_OPENEDX_EVENTS = [
content_signals.ENTITIES_DRAFT_CHANGED.event_type, # Required for library events to work
LIBRARY_BLOCK_DELETED.event_type,
XBLOCK_CREATED.event_type,
XBLOCK_DELETED.event_type,
Expand Down Expand Up @@ -491,7 +493,8 @@ def test_paste_from_library_read_only_tags(self):
assert object_tag.is_copied

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

# ...the copied tags remain, but should no longer be marked as "copied"
object_tags = tagging_api.get_object_tags(new_block_key)
Expand Down
4 changes: 0 additions & 4 deletions cms/djangoapps/modulestore_migrator/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -895,13 +895,9 @@ def _migrate_container(
).publishable_entity_version

# Publish the container
# Call post publish events synchronously to avoid
# an error when calling `wait_for_post_publish_events`
# inside a celery task.
libraries_api.publish_container_changes(
container.container_key,
context.created_by,
call_post_publish_events_sync=True,
)
context.used_container_slugs.add(container.container_key.container_id)
return container_publishable_entity_version, None
Expand Down
45 changes: 18 additions & 27 deletions openedx/core/djangoapps/content/search/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,36 +883,27 @@ def upsert_library_collection_index_doc(collection_key: LibraryCollectionLocator
If the Collection is not found or disabled (i.e. soft-deleted), then delete it from the search index.
"""
doc = searchable_doc_for_collection(collection_key)
update_items = False

# Soft-deleted/disabled collections are removed from the index
# and their components updated.
if doc.get("_disabled"):
_delete_index_doc(doc[Fields.id])

update_items = True

# Hard-deleted collections are also deleted from the index,
# but their components are automatically updated as part of the deletion process, so we don't have to.
elif not doc.get(Fields.type):
# Soft-deleted/disabled/hard-deleted collections are removed from the index:
# (If the collection is soft-deleted, searchable_doc_for_collection() sets `_disabled: True`)
# (If the collection is hard-deleted, searchable_doc_for_collection() leaves all fields other than ID empty)
if doc.get("_disabled") or not doc.get(Fields.type):
_delete_index_doc(doc[Fields.id])
return

# Otherwise, upsert the collection.
# Newly-added/restored collection get their components updated too.
else:
already_indexed = _get_document_from_index(doc[Fields.id])
if not already_indexed:
update_items = True

_update_index_docs([doc])

# Asynchronously update the collection's components "collections" field
if update_items:
from .tasks import update_library_components_collections as update_components_task
from .tasks import update_library_containers_collections as update_containers_task
# Normal case - update the collection doc.
_update_index_docs([doc])

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


def update_library_components_collections(
Expand Down
Loading
Loading