Skip to content

Commit

Permalink
feat: add new content authoring event signals
Browse files Browse the repository at this point in the history
  • Loading branch information
JuanDavidBuitrago committed Nov 17, 2023
1 parent c2428f8 commit e498e5f
Show file tree
Hide file tree
Showing 12 changed files with 661 additions and 65 deletions.
92 changes: 76 additions & 16 deletions openedx/core/djangoapps/content_libraries/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@
ContentLibraryPermission,
ContentLibraryBlockImportTask,
)
from openedx.core.djangoapps.content_libraries.signals import (
from openedx_events.content_authoring.data import ContentLibraryData, LibraryBlockData
from openedx_events.content_authoring.signals import (
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.olx_rest_api.block_serializer import XBlockSerializer
from openedx.core.djangoapps.xblock.api import get_block_display_name, load_block
Expand Down Expand Up @@ -451,7 +452,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(
library_key=ref.library_key
)
)
return ContentLibraryMetadata(
key=ref.library_key,
bundle_uuid=bundle.uuid,
Expand Down Expand Up @@ -601,7 +606,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 @@ -616,7 +625,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 @@ -753,7 +766,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 @@ -802,7 +820,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 @@ -855,7 +878,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 @@ -879,7 +907,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 @@ -929,7 +962,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 @@ -950,7 +988,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 @@ -1043,7 +1086,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 @@ -1067,7 +1114,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 @@ -1083,7 +1134,11 @@ 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
)
)


def revert_changes(library_key):
Expand All @@ -1099,7 +1154,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
70 changes: 56 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 (
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,20 @@ 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
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 +266,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 +310,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 +328,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
17 changes: 0 additions & 17 deletions openedx/core/djangoapps/content_libraries/signals.py

This file was deleted.

2 changes: 1 addition & 1 deletion openedx/core/djangoapps/content_libraries/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def _set_library_block_asset(self, block_key, file_name, content, expect_respons
assert response.status_code == expect_response,\
'Unexpected response code {}:\n{}'.format(response.status_code, getattr(response, 'data', '(no data)'))

def _delete_library_block_asset(self, block_key, file_name, expect_response=200):
def _delete_library_block_asset(self, block_key, file_name, expect_response=204):
""" Delete a static asset file. """
url = URL_LIB_BLOCK_ASSET_FILE.format(block_key=block_key, file_name=file_name)
return self._api('delete', url, None, expect_response)
Expand Down
Loading

0 comments on commit e498e5f

Please sign in to comment.