Repository: meilisearch/meilisearch
File: index-scheduler/src/index_mapper.rs (Rust)

Code before:

        // We remove the index from the in-memory index map.
        let mut lock = self.index_map.write().unwrap();
        // check the existing value because we don't want to insert a new resize operation in the map if the index
        // is currently unavailable.
        let index = match lock.entry(uuid) {
            Entry::Occupied(mut occupied) => {
                // exchange the current index status in the entry with a dummy one so we can take ownership of the index
                // in the "available" case.
                // We will reset the index_status to an actual value in the match below.
                let index_status = std::mem::replace(occupied.get_mut(), BeingDeleted);
                match index_status {
                    Available(index) => {
                        // signal that will be sent when the resize operation completes
                        let resize_operation = Arc::new(SignalEvent::manual(false));
                        // temporarily block further attempts to get the index
                        *(occupied.get_mut()) = BeingResized(resize_operation);
                        index
                    }
                    // the index is already being deleted or resized, so let's ignore this new resize request.
                    entry @ (BeingDeleted | BeingResized(_)) => {
                        // reset the index_status to what it was
                        *(occupied.get_mut()) = entry;
                        return Ok(());
                    }
                }
            }
            // the index could not be found, so let's ignore this new resize request.
            Entry::Vacant(_) => return Ok(()),
        };

        drop(lock);

        let current_size = index.map_size()?;
        let closing_event = index.prepare_for_closing();
        log::info!("Resizing index {} from {} to {} bytes", name, current_size, current_size * 2);

        closing_event.wait();

        log::info!("Resized index {} from {} to {} bytes", name, current_size, current_size * 2);

        let index_path = self.base_path.join(uuid.to_string());
        let index = self.create_or_open_index(&index_path, None, 2 * current_size)?;

        // Add back the resized index
        let mut lock = self.index_map.write().unwrap();
        match lock.insert(uuid, Available(index)) {
            Some(BeingResized(resize_operation)) => {
                // drop the lock before signaling completion so that other threads don't immediately await on the lock after waking up.
                drop(lock);
                resize_operation.signal();

Review comment (suggestion):
I would prefer that we keep the computation of the new size localized. 😊 

```suggestion
        let current_size = index.map_size()?;
        let new_size = current_size * 2;
```

Code after:
        // fixme: factor to a function?
        let uuid = self
            .index_mapping
            .get(rtxn, name)?
            .ok_or_else(|| Error::IndexNotFound(name.to_string()))?;

        // We remove the index from the in-memory index map.
        let mut lock = self.index_map.write().unwrap();
        // signal that will be sent when the resize operation completes
        let resize_operation = Arc::new(SignalEvent::manual(false));
        let index = match lock.insert(uuid, BeingResized(resize_operation)) {
            Some(Available(index)) => index,
            Some(previous_status) => {
                lock.insert(uuid, previous_status);
                panic!(
                    "Attempting to resize index {name} that is already being resized or deleted."
                )
            }
            None => {
                panic!("Could not find the status of index {name} in the in-memory index mapper.")
            }
        };

        drop(lock);

        let resize_succeeded = (move || {
            let current_size = index.map_size()?;
            let new_size = current_size * 2;
            let closing_event = index.prepare_for_closing();

            log::debug!("Waiting for index {name} to close");

            if !closing_event.wait_timeout(std::time::Duration::from_secs(600)) {
                // fail after 10 minutes waiting
                panic!("Could not resize index {name} (unable to close it)");
            }

            log::info!("Resized index {name} from {current_size} to {new_size} bytes");
            let index_path = self.base_path.join(uuid.to_string());
            let index = self.create_or_open_index(&index_path, None, new_size)?;
            Ok(index)
        })();

        // Put the map back to a consistent state.
        // Even if there was an error we don't want to leave the map in an inconsistent state as it would cause
        // deadlocks.
        let mut lock = self.index_map.write().unwrap();
        let (resize_operation, resize_succeeded) = match resize_succeeded {
            Ok(index) => {
                // insert the resized index
                let Some(BeingResized(resize_operation)) = lock.insert(uuid, Available(index)) else {