fix: add to search index when creating library from archive (#37526)

Implement full re-index process when creating a library.
This commit is contained in:
Daniel Wong
2025-10-27 15:53:07 -06:00
committed by GitHub
parent 8aaae4604a
commit 6deb4f8d05
10 changed files with 82 additions and 12 deletions

View File

@@ -873,7 +873,7 @@ def upsert_library_container_index_doc(container_key: LibraryContainerLocator) -
_update_index_docs([doc])
def upsert_content_library_index_docs(library_key: LibraryLocatorV2) -> None:
def upsert_content_library_index_docs(library_key: LibraryLocatorV2, full_index: bool = False) -> None:
"""
Creates or updates the documents for the given Content Library in the search index
"""
@@ -883,6 +883,21 @@ def upsert_content_library_index_docs(library_key: LibraryLocatorV2) -> None:
doc = searchable_doc_for_library_block(metadata)
docs.append(doc)
if full_index:
# For a full re-index, we also need to update collections, and containers data:
for container in lib_api.get_library_containers(library_key):
container_key = lib_api.library_container_locator(
library_key,
container,
)
doc = searchable_doc_for_container(container_key)
docs.append(doc)
for collection in lib_api.get_library_collections(library_key):
collection_key = lib_api.library_collection_locator(library_key, collection.key)
doc = searchable_doc_for_collection(collection_key, collection=collection)
docs.append(doc)
_update_index_docs(docs)

View File

@@ -19,6 +19,7 @@ from openedx_events.content_authoring.data import (
XBlockData,
)
from openedx_events.content_authoring.signals import (
CONTENT_LIBRARY_CREATED,
CONTENT_LIBRARY_DELETED,
CONTENT_LIBRARY_UPDATED,
CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
@@ -187,6 +188,21 @@ def library_block_deleted(**kwargs) -> None:
delete_library_block_index_doc.apply(args=[str(library_block_data.usage_key)])
@receiver(CONTENT_LIBRARY_CREATED)
@only_if_meilisearch_enabled
def content_library_created_handler(**kwargs) -> None:
"""
Create the index for the content library
"""
content_library_data = kwargs.get("content_library", None)
if not content_library_data or not isinstance(content_library_data, ContentLibraryData): # pragma: no cover
log.error("Received null or incorrect data for event")
return
library_key = content_library_data.library_key
update_content_library_index_docs.apply(args=[str(library_key), True])
@receiver(CONTENT_LIBRARY_UPDATED)
@only_if_meilisearch_enabled
def content_library_updated_handler(**kwargs) -> None:

View File

@@ -91,7 +91,7 @@ def delete_library_block_index_doc(usage_key_str: str) -> None:
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))
@set_code_owner_attribute
def update_content_library_index_docs(library_key_str: str) -> None:
def update_content_library_index_docs(library_key_str: str, full_index: bool = False) -> None:
"""
Celery task to update the content index documents for all library blocks in a library
"""
@@ -99,7 +99,8 @@ def update_content_library_index_docs(library_key_str: str) -> None:
log.info("Updating content index documents for library with id: %s", library_key)
api.upsert_content_library_index_docs(library_key)
# If full_index is True, also update collections and containers data
api.upsert_content_library_index_docs(library_key, full_index=full_index)
@shared_task(base=LoggedTask, autoretry_for=(MeilisearchError, ConnectionError))

View File

@@ -37,7 +37,10 @@ from openedx_events.content_authoring.signals import (
LIBRARY_CONTAINER_UPDATED
)
from openedx_learning.api import authoring as authoring_api
from openedx_learning.api.authoring_models import Component, ComponentVersion, LearningPackage, MediaType
from openedx_learning.api.authoring_models import (
Component, ComponentVersion, LearningPackage, MediaType,
Container, Collection
)
from xblock.core import XBlock
from openedx.core.djangoapps.xblock.api import (
@@ -80,6 +83,8 @@ log = logging.getLogger(__name__)
__all__ = [
# API methods
"get_library_components",
"get_library_containers",
"get_library_collections",
"get_library_block",
"set_library_block_olx",
"get_component_from_usage_key",
@@ -121,6 +126,33 @@ def get_library_components(
return components
def get_library_containers(library_key: LibraryLocatorV2) -> QuerySet[Container]:
"""
Get all containers in the given content library.
"""
lib = ContentLibrary.objects.get_by_key(library_key) # type: ignore[attr-defined]
learning_package = lib.learning_package
assert learning_package is not None
containers: QuerySet[Container] = authoring_api.get_containers(
learning_package.id
)
return containers
def get_library_collections(library_key: LibraryLocatorV2) -> QuerySet[Collection]:
"""
Get all collections in the given content library.
"""
lib = ContentLibrary.objects.get_by_key(library_key) # type: ignore[attr-defined]
learning_package = lib.learning_package
assert learning_package is not None
collections = authoring_api.get_collections(
learning_package.id
)
return collections
def get_library_block(usage_key: LibraryUsageLocatorV2, include_collections=False) -> LibraryXBlockMetadata:
"""
Get metadata about (the draft version of) one specific XBlock in a library.

View File

@@ -53,12 +53,17 @@ from django.core.validators import validate_unicode_slug
from django.db import IntegrityError, transaction
from django.db.models import Q, QuerySet
from django.utils.translation import gettext as _
from opaque_keys.edx.locator import LibraryLocatorV2, LibraryUsageLocatorV2
from openedx_events.content_authoring.data import ContentLibraryData
from opaque_keys.edx.locator import (
LibraryLocatorV2,
LibraryUsageLocatorV2,
)
from openedx_events.content_authoring.data import (
ContentLibraryData,
)
from openedx_events.content_authoring.signals import (
CONTENT_LIBRARY_CREATED,
CONTENT_LIBRARY_DELETED,
CONTENT_LIBRARY_UPDATED
CONTENT_LIBRARY_UPDATED,
)
from openedx_learning.api import authoring as authoring_api
from openedx_learning.api.authoring_models import Component, LearningPackage
@@ -407,6 +412,7 @@ def create_library(
"""
assert isinstance(org, Organization)
validate_unicode_slug(slug)
is_learning_package_loaded = learning_package is not None
try:
with transaction.atomic():
ref = ContentLibrary.objects.create(

View File

@@ -61,7 +61,7 @@ numpy<2.0.0
# Date: 2023-09-18
# pinning this version to avoid updates while the library is being developed
# Issue for unpinning: https://github.com/openedx/edx-platform/issues/35269
openedx-learning==0.29.0
openedx-learning==0.29.1
# Date: 2023-11-29
# Open AI version 1.0.0 dropped support for openai.ChatCompletion which is currently in use in enterprise.

View File

@@ -841,7 +841,7 @@ openedx-filters==2.1.0
# ora2
openedx-forum==0.3.8
# via -r requirements/edx/kernel.in
openedx-learning==0.29.0
openedx-learning==0.29.1
# via
# -c requirements/constraints.txt
# -r requirements/edx/kernel.in

View File

@@ -1393,7 +1393,7 @@ openedx-forum==0.3.8
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
openedx-learning==0.29.0
openedx-learning==0.29.1
# via
# -c requirements/constraints.txt
# -r requirements/edx/doc.txt

View File

@@ -1015,7 +1015,7 @@ openedx-filters==2.1.0
# ora2
openedx-forum==0.3.8
# via -r requirements/edx/base.txt
openedx-learning==0.29.0
openedx-learning==0.29.1
# via
# -c requirements/constraints.txt
# -r requirements/edx/base.txt

View File

@@ -1059,7 +1059,7 @@ openedx-filters==2.1.0
# ora2
openedx-forum==0.3.8
# via -r requirements/edx/base.txt
openedx-learning==0.29.0
openedx-learning==0.29.1
# via
# -c requirements/constraints.txt
# -r requirements/edx/base.txt