23
23
LIBRARY_BLOCK_CREATED ,
24
24
LIBRARY_BLOCK_DELETED ,
25
25
LIBRARY_BLOCK_UPDATED ,
26
+ LIBRARY_BLOCK_PUBLISHED ,
26
27
LIBRARY_COLLECTION_CREATED ,
27
28
LIBRARY_COLLECTION_DELETED ,
28
29
LIBRARY_COLLECTION_UPDATED ,
29
30
LIBRARY_CONTAINER_CREATED ,
30
31
LIBRARY_CONTAINER_DELETED ,
31
32
LIBRARY_CONTAINER_UPDATED ,
33
+ LIBRARY_CONTAINER_PUBLISHED ,
32
34
XBLOCK_CREATED ,
33
35
XBLOCK_DELETED ,
34
36
XBLOCK_UPDATED ,
37
39
38
40
from openedx .core .djangoapps .content .course_overviews .models import CourseOverview
39
41
from openedx .core .djangoapps .content .search .models import SearchAccess
42
+ from openedx .core .djangoapps .content_libraries import api as lib_api
40
43
41
44
from .api import (
42
45
only_if_meilisearch_enabled ,
@@ -136,6 +139,32 @@ def library_block_updated_handler(**kwargs) -> None:
136
139
upsert_library_block_index_doc .apply (args = [str (library_block_data .usage_key )])
137
140
138
141
142
+ @receiver (LIBRARY_BLOCK_PUBLISHED )
143
+ @only_if_meilisearch_enabled
144
+ def library_block_published_handler (** kwargs ) -> None :
145
+ """
146
+ Update the index for the content library block when its published version
147
+ has changed.
148
+ """
149
+ library_block_data = kwargs .get ("library_block" , None )
150
+ if not library_block_data or not isinstance (library_block_data , LibraryBlockData ): # pragma: no cover
151
+ log .error ("Received null or incorrect data for event" )
152
+ return
153
+
154
+ # The PUBLISHED event is sent for any change to the published version including deletes, so check if it exists:
155
+ try :
156
+ lib_api .get_library_block (library_block_data .usage_key )
157
+ except lib_api .ContentLibraryBlockNotFound :
158
+ log .info (f"Observed published deletion of library block { str (library_block_data .usage_key )} ." )
159
+ # The document should already have been deleted from the search index
160
+ # via the DELETED handler, so there's nothing to do now.
161
+ return
162
+
163
+ # Update content library index synchronously to make sure that search index is updated before
164
+ # the frontend invalidates/refetches results. This is only a single document update so is very fast.
165
+ upsert_library_block_index_doc .apply (args = [str (library_block_data .usage_key )])
166
+
167
+
139
168
@receiver (LIBRARY_BLOCK_DELETED )
140
169
@only_if_meilisearch_enabled
141
170
def library_block_deleted (** kwargs ) -> None :
@@ -162,14 +191,14 @@ def content_library_updated_handler(**kwargs) -> None:
162
191
if not content_library_data or not isinstance (content_library_data , ContentLibraryData ): # pragma: no cover
163
192
log .error ("Received null or incorrect data for event" )
164
193
return
194
+ library_key = content_library_data .library_key
165
195
166
- # Update content library index synchronously to make sure that search index is updated before
167
- # the frontend invalidates/refetches index.
168
- # Currently, this is only required to make sure that removed/discarded components are removed
169
- # from the search index and displayed to user properly. If it becomes a performance bottleneck
170
- # for other update operations other than discard, we can update CONTENT_LIBRARY_UPDATED event
171
- # to include a parameter which can help us decide if the task needs to run sync or async.
172
- update_content_library_index_docs .apply (args = [str (content_library_data .library_key )])
196
+ # For now we assume the library has been renamed. Few other things will trigger this event.
197
+
198
+ # Update ALL items in the library, because their breadcrumbs will be outdated.
199
+ # TODO: just patch the "breadcrumbs" field? It's the same on every one.
200
+ # TODO: check if the library display_name has actually changed before updating all items?
201
+ update_content_library_index_docs .apply (args = [str (library_key )])
173
202
174
203
175
204
@receiver (LIBRARY_COLLECTION_CREATED )
@@ -248,17 +277,34 @@ def library_container_updated_handler(**kwargs) -> None:
248
277
log .error ("Received null or incorrect data for event" )
249
278
return
250
279
251
- if library_container .background :
252
- update_library_container_index_doc .delay (
253
- str (library_container .container_key ),
254
- )
255
- else :
256
- # Update container index synchronously to make sure that search index is updated before
257
- # the frontend invalidates/refetches index.
258
- # See content_library_updated_handler for more details.
259
- update_library_container_index_doc .apply (args = [
260
- str (library_container .container_key ),
261
- ])
280
+ update_library_container_index_doc .apply (args = [
281
+ str (library_container .container_key ),
282
+ ])
283
+
284
+
285
+ @receiver (LIBRARY_CONTAINER_PUBLISHED )
286
+ @only_if_meilisearch_enabled
287
+ def library_container_published_handler (** kwargs ) -> None :
288
+ """
289
+ Update the index for the content library container when its published
290
+ version has changed.
291
+ """
292
+ library_container = kwargs .get ("library_container" , None )
293
+ if not library_container or not isinstance (library_container , LibraryContainerData ): # pragma: no cover
294
+ log .error ("Received null or incorrect data for event" )
295
+ return
296
+ # The PUBLISHED event is sent for any change to the published version including deletes, so check if it exists:
297
+ try :
298
+ lib_api .get_container (library_container .container_key )
299
+ except lib_api .ContentLibraryContainerNotFound :
300
+ log .info (f"Observed published deletion of container { str (library_container .container_key )} ." )
301
+ # The document should already have been deleted from the search index
302
+ # via the DELETED handler, so there's nothing to do now.
303
+ return
304
+
305
+ update_library_container_index_doc .apply (args = [
306
+ str (library_container .container_key ),
307
+ ])
262
308
263
309
264
310
@receiver (LIBRARY_CONTAINER_DELETED )
@@ -275,3 +321,6 @@ def library_container_deleted(**kwargs) -> None:
275
321
# Update content library index synchronously to make sure that search index is updated before
276
322
# the frontend invalidates/refetches results. This is only a single document update so is very fast.
277
323
delete_library_container_index_doc .apply (args = [str (library_container .container_key )])
324
+ # TODO: post-Teak, move all the celery tasks directly inline into this handlers? Because now the
325
+ # events are emitted in an [async] worker, so it doesn't matter if the handlers are synchronous.
326
+ # See https://github.com/openedx/edx-platform/pull/36640 discussion.
0 commit comments