1
+ from time import monotonic , sleep
2
+
1
3
from django .db .backends .base .schema import BaseDatabaseSchemaEditor
2
4
from django .db .models import Index , UniqueConstraint
3
5
from pymongo .operations import SearchIndexModel
@@ -269,10 +271,12 @@ def add_index(
269
271
)
270
272
if idx :
271
273
model = parent_model or model
274
+ collection = self .get_collection (model ._meta .db_table )
272
275
if isinstance (idx , SearchIndexModel ):
273
- self .get_collection (model ._meta .db_table ).create_search_index (idx )
276
+ collection .create_search_index (idx )
277
+ self .wait_until_index_created (collection , index .name )
274
278
else :
275
- self . get_collection ( model . _meta . db_table ) .create_indexes ([idx ])
279
+ collection .create_indexes ([idx ])
276
280
277
281
def _add_composed_index (self , model , field_names , column_prefix = "" , parent_model = None ):
278
282
"""Add an index on the given list of field_names."""
@@ -290,12 +294,14 @@ def _add_field_index(self, model, field, *, column_prefix=""):
290
294
def remove_index (self , model , index ):
291
295
if index .contains_expressions :
292
296
return
297
+ collection = self .get_collection (model ._meta .db_table )
293
298
if isinstance (index , SearchIndex ):
294
299
# Drop the index if it's supported.
295
300
if self .connection .features .supports_atlas_search :
296
- self .get_collection (model ._meta .db_table ).drop_search_index (index .name )
301
+ collection .drop_search_index (index .name )
302
+ self .wait_until_index_deleted (collection , index .name )
297
303
else :
298
- self . get_collection ( model . _meta . db_table ) .drop_index (index .name )
304
+ collection .drop_index (index .name )
299
305
300
306
def _remove_composed_index (
301
307
self , model , field_names , constraint_kwargs , column_prefix = "" , parent_model = None
@@ -420,6 +426,27 @@ def _field_should_have_unique(self, field):
420
426
# The _id column is automatically unique.
421
427
return db_type and field .unique and field .column != "_id"
422
428
429
+ @staticmethod
430
+ def wait_until_index_created (collection , index_name , timeout = 60 , interval = 0.5 ):
431
+ start = monotonic ()
432
+ while monotonic () - start < timeout :
433
+ indexes = list (collection .list_search_indexes ())
434
+ for idx in indexes :
435
+ if idx ["name" ] == index_name and idx ["status" ] == "READY" :
436
+ return True
437
+ sleep (interval )
438
+ raise TimeoutError (f"Index { index_name } not ready after { timeout } seconds." )
439
+
440
+ @staticmethod
441
+ def wait_until_index_deleted (collection , index_name , timeout = 60 , interval = 0.5 ):
442
+ start = monotonic ()
443
+ while monotonic () - start < timeout :
444
+ indexes = list (collection .list_search_indexes ())
445
+ if all (idx ["name" ] != index_name for idx in indexes ):
446
+ return True
447
+ sleep (interval )
448
+ raise TimeoutError (f"Index { index_name } not deleted after { timeout } seconds." )
449
+
423
450
424
451
# GISSchemaEditor extends some SchemaEditor methods.
425
452
class DatabaseSchemaEditor (GISSchemaEditor , BaseSchemaEditor ):
0 commit comments