Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
45 changes: 41 additions & 4 deletions docs/hooks/events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,18 +192,55 @@ Content Authoring Events
- *Type*
- *Date added*

* - `COURSE_CATALOG_INFO_CHANGED <https://github.com/openedx/openedx-events/blob/main/openedx_events/content_authoring/signals.py#L23>`_
* - `COURSE_CATALOG_INFO_CHANGED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L25>`_
- org.openedx.content_authoring.course.catalog_info.changed.v1
- `2022-08-24 <https://github.com/openedx/edx-platform/blob/a8598fa1fac5e26ac212aa588e8527e727581742/cms/djangoapps/contentstore/signals/handlers.py#L111>`_

* - `XBLOCK_PUBLISHED <https://github.com/openedx/openedx-events/blob/main/openedx_events/content_authoring/signals.py#L30>`_
* - `XBLOCK_PUBLISHED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L63>`_
- org.openedx.content_authoring.xblock.published.v1
- `2022-12-06 <https://github.com/openedx/edx-platform/blob/master/xmodule/modulestore/mixed.py#L926>`_

* - `XBLOCK_DELETED <https://github.com/openedx/openedx-events/blob/main/openedx_events/content_authoring/signals.py#L42>`_
* - `XBLOCK_DELETED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L75>`_
- org.openedx.content_authoring.xblock.deleted.v1
- `2022-12-06 <https://github.com/openedx/edx-platform/blob/master/xmodule/modulestore/mixed.py#L804>`_

* - `XBLOCK_DUPLICATED <https://github.com/openedx/openedx-events/blob/main/openedx_events/content_authoring/signals.py#L54>`_
* - `XBLOCK_DUPLICATED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L87>`_
- org.openedx.content_authoring.xblock.duplicated.v1
- `2022-12-06 <https://github.com/openedx/edx-platform/blob/master/cms/djangoapps/contentstore/views/item.py#L965>`_

* - `XBLOCK_CREATED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L36>`_
- org.openedx.content_authoring.xblock.created.v1
- 2023-07-20

* - `XBLOCK_UPDATED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L47>`_
- org.openedx.content_authoring.xblock.updated.v1
- 2023-07-20

* - `COURSE_CREATED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L123>`_
- org.openedx.content_authoring.course.created.v1
- 2023-07-20

* - `CONTENT_LIBRARY_CREATED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L134>`_
- org.openedx.content_authoring.content_library.created.v1
- 2023-07-20

* - `CONTENT_LIBRARY_UPDATED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L145>`_
- org.openedx.content_authoring.content_library.updated.v1
- 2023-07-20

* - `CONTENT_LIBRARY_DELETED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L156>`_
- org.openedx.content_authoring.content_library.deleted.v1
- 2023-07-20

* - `LIBRARY_BLOCK_CREATED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L167>`_
- org.openedx.content_authoring.content_library.created.v1
- 2023-07-20

* - `LIBRARY_BLOCK_UPDATED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L178>`_
- org.openedx.content_authoring.content_library.updated.v1
- 2023-07-20

* - `LIBRARY_BLOCK_DELETED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L189>`_
- org.openedx.content_authoring.content_library.deleted.v1
- 2023-07-20

104 changes: 83 additions & 21 deletions openedx/core/djangoapps/content_libraries/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@
LibraryUsageLocatorV2,
LibraryLocator as LibraryLocatorV1
)
from openedx_events.content_authoring.data import ContentLibraryData, LibraryBlockData
from openedx_events.content_authoring.signals import (
CONTENT_LIBRARY_CREATED,
CONTENT_LIBRARY_DELETED,
CONTENT_LIBRARY_UPDATED,
LIBRARY_BLOCK_CREATED,
LIBRARY_BLOCK_DELETED,
LIBRARY_BLOCK_UPDATED,
)

from organizations.models import Organization
from xblock.core import XBlock
Expand All @@ -90,14 +99,7 @@
ContentLibraryPermission,
ContentLibraryBlockImportTask,
)
from openedx.core.djangoapps.content_libraries.signals import (
CONTENT_LIBRARY_CREATED,
CONTENT_LIBRARY_UPDATED,
CONTENT_LIBRARY_DELETED,
LIBRARY_BLOCK_CREATED,
LIBRARY_BLOCK_UPDATED,
LIBRARY_BLOCK_DELETED,
)

from openedx.core.djangoapps.xblock.api import (
get_block_display_name,
get_learning_context_impl,
Expand Down Expand Up @@ -452,7 +454,11 @@ def create_library(
)
except IntegrityError:
raise LibraryAlreadyExists(slug) # lint-amnesty, pylint: disable=raise-missing-from
CONTENT_LIBRARY_CREATED.send(sender=None, library_key=ref.library_key)
CONTENT_LIBRARY_CREATED.send_event(
content_library=ContentLibraryData(
Comment thread
rpenido marked this conversation as resolved.
Outdated
library_key=ref.library_key
)
)
Comment thread
navinkarkera marked this conversation as resolved.
Outdated
return ContentLibraryMetadata(
key=ref.library_key,
bundle_uuid=bundle.uuid,
Expand Down Expand Up @@ -602,7 +608,11 @@ def update_library(
assert isinstance(description, str)
fields["description"] = description
update_bundle(ref.bundle_uuid, **fields)
CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=ref.library_key)
CONTENT_LIBRARY_UPDATED.send_event(
content_library=ContentLibraryData(
library_key=ref.library_key
)
)


def delete_library(library_key):
Expand All @@ -617,7 +627,11 @@ def delete_library(library_key):
# system, which is a better state than having a reference to a library with
# no backing blockstore bundle.
ref.delete()
CONTENT_LIBRARY_DELETED.send(sender=None, library_key=ref.library_key)
CONTENT_LIBRARY_DELETED.send_event(
content_library=ContentLibraryData(
library_key=ref.library_key
)
)
try:
delete_bundle(bundle_uuid)
except:
Expand Down Expand Up @@ -754,7 +768,12 @@ def set_library_block_olx(usage_key, new_olx_str):
write_draft_file(draft.uuid, metadata.def_key.olx_path, new_olx_str.encode('utf-8'))
# Clear the bundle cache so everyone sees the new block immediately:
BundleCache(metadata.def_key.bundle_uuid, draft_name=DRAFT_NAME).clear()
LIBRARY_BLOCK_UPDATED.send(sender=None, library_key=usage_key.context_key, usage_key=usage_key)
LIBRARY_BLOCK_UPDATED.send_event(
library_block=LibraryBlockData(
library_key=usage_key.context_key,
usage_key=usage_key
)
)


def create_library_block(library_key, block_type, definition_id):
Expand Down Expand Up @@ -803,7 +822,12 @@ def create_library_block(library_key, block_type, definition_id):
# Clear the bundle cache so everyone sees the new block immediately:
BundleCache(ref.bundle_uuid, draft_name=DRAFT_NAME).clear()
# Now return the metadata about the new block:
LIBRARY_BLOCK_CREATED.send(sender=None, library_key=ref.library_key, usage_key=usage_key)
LIBRARY_BLOCK_CREATED.send_event(
library_block=LibraryBlockData(
library_key=ref.library_key,
usage_key=usage_key
)
)
return get_library_block(usage_key)


Expand Down Expand Up @@ -856,7 +880,12 @@ def delete_library_block(usage_key, remove_from_parent=True):
pass
# Clear the bundle cache so everyone sees the deleted block immediately:
lib_bundle.cache.clear()
LIBRARY_BLOCK_DELETED.send(sender=None, library_key=lib_bundle.library_key, usage_key=usage_key)
LIBRARY_BLOCK_DELETED.send_event(
library_block=LibraryBlockData(
library_key=lib_bundle.library_key,
usage_key=usage_key
)
)


def create_library_block_child(parent_usage_key, block_type, definition_id):
Expand All @@ -880,7 +909,12 @@ def create_library_block_child(parent_usage_key, block_type, definition_id):
parent_block.runtime.add_child_include(parent_block, include_data)
parent_block.save()
ref = ContentLibrary.objects.get_by_key(parent_usage_key.context_key)
LIBRARY_BLOCK_UPDATED.send(sender=None, library_key=ref.library_key, usage_key=metadata.usage_key)
LIBRARY_BLOCK_UPDATED.send_event(
library_block=LibraryBlockData(
library_key=ref.library_key,
usage_key=metadata.usage_key
)
)
return metadata


Expand Down Expand Up @@ -930,7 +964,12 @@ def add_library_block_static_asset_file(usage_key, file_name, file_content):
file_metadata = blockstore_cache.get_bundle_file_metadata_with_cache(
bundle_uuid=def_key.bundle_uuid, path=file_path, draft_name=DRAFT_NAME,
)
LIBRARY_BLOCK_UPDATED.send(sender=None, library_key=lib_bundle.library_key, usage_key=usage_key)
LIBRARY_BLOCK_UPDATED.send_event(
library_block=LibraryBlockData(
library_key=lib_bundle.library_key,
usage_key=usage_key
)
)
return LibraryXBlockStaticFile(path=file_metadata.path, url=file_metadata.url, size=file_metadata.size)


Expand All @@ -951,7 +990,12 @@ def delete_library_block_static_asset_file(usage_key, file_name):
write_draft_file(draft.uuid, file_path, contents=None)
# Clear the bundle cache so everyone sees the new file immediately:
lib_bundle.cache.clear()
LIBRARY_BLOCK_UPDATED.send(sender=None, library_key=lib_bundle.library_key, usage_key=usage_key)
LIBRARY_BLOCK_UPDATED.send_event(
library_block=LibraryBlockData(
library_key=lib_bundle.library_key,
usage_key=usage_key
)
)


def get_allowed_block_types(library_key): # pylint: disable=unused-argument
Expand Down Expand Up @@ -1044,7 +1088,11 @@ def create_bundle_link(library_key, link_id, target_opaque_key, version=None):
set_draft_link(draft.uuid, link_id, target_bundle_uuid, version)
# Clear the cache:
LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear()
CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key)
CONTENT_LIBRARY_UPDATED.send_event(
content_library=ContentLibraryData(
library_key=library_key
)
)


def update_bundle_link(library_key, link_id, version=None, delete=False):
Expand All @@ -1068,7 +1116,11 @@ def update_bundle_link(library_key, link_id, version=None, delete=False):
set_draft_link(draft.uuid, link_id, link.bundle_uuid, version)
# Clear the cache:
LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear()
CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key)
CONTENT_LIBRARY_UPDATED.send_event(
content_library=ContentLibraryData(
library_key=library_key
)
)


def publish_changes(library_key):
Expand All @@ -1084,7 +1136,12 @@ def publish_changes(library_key):
return # If there is no draft, no action is needed.
LibraryBundle(library_key, ref.bundle_uuid).cache.clear()
LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear()
CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key, update_blocks=True)
CONTENT_LIBRARY_UPDATED.send_event(
content_library=ContentLibraryData(
library_key=library_key,
update_blocks=True
)
)


def revert_changes(library_key):
Expand All @@ -1100,7 +1157,12 @@ def revert_changes(library_key):
else:
return # If there is no draft, no action is needed.
LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear()
CONTENT_LIBRARY_UPDATED.send(sender=None, library_key=library_key, update_blocks=True)
CONTENT_LIBRARY_UPDATED.send_event(
content_library=ContentLibraryData(
library_key=library_key,
update_blocks=True
)
)


# Import from Courseware
Expand Down
71 changes: 57 additions & 14 deletions openedx/core/djangoapps/content_libraries/libraries_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
from search.elastic import _translate_hits, RESERVED_CHARACTERS
from search.search_engine_base import SearchEngine
from opaque_keys.edx.locator import LibraryUsageLocatorV2

from openedx.core.djangoapps.content_libraries.constants import DRAFT_NAME
from openedx.core.djangoapps.content_libraries.signals import (
from openedx_events.content_authoring.data import ContentLibraryData, LibraryBlockData
from openedx_events.content_authoring.signals import (
Comment thread
rpenido marked this conversation as resolved.
Outdated
CONTENT_LIBRARY_CREATED,
CONTENT_LIBRARY_UPDATED,
CONTENT_LIBRARY_DELETED,
CONTENT_LIBRARY_UPDATED,
LIBRARY_BLOCK_CREATED,
LIBRARY_BLOCK_UPDATED,
LIBRARY_BLOCK_DELETED,
LIBRARY_BLOCK_UPDATED,
)

from openedx.core.djangoapps.content_libraries.constants import DRAFT_NAME
from openedx.core.djangoapps.content_libraries.library_bundle import LibraryBundle
from openedx.core.djangoapps.content_libraries.models import ContentLibrary
from openedx.core.lib.blockstore_api import get_bundle
Expand Down Expand Up @@ -242,17 +243,21 @@ def get_item_definition(cls, item):

@receiver(CONTENT_LIBRARY_CREATED)
@receiver(CONTENT_LIBRARY_UPDATED)
@receiver(LIBRARY_BLOCK_CREATED)
@receiver(LIBRARY_BLOCK_UPDATED)
@receiver(LIBRARY_BLOCK_DELETED)
def index_library(sender, library_key, **kwargs): # pylint: disable=unused-argument
def index_library(**kwargs):
"""
Index library when created or updated, or when its blocks are modified.
"""
content_library = kwargs.get('content_library', None)
if not content_library or not isinstance(content_library, ContentLibraryData):
log.error('Received null or incorrect data for event')
return
Comment thread
navinkarkera marked this conversation as resolved.
Outdated

library_key = content_library.library_key
update_blocks = content_library.update_blocks
if ContentLibraryIndexer.indexing_is_enabled():
try:
ContentLibraryIndexer.index_items([library_key])
if kwargs.get('update_blocks', False):
if update_blocks:
blocks = LibraryBlockIndexer.get_items(filter_terms={
'library_key': str(library_key)
})
Expand All @@ -262,12 +267,38 @@ def index_library(sender, library_key, **kwargs): # pylint: disable=unused-argu
log.exception(e)


@receiver(LIBRARY_BLOCK_CREATED)
@receiver(LIBRARY_BLOCK_DELETED)
@receiver(LIBRARY_BLOCK_UPDATED)
def index_library_block(**kwargs):
"""
Index library when its blocks are created, modified, or deleted.
"""
library_block = kwargs.get('library_block', None)
if not library_block or not isinstance(library_block, LibraryBlockData):
log.error('Received null or incorrect data for event')
return

library_key = library_block.library_key
if ContentLibraryIndexer.indexing_is_enabled():
try:
ContentLibraryIndexer.index_items([library_key])
except ElasticConnectionError as e:
log.exception(e)


@receiver(CONTENT_LIBRARY_DELETED)
def remove_library_index(sender, library_key, **kwargs): # pylint: disable=unused-argument
def remove_library_index(**kwargs):
"""
Remove from index when library is deleted
"""
content_library = kwargs.get('content_library', None)
if not content_library or not isinstance(content_library, ContentLibraryData):
log.error('Received null or incorrect data for event')
return

if ContentLibraryIndexer.indexing_is_enabled():
library_key = content_library.library_key
try:
ContentLibraryIndexer.remove_items([library_key])
blocks = LibraryBlockIndexer.get_items(filter_terms={
Expand All @@ -280,10 +311,16 @@ def remove_library_index(sender, library_key, **kwargs): # pylint: disable=unus

@receiver(LIBRARY_BLOCK_CREATED)
@receiver(LIBRARY_BLOCK_UPDATED)
def index_block(sender, usage_key, **kwargs): # pylint: disable=unused-argument
def index_block(**kwargs):
"""
Index block metadata when created
Index block metadata when created or updated
"""
library_block = kwargs.get('library_block', None)
if not library_block or not isinstance(library_block, LibraryBlockData):
log.error('Received null or incorrect data for event')
return

usage_key = library_block.usage_key
if LibraryBlockIndexer.indexing_is_enabled():
try:
LibraryBlockIndexer.index_items([usage_key])
Expand All @@ -292,10 +329,16 @@ def index_block(sender, usage_key, **kwargs): # pylint: disable=unused-argument


@receiver(LIBRARY_BLOCK_DELETED)
def remove_block_index(sender, usage_key, **kwargs): # pylint: disable=unused-argument
def remove_block_index(**kwargs):
"""
Remove the block from the index when deleted
"""
library_block = kwargs.get('library_block', None)
if not library_block or not isinstance(library_block, LibraryBlockData):
log.error('Received null or incorrect data for LIBRARY_BLOCK_DELETED')
return

usage_key = library_block.usage_key
if LibraryBlockIndexer.indexing_is_enabled():
try:
LibraryBlockIndexer.remove_items([usage_key])
Expand Down
Loading