@@ -245,28 +245,49 @@ def _index_is_empty(index_name: str) -> bool:
245245 return index .get_stats ().number_of_documents == 0
246246
247247
248- def _configure_index (index_name ):
248+ def _apply_index_settings (
249+ index_name : str ,
250+ wait : bool ,
251+ status_cb : Callable [[str ], None ] | None = None ,
252+ ) -> None :
249253 """
250- Configure the index. The following index settings are best changed on an empty index.
251- Changing them on a populated index will "re-index all documents in the index", which can take some time.
254+ Apply the standard Meilisearch settings to an index.
255+
256+ When wait=False, settings are sent in fire-and-forget mode. This is appropriate
257+ for empty temporary indexes that will immediately be populated on the same Meilisearch
258+ task queue.
259+
260+ When wait=True, each settings task is synchronously waited on before returning.
261+ This is appropriate when reconciling a live index and we need confirmation that the
262+ settings have been applied before returning.
252263
253264 Args:
254- index_name (str): The name of the index to configure
265+ index_name: The name of the index to configure.
266+ wait: Whether to wait for each Meilisearch settings task to complete.
267+ status_cb: Optional callback for status messages when wait=True.
255268 """
269+ if status_cb is None :
270+ status_cb = log .info
271+
256272 client = _get_meilisearch_client ()
273+ index = client .index (index_name )
274+
275+ settings_updates = (
276+ ("distinct attribute" , index .update_distinct_attribute , INDEX_DISTINCT_ATTRIBUTE ),
277+ ("filterable attributes" , index .update_filterable_attributes , INDEX_FILTERABLE_ATTRIBUTES ),
278+ ("searchable attributes" , index .update_searchable_attributes , INDEX_SEARCHABLE_ATTRIBUTES ),
279+ ("sortable attributes" , index .update_sortable_attributes , INDEX_SORTABLE_ATTRIBUTES ),
280+ ("ranking rules" , index .update_ranking_rules , INDEX_RANKING_RULES ),
281+ )
257282
258- # Mark usage_key as unique (it's not the primary key for the index, but nevertheless must be unique):
259- client .index (index_name ).update_distinct_attribute (INDEX_DISTINCT_ATTRIBUTE )
260- # Mark which attributes can be used for filtering/faceted search:
261- client .index (index_name ).update_filterable_attributes (INDEX_FILTERABLE_ATTRIBUTES )
262- # Mark which attributes are used for keyword search, in order of importance:
263- client .index (index_name ).update_searchable_attributes (INDEX_SEARCHABLE_ATTRIBUTES )
264- # Mark which attributes can be used for sorting search results:
265- client .index (index_name ).update_sortable_attributes (INDEX_SORTABLE_ATTRIBUTES )
283+ for label , update_method , value in settings_updates :
284+ status_cb (f"Applying { label } to '{ index_name } '..." )
285+ if wait :
286+ _wait_for_meili_task (update_method (value ))
287+ else :
288+ update_method (value )
266289
267- # Update the search ranking rules to let the (optional) "sort" parameter take precedence over keyword relevance.
268- # cf https://www.meilisearch.com/docs/learn/core_concepts/relevancy
269- client .index (index_name ).update_ranking_rules (INDEX_RANKING_RULES )
290+ status_cb (f"All settings applied to '{ index_name } '." )
270291
271292
272293def _recurse_children (block , fn , status_cb : Callable [[str ], None ] | None = None ) -> None :
@@ -345,7 +366,7 @@ def reset_index(status_cb: Callable[[str], None] | None = None) -> None:
345366
346367 status_cb ("Creating new empty index..." )
347368 with _using_temp_index (status_cb ) as temp_index_name :
348- _configure_index (temp_index_name )
369+ _apply_index_settings (temp_index_name , wait = False )
349370 status_cb ("Index recreated!" )
350371 status_cb ("Index reset complete." )
351372
@@ -429,41 +450,6 @@ def _compare_setting(key, expected):
429450 )
430451
431452
432- def _apply_settings_with_waits (index_name : str , status_cb : Callable [[str ], None ] | None = None ) -> None :
433- """
434- Apply all index settings and wait for each Meilisearch task to complete.
435-
436- Unlike _configure_index() which fires-and-forgets, this function waits for
437- confirmation that each setting has been applied. This is used during reconciliation
438- where we need a definitive state before returning.
439-
440- Args:
441- index_name (str): The name of the index to configure.
442- status_cb: Optional callback for status messages.
443- """
444- if status_cb is None :
445- status_cb = log .info
446-
447- client = _get_meilisearch_client ()
448-
449- status_cb (f"Applying distinct attribute to '{ index_name } '..." )
450- _wait_for_meili_task (client .index (index_name ).update_distinct_attribute (INDEX_DISTINCT_ATTRIBUTE ))
451-
452- status_cb (f"Applying filterable attributes to '{ index_name } '..." )
453- _wait_for_meili_task (client .index (index_name ).update_filterable_attributes (INDEX_FILTERABLE_ATTRIBUTES ))
454-
455- status_cb (f"Applying searchable attributes to '{ index_name } '..." )
456- _wait_for_meili_task (client .index (index_name ).update_searchable_attributes (INDEX_SEARCHABLE_ATTRIBUTES ))
457-
458- status_cb (f"Applying sortable attributes to '{ index_name } '..." )
459- _wait_for_meili_task (client .index (index_name ).update_sortable_attributes (INDEX_SORTABLE_ATTRIBUTES ))
460-
461- status_cb (f"Applying ranking rules to '{ index_name } '..." )
462- _wait_for_meili_task (client .index (index_name ).update_ranking_rules (INDEX_RANKING_RULES ))
463-
464- status_cb (f"All settings applied to '{ index_name } '." )
465-
466-
467453def reconcile_index (
468454 status_cb : Callable [[str ], None ] | None = None , warn_cb : Callable [[str ], None ] | None = None
469455) -> None : # noqa: E501
@@ -511,7 +497,7 @@ def reconcile_index(
511497 if drift .is_empty :
512498 if drift .is_settings_drifted :
513499 status_cb ("Empty index has drifted settings. Reconfiguring..." )
514- _apply_settings_with_waits (STUDIO_INDEX_NAME , status_cb )
500+ _apply_index_settings (STUDIO_INDEX_NAME , wait = True , status_cb = status_cb )
515501 status_cb ("Reconfigured. Run './manage.py cms' reindex_studio to populate." )
516502 else :
517503 status_cb (
@@ -533,7 +519,7 @@ def reconcile_index(
533519 if match is False :
534520 warn_cb (f" - { field_name } : DRIFTED" )
535521
536- _apply_settings_with_waits (STUDIO_INDEX_NAME , status_cb )
522+ _apply_index_settings (STUDIO_INDEX_NAME , wait = True , status_cb = status_cb )
537523 warn_cb (
538524 "Settings applied. Meilisearch will re-index documents in the background. "
539525 "Consider running './manage.py cms' reindex_studio for a full rebuild "
@@ -624,7 +610,7 @@ def rebuild_index( # pylint: disable=too-many-statements
624610 # Changing them on a populated index will "re-index all documents in the index", which can take some time
625611 # and use more RAM. Instead, we configure an empty index then populate it one course/library at a time.
626612 if not incremental :
627- _configure_index (index_name )
613+ _apply_index_settings (index_name , wait = False )
628614
629615 ############## Libraries ##############
630616 status_cb ("Indexing libraries..." )
0 commit comments