You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: directory.rs
    path of file: ./repos/spacedrive/core/src/object/media/old_thumbnail
    
    the code of the file until where you have to start completion: use crate::{
	library::{Libraries, LibraryId},
	object::media::old_thumbnail::ONE_SEC,
	util::version_manager::{Kind, ManagedVersion, VersionManager, VersionManagerError},
};

use sd_prisma::prisma::{file_path, PrismaClient};
use sd_utils::error::FileIOError;
use serde_repr::{Deserialize_repr, Serialize_repr};

use std::{
	collections::{HashMap, HashSet},
	path::{Path, PathBuf},
	sync::Arc,
};

use futures_concurrency::future::{Join, TryJoin};
use int_enum::IntEnum;
use tokio::{
	fs, io, spawn,
	time::{sleep, timeout},
};
use tracing::{debug, error, info, trace, warn};

use super::{
	get_shard_hex, ThumbnailerError, EPHEMERAL_DIR, THIRTY_SECS, THUMBNAIL_CACHE_DIR_NAME,
	VERSION_FILE, WEBP_EXTENSION,
};

#[derive(
	IntEnum, Debug, Clone, Copy, Eq, PartialEq, strum::Display, Serialize_repr, Deserialize_repr,
)]
#[repr(u64)]
pub enum ThumbnailVersion {
	V1 = 1,
	V2 = 2,
	V3 = 3,
}

impl ManagedVersion<Self> for ThumbnailVersion {
	const LATEST_VERSION: Self = Self::V3;

	const KIND: Kind = Kind::PlainText;

	type MigrationError = ThumbnailerError;

	fn from_latest_version() -> Option<Self> {
		Some(Self::LATEST_VERSION
    
async fn move_to_shards(thumbnails_directory: impl AsRef<Path>) -> Result<(), ThumbnailerError> {
	let thumbnails_directory = thumbnails_directory.as_ref();

	let mut dir_entries = fs::read_dir(thumbnails_directory)
		.await
		.map_err(|source| FileIOError::from((thumbnails_directory, source)))?;

	let mut count = 0;

	while let Ok(Some(entry)) = dir_entries.next_entry().await {
		if entry
			.file_type()
			.await
			.map_err(|e| FileIOError::from((entry.path(), e)))?
			.is_file()
		{
			let path = entry.path();
			if path.extension() == Some(WEBP_EXTENSION.as_ref()) {
				let file_name = entry.file_name();

				// we know they're cas_id's, so they're valid utf8
				let shard_folder = get_shard_hex(file_name.to_str().expect("Failed to parse UTF8"));

				let new_dir = thumbnails_directory.join(shard_folder);
				fs::create_dir_all(&new_dir)
					.await
					.map_err(|source| FileIOError::from((new_dir.clone(), source)))?;

				let new_path = new_dir.join(file_name);
				fs::rename(&path, &new_path)
					.await
					.map_err(|source| FileIOError::from((path.clone(), source)))?;
				count += 1;
			}
		}
	}

	info!(
		"Moved {} webp files to their respective shard folders.",
		count
	);

	Ok(())
}