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

Code before:
            return Err(Error::UnrecoverableError(Box::new(
                Error::IndexSchedulerVersionMismatch {
                    index_scheduler_version: version.unwrap_or((1, 12, 0)),
                    package_version,
                },
            )));
        }

        // 2. we get the next task to delete
        let to_delete = self.queue.tasks.get_kind(rtxn, Kind::TaskDeletion)? & enqueued;
        if !to_delete.is_empty() {
            let mut tasks = self.queue.tasks.get_existing_tasks(rtxn, to_delete)?;
            current_batch.processing(&mut tasks);
            current_batch
                .reason(BatchStopReason::TaskKindCannotBeBatched { kind: Kind::TaskDeletion });
            return Ok(Some((Batch::TaskDeletions(tasks), current_batch)));
        }

        // 3. we get the next task to compact
        let to_compact = self.queue.tasks.get_kind(rtxn, Kind::IndexCompaction)? & enqueued;
        if let Some(task_id) = to_compact.min() {
            let mut task =
                self.queue.tasks.get_task(rtxn, task_id)?.ok_or(Error::CorruptedTaskQueue)?;
            current_batch.processing(Some(&mut task));
            current_batch
                .reason(BatchStopReason::TaskKindCannotBeBatched { kind: Kind::IndexCompaction });
            let index_uid =
                task.index_uid().expect("Compaction task must have an index uid").to_owned();
            return Ok(Some((Batch::IndexCompaction { index_uid, task }, current_batch)));
        }

        // 4. we batch the export.
        let to_export = self.queue.tasks.get_kind(rtxn, Kind::Export)? & enqueued;
        if !to_export.is_empty() {
            let task_id = to_export.iter().next().expect("There must be at least one export task");
            let mut task = self.queue.tasks.get_task(rtxn, task_id)?.unwrap();
            current_batch.processing([&mut task]);
            current_batch.reason(BatchStopReason::TaskKindCannotBeBatched { kind: Kind::Export });
            return Ok(Some((Batch::Export { task }, current_batch)));
        }

        // 5. we batch the snapshot.
        let to_snapshot = self.queue.tasks.get_kind(rtxn, Kind::SnapshotCreation)? & enqueued;
        if !to_snapshot.is_empty() {
            let mut tasks = self.queue.tasks.get_existing_tasks(rtxn, to_snapshot)?;
            current_batch.processing(&mut tasks);
            current_batch
                .reason(BatchStopReason::TaskKindCannotBeBatched { kind: Kind::SnapshotCreation });
            return Ok(Some((Batch::SnapshotCreation(tasks), current_batch)));
        }


Review comment (performance):
nitpick: for the stop reason you want `TaskCannotBeBatched` so that the batch stop reason message reads:

> created batch containing only task with id {id} of type `{kind}` that cannot be batched with any other task.

rather than:

> stopped after the last task of type `{kind}` because they cannot be batched with tasks of any other type.

(the former is happening rather than the later)

Code after:
        }

        // 2. we get the next task to delete
        let to_delete = self.queue.tasks.get_kind(rtxn, Kind::TaskDeletion)? & enqueued;
        if !to_delete.is_empty() {
            let mut tasks = self.queue.tasks.get_existing_tasks(rtxn, to_delete)?;
            current_batch.processing(&mut tasks);
            current_batch
                .reason(BatchStopReason::TaskKindCannotBeBatched { kind: Kind::TaskDeletion });
            return Ok(Some((Batch::TaskDeletions(tasks), current_batch)));
        }

        // 3. we get the next task to compact
        let to_compact = self.queue.tasks.get_kind(rtxn, Kind::IndexCompaction)? & enqueued;
        if let Some(task_id) = to_compact.min() {
            let mut task =
                self.queue.tasks.get_task(rtxn, task_id)?.ok_or(Error::CorruptedTaskQueue)?;
            current_batch.processing(Some(&mut task));
            current_batch.reason(BatchStopReason::TaskCannotBeBatched {
                kind: Kind::IndexCompaction,
                id: task_id,
            });
            let index_uid =
                task.index_uid().expect("Compaction task must have an index uid").to_owned();
            return Ok(Some((Batch::IndexCompaction { index_uid, task }, current_batch)));
        }

        // 4. we batch the export.
        let to_export = self.queue.tasks.get_kind(rtxn, Kind::Export)? & enqueued;
        if !to_export.is_empty() {
            let task_id = to_export.iter().next().expect("There must be at least one export task");
            let mut task = self.queue.tasks.get_task(rtxn, task_id)?.unwrap();
            current_batch.processing([&mut task]);
            current_batch
                .reason(BatchStopReason::TaskCannotBeBatched { kind: Kind::Export, id: task_id });
            return Ok(Some((Batch::Export { task }, current_batch)));
        }

        // 5. we batch the snapshot.
        let to_snapshot = self.queue.tasks.get_kind(rtxn, Kind::SnapshotCreation)? & enqueued;
        if !to_snapshot.is_empty() {
            let mut tasks = self.queue.tasks.get_existing_tasks(rtxn, to_snapshot)?;
            current_batch.processing(&mut tasks);
            current_batch
                .reason(BatchStopReason::TaskKindCannotBeBatched { kind: Kind::SnapshotCreation });
            return Ok(Some((Batch::SnapshotCreation(tasks), current_batch)));
        }

        // 6. we batch the dumps.
        let to_dump = self.queue.tasks.get_kind(rtxn, Kind::DumpCreation)? & enqueued;
        if let Some(to_dump) = to_dump.min() {