pub async fn run(
        self,
        mut stop_receiver: watch::Receiver<bool>,
    ) -> Result<SnapshotApplierTaskStats, OrStopped> {
        tracing::info!("Starting snapshot recovery with config: {:?}", self.config);

        let mut backoff = self.config.initial_retry_backoff;
        let mut last_error = None;
        for retry_id in 0..self.config.retry_count {
            if *stop_receiver.borrow() {
                return Err(OrStopped::Stopped);
            }

            let result = SnapshotsApplierOrStatus::load_snapshot(&self, &mut stop_receiver).await;
            match result {
                Ok((strategy, final_status)) => {
                    let health_details = SnapshotsApplierHealthDetails::done(&final_status)?;
                    self.health_updater
                        .update(Health::from(HealthStatus::Ready).with_details(health_details));
                    // Freeze the health check in the "ready" status, so that the snapshot recovery isn't marked
                    // as "shut down", which would lead to the app considered unhealthy.
                    self.health_updater.freeze();
                    return Ok(SnapshotApplierTaskStats {
                        done_work: !matches!(strategy, SnapshotRecoveryStrategy::Completed),
                    });
                }
                Err(OrStopped::Internal(SnapshotsApplierError::Fatal(err))) => {
                    tracing::error!("Fatal error occurred during snapshots recovery: {err:?}");
                    return Err(err.into());
                }
                Err(OrStopped::Internal(SnapshotsApplierError::Retryable(err))) => {
                    tracing::warn!("Retryable error occurred during snapshots recovery: {err:?}");
                    last_error = Some(err);
                    tracing::info!(
                        "Recovering from error; attempt {retry_id} / {}, retrying in {backoff:?}",
                        self.config.retry_count
                    );
                    tokio::time::timeout(backoff, stop_receiver.changed())
                        .await
                        .ok();
                    // Stop receiver will be checked on the next iteration.
                    backoff = backoff.mul_f32(self.config.retry_backoff_multiplier);
                }
                Err(OrStopped::Stopped) => {
                    tracing::info!("Snapshot recovery has been canceled");
                    return Err(OrStopped::Stopped);
                }
            }
        }

        let last_error = last_error.unwrap(); // `unwrap()` is safe: `last_error` was assigned at least once
        tracing::error!("Snapshot recovery run out of retries; last error: {last_error:?}");
        Err(last_error.into())
    }
Runs the snapshot applier with these options.

# Errors

This method will return an error if a fatal error occurs during recovery (e.g., the DB is unreachable),
or under any of the following conditions:

- There are no snapshots on the main node
core/lib/snapshots_applier/src/lib.rs