Skip to content

Commit 7665f13

Browse files
yusuf-muslehpomegranitedChrisChVrpenido
authored
feat: Add Library Collections REST endpoints [FC-0062] (#35321)
* feat: Add Library Collections REST endpoints * test: Add tests for Collections REST APIs * chore: Add missing __init__ files * feat: Add events emitting for Collections * feat: Add REST endpoints to update Components in a Collections (temp) (#674) * feat: add/remove components to/from a collection * docs: Add warning about unstable REST APIs * chore: updates openedx-events==9.14.0 * chore: updates openedx-learning==0.11.4 * fix: assert collection doc have unique id --------- Co-authored-by: Jillian <jill@opencraft.com> Co-authored-by: Chris Chávez <xnpiochv@gmail.com> Co-authored-by: Rômulo Penido <romulo.penido@gmail.com>
1 parent d59e2f4 commit 7665f13

16 files changed

Lines changed: 1222 additions & 68 deletions

File tree

docs/hooks/events.rst

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,17 +233,29 @@ Content Authoring Events
233233
- 2023-07-20
234234

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

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

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

247247
* - `CONTENT_OBJECT_TAGS_CHANGED <https://github.com/openedx/openedx-events/blob/c0eb4ba1a3d7d066d58e5c87920b8ccb0645f769/openedx_events/content_authoring/signals.py#L207>`_
248248
- org.openedx.content_authoring.content.object.tags.changed.v1
249249
- 2024-03-31
250+
251+
* - `LIBRARY_COLLECTION_CREATED <https://github.com/openedx/openedx-events/blob/main/openedx_events/content_authoring/signals.py#L219>`_
252+
- org.openedx.content_authoring.content_library.collection.created.v1
253+
- 2024-08-23
254+
255+
* - `LIBRARY_COLLECTION_UPDATED <https://github.com/openedx/openedx-events/blob/main/openedx_events/content_authoring/signals.py#L230>`_
256+
- org.openedx.content_authoring.content_library.collection.updated.v1
257+
- 2024-08-23
258+
259+
* - `LIBRARY_COLLECTION_DELETED <https://github.com/openedx/openedx-events/blob/main/openedx_events/content_authoring/signals.py#L241>`_
260+
- org.openedx.content_authoring.content_library.collection.deleted.v1
261+
- 2024-08-23

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

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -296,16 +296,12 @@ def rebuild_index(status_cb: Callable[[str], None] | None = None) -> None:
296296
status_cb("Counting courses...")
297297
num_courses = CourseOverview.objects.count()
298298

299-
# Get the list of collections
300-
status_cb("Counting collections...")
301-
num_collections = authoring_api.get_collections().count()
302-
303299
# Some counters so we can track our progress as indexing progresses:
304-
num_contexts = num_courses + num_libraries + num_collections
300+
num_contexts = num_courses + num_libraries
305301
num_contexts_done = 0 # How many courses/libraries we've indexed
306302
num_blocks_done = 0 # How many individual components/XBlocks we've indexed
307303

308-
status_cb(f"Found {num_courses} courses, {num_libraries} libraries and {num_collections} collections.")
304+
status_cb(f"Found {num_courses} courses, {num_libraries} libraries.")
309305
with _using_temp_index(status_cb) as temp_index_name:
310306
############## Configure the index ##############
311307

@@ -390,10 +386,43 @@ def index_library(lib_key: str) -> list:
390386
status_cb(f"Error indexing library {lib_key}: {err}")
391387
return docs
392388

389+
############## Collections ##############
390+
def index_collection_batch(batch, num_done) -> int:
391+
docs = []
392+
for collection in batch:
393+
try:
394+
doc = searchable_doc_for_collection(collection)
395+
# Uncomment below line once collections are tagged.
396+
# doc.update(searchable_doc_tags(collection.id))
397+
docs.append(doc)
398+
except Exception as err: # pylint: disable=broad-except
399+
status_cb(f"Error indexing collection {collection}: {err}")
400+
num_done += 1
401+
402+
if docs:
403+
try:
404+
# Add docs in batch of 100 at once (usually faster than adding one at a time):
405+
_wait_for_meili_task(client.index(temp_index_name).add_documents(docs))
406+
except (TypeError, KeyError, MeilisearchError) as err:
407+
status_cb(f"Error indexing collection batch {p}: {err}")
408+
return num_done
409+
393410
for lib_key in lib_keys:
394-
status_cb(f"{num_contexts_done + 1}/{num_contexts}. Now indexing library {lib_key}")
411+
status_cb(f"{num_contexts_done + 1}/{num_contexts}. Now indexing blocks in library {lib_key}")
395412
lib_docs = index_library(lib_key)
396413
num_blocks_done += len(lib_docs)
414+
415+
# To reduce memory usage on large instances, split up the Collections into pages of 100 collections:
416+
library = lib_api.get_library(lib_key)
417+
collections = authoring_api.get_collections(library.learning_package.id, enabled=True)
418+
num_collections = collections.count()
419+
num_collections_done = 0
420+
status_cb(f"{num_collections_done + 1}/{num_collections}. Now indexing collections in library {lib_key}")
421+
paginator = Paginator(collections, 100)
422+
for p in paginator.page_range:
423+
num_collections_done = index_collection_batch(paginator.page(p).object_list, num_collections_done)
424+
status_cb(f"{num_collections_done}/{num_collections} collections indexed for library {lib_key}")
425+
397426
num_contexts_done += 1
398427

399428
############## Courses ##############
@@ -430,39 +459,6 @@ def add_with_children(block):
430459
num_contexts_done += 1
431460
num_blocks_done += len(course_docs)
432461

433-
############## Collections ##############
434-
status_cb("Indexing collections...")
435-
436-
def index_collection_batch(batch, num_contexts_done) -> int:
437-
docs = []
438-
for collection in batch:
439-
status_cb(
440-
f"{num_contexts_done + 1}/{num_contexts}. "
441-
f"Now indexing collection {collection.title} ({collection.id})"
442-
)
443-
try:
444-
doc = searchable_doc_for_collection(collection)
445-
# Uncomment below line once collections are tagged.
446-
# doc.update(searchable_doc_tags(collection.id))
447-
docs.append(doc)
448-
except Exception as err: # pylint: disable=broad-except
449-
status_cb(f"Error indexing collection {collection}: {err}")
450-
finally:
451-
num_contexts_done += 1
452-
453-
if docs:
454-
try:
455-
# Add docs in batch of 100 at once (usually faster than adding one at a time):
456-
_wait_for_meili_task(client.index(temp_index_name).add_documents(docs))
457-
except (TypeError, KeyError, MeilisearchError) as err:
458-
status_cb(f"Error indexing collection batch {p}: {err}")
459-
return num_contexts_done
460-
461-
# To reduce memory usage on large instances, split up the Collections into pages of 100 collections:
462-
paginator = Paginator(authoring_api.get_collections(enabled=True), 100)
463-
for p in paginator.page_range:
464-
num_contexts_done = index_collection_batch(paginator.page(p).object_list, num_contexts_done)
465-
466462
status_cb(f"Done! {num_blocks_done} blocks indexed across {num_contexts_done} courses, collections and libraries.")
467463

468464

openedx/core/djangoapps/content/search/tests/test_api.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,16 @@ def setUp(self):
177177

178178
# Create a collection:
179179
self.learning_package = authoring_api.get_learning_package_by_key(self.library.key)
180+
with freeze_time(created_date):
181+
self.collection = authoring_api.create_collection(
182+
learning_package_id=self.learning_package.id,
183+
key="MYCOL",
184+
title="my_collection",
185+
created_by=None,
186+
description="my collection description"
187+
)
180188
self.collection_dict = {
181-
'id': 1,
189+
'id': self.collection.id,
182190
'type': 'collection',
183191
'display_name': 'my_collection',
184192
'description': 'my collection description',
@@ -189,13 +197,6 @@ def setUp(self):
189197
"access_id": lib_access.id,
190198
'breadcrumbs': [{'display_name': 'Library'}]
191199
}
192-
with freeze_time(created_date):
193-
self.collection = authoring_api.create_collection(
194-
learning_package_id=self.learning_package.id,
195-
title="my_collection",
196-
created_by=None,
197-
description="my collection description"
198-
)
199200

200201
@override_settings(MEILISEARCH_ENABLED=False)
201202
def test_reindex_meilisearch_disabled(self, mock_meilisearch):

openedx/core/djangoapps/content/search/tests/test_documents.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ def test_collection_with_no_library(self):
215215
)
216216
collection = authoring_api.create_collection(
217217
learning_package_id=learning_package.id,
218+
key="MYCOL",
218219
title="my_collection",
219220
created_by=None,
220221
description="my collection description"
@@ -223,11 +224,11 @@ def test_collection_with_no_library(self):
223224
assert doc == {
224225
"id": collection.id,
225226
"type": "collection",
226-
"display_name": collection.title,
227-
"description": collection.description,
227+
"display_name": "my_collection",
228+
"description": "my collection description",
228229
"context_key": learning_package.key,
229230
"access_id": self.toy_course_access_id,
230-
"breadcrumbs": [{"display_name": learning_package.title}],
231+
"breadcrumbs": [{"display_name": "some learning_package"}],
231232
"created": created_date.timestamp(),
232233
"modified": created_date.timestamp(),
233234
}

0 commit comments

Comments
 (0)