thumbnails builder for reuse

This commit is contained in:
Kasisnu committed 2024-02-16 12:51:54 +05:30
1 parent 5936ef87f4
commit 130326e7de
9 files changed
+261 -135

No files matched your search

Generated
+71 -58
View File
@@ -128,7 +128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -166,7 +166,7 @@ dependencies = [
"parse-size",
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -298,7 +298,7 @@ dependencies = [
"actix-router",
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -347,7 +347,7 @@ checksum = "9aa0b287c8de4a76b691f29dbb5451e8dd5b79d777eaf87350c9b0cbfdb5e968"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -358,7 +358,7 @@ checksum = "7c7db3d5a9718568e4cf4a537cfd7070e6e6ff7481510d0237fb529ac850f6d3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -681,7 +681,7 @@ checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -1210,7 +1210,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -1579,7 +1579,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -1672,7 +1672,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -1705,7 +1705,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [
"darling_core 0.20.3",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -1916,7 +1916,7 @@ dependencies = [
"diesel_table_macro_syntax",
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -1925,7 +1925,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5"
dependencies = [
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -1992,7 +1992,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -2640,7 +2640,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -2769,7 +2769,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http",
"indexmap 2.1.0",
"indexmap 2.2.3",
"slab",
"tokio",
"tokio-util",
@@ -3142,9 +3142,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.1.0"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
dependencies = [
"equivalent",
"hashbrown 0.14.2",
@@ -3227,6 +3227,7 @@ dependencies = [
"subprocess",
"subprocess_common",
"tempdir",
"thumbnail_generator",
"time 0.3.30",
"tokens",
"tokio",
@@ -3960,7 +3961,7 @@ dependencies = [
"heck",
"hmac 0.12.1",
"hyper",
"indexmap 2.1.0",
"indexmap 2.2.3",
"lazy_static",
"libc",
"log",
@@ -3995,7 +3996,7 @@ dependencies = [
"sqlx-mysql",
"sqlx-sqlite",
"syn 1.0.109",
"syn 2.0.39",
"syn 2.0.49",
"time 0.3.30",
"time-macros",
"tokio",
@@ -4292,7 +4293,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -4331,7 +4332,7 @@ checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a"
dependencies = [
"futures-core",
"futures-sink",
"indexmap 2.1.0",
"indexmap 2.2.3",
"js-sys",
"once_cell",
"pin-project-lite",
@@ -4593,7 +4594,7 @@ dependencies = [
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -4631,7 +4632,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -4760,9 +4761,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.69"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@@ -4842,9 +4843,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.33"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -5152,9 +5153,9 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.11.22"
version = "0.11.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
dependencies = [
"async-compression",
"base64 0.21.5",
@@ -5175,9 +5176,11 @@ dependencies = [
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-native-tls",
@@ -5285,7 +5288,7 @@ dependencies = [
"quote",
"rust-embed-utils",
"shellexpand",
"syn 2.0.39",
"syn 2.0.49",
"walkdir",
]
@@ -5615,22 +5618,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.193"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.193"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -5640,7 +5643,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224e6a14f315852940f3ec103125aa6482f0e224732ed91ed3330ed633077c34"
dependencies = [
"form_urlencoded",
"indexmap 2.1.0",
"indexmap 2.2.3",
"itoa 1.0.9",
"ryu",
"serde",
@@ -5648,11 +5651,11 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.108"
version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"indexmap 2.1.0",
"indexmap 2.2.3",
"itoa 1.0.9",
"ryu",
"serde",
@@ -5707,7 +5710,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -5789,7 +5792,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -5800,7 +5803,7 @@ checksum = "b93fb4adc70021ac1b47f7d45e8cc4169baaa7ea58483bc5b721d19a26202212"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -6078,7 +6081,7 @@ dependencies = [
"futures-util",
"hashlink",
"hex",
"indexmap 2.1.0",
"indexmap 2.2.3",
"log",
"memchr",
"native-tls",
@@ -6456,7 +6459,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -6668,9 +6671,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.39"
version = "2.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
dependencies = [
"proc-macro2",
"quote",
@@ -6778,7 +6781,17 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
name = "thumbnail_generator"
version = "0.1.0"
dependencies = [
"easyenv",
"log",
"reqwest",
"serde_json",
]
[[package]]
@@ -6944,7 +6957,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -7107,7 +7120,7 @@ version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap 2.1.0",
"indexmap 2.2.3",
"serde",
"serde_spanned",
"toml_datetime",
@@ -7194,7 +7207,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -7626,7 +7639,7 @@ version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ff05e3bac2c9428f57ade702667753ca3f5cf085e2011fe697de5bfd49aa72d"
dependencies = [
"indexmap 2.1.0",
"indexmap 2.2.3",
"serde",
"serde_json",
"utoipa-gen",
@@ -7642,7 +7655,7 @@ dependencies = [
"proc-macro2",
"quote",
"regex",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
@@ -7692,7 +7705,7 @@ dependencies = [
"pulldown-cmark",
"regex",
"semver 1.0.20",
"syn 2.0.39",
"syn 2.0.49",
"toml 0.7.8",
"url",
]
@@ -7833,7 +7846,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
"wasm-bindgen-shared",
]
@@ -7867,7 +7880,7 @@ checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -7880,9 +7893,9 @@ checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
[[package]]
name = "wasm-streams"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129"
dependencies = [
"futures-util",
"js-sys",
@@ -8245,7 +8258,7 @@ checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
"syn 2.0.49",
]
[[package]]
+1
View File
@@ -26,6 +26,7 @@ members = [
"crates/lib/api_clients/cloud_storage",
"crates/lib/api_clients/google_drive_common",
"crates/lib/api_clients/twitch_common",
"crates/lib/api_clients/thumbnail_generator",
"crates/lib/bootstrap",
"crates/lib/caching/memory_caching",
"crates/lib/caching/redis_caching",
@@ -36,8 +36,8 @@ impl Error for BucketClientError {}
impl BucketClient {
pub fn bucket(&self) -> &Bucket {
&self.bucket
pub fn bucket_name(&self) -> String {
self.bucket.name().to_string()
}
pub fn create(
@@ -0,0 +1,12 @@
[package]
name = "thumbnail_generator"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde_json = "1.0.113"
reqwest = "0.11.24"
easyenv = { path = "../../easyenv" }
log = "0.4.20"
@@ -0,0 +1 @@
pub mod task_client;
@@ -0,0 +1 @@
pub mod thumbnail_task;
@@ -0,0 +1,157 @@
use reqwest::Error;
use serde_json::{Value, json};
use log::error;
#[derive(Debug)]
pub enum ThumbnailTaskError {
InvalidTask,
RequestError,
}
struct ThumbnailTask{
bucket: String,
path: String,
source_mimetype: String,
output_mimetype: String,
output_extension: String,
output_suffix: String,
event_id: String,
}
#[derive(Debug)]
pub struct ThumbnailTaskBuilder{
bucket: Option<String>,
path: Option<String>,
source_mimetype: Option<String>,
output_mimetype: Option<String>,
output_extension: Option<String>,
output_suffix: Option<String>,
event_id: Option<String>,
}
impl ThumbnailTaskBuilder {
pub fn new() -> Self {
Self {
bucket: None,
path: None,
source_mimetype: None,
output_mimetype: None,
output_extension: None,
output_suffix: None,
event_id: None,
}
}
pub fn with_bucket(&mut self, bucket: &str) -> &mut Self {
self.bucket = Some(bucket.to_string());
self
}
pub fn with_path(&mut self, path: &str) -> &mut Self {
self.path = Some(path.to_string());
self
}
pub fn with_source_mimetype(&mut self, source_mimetype: &str) -> &mut Self {
self.source_mimetype = Some(source_mimetype.to_string());
self
}
pub fn with_output_mimetype(&mut self, output_mimetype: &str) -> &mut Self {
self.output_mimetype = Some(output_mimetype.to_string());
self
}
pub fn with_output_extension(&mut self, output_extension: &str) -> &mut Self {
self.output_extension = Some(output_extension.to_string());
self
}
pub fn with_output_suffix(&mut self, output_suffix: &str) -> &mut Self {
self.output_suffix = Some(output_suffix.to_string());
self
}
pub fn with_event_id(&mut self, event_id: &str) -> &mut Self {
self.event_id = Some(event_id.to_string());
self
}
fn build(&self) -> Result<ThumbnailTask, String> {
Ok(ThumbnailTask {
bucket: self.bucket.clone().ok_or("bucket is required")?,
path: self.path.clone().ok_or("path is required")?,
source_mimetype: self.source_mimetype.clone().ok_or("source_mimetype is required")?,
output_mimetype: self.output_mimetype.clone().ok_or("output_mimetype is required")?,
output_extension: self.output_extension.clone().ok_or("output_extension is required")?,
output_suffix: self.output_suffix.clone().unwrap_or("".to_string()),
event_id: self.event_id.clone().ok_or("event_id is required")?,
})
}
pub async fn send(&self) -> Result<(), ThumbnailTaskError> {
match self.build() {
Ok(task) => {
match task.send().await {
Ok(_) => Ok(()),
Err(_) => Err(ThumbnailTaskError::RequestError),
}
}
Err(_) => {
error!("Invalid thumbnail task: {:?}", self);
Err(ThumbnailTaskError::InvalidTask)
},
}
}
}
impl ThumbnailTask{
fn request_json(&self) -> Value {
let output_path = format!(
"{}-{}.{}",
self.path,
self.output_suffix,
self.output_extension);
let input = json!({
"bucket": self.bucket,
"path": self.path,
"type": self.source_mimetype,
});
let output = json!({
"bucket": self.bucket,
"path": output_path,
"type": self.output_mimetype,
});
// TODO@madhukar: add tags -> metadata for gcs objects
let tags = json!([]);
json!({
"event_id": self.event_id,
"input": input,
"output": output,
"tags": tags,
})
}
async fn send(&self) -> Result<(), reqwest::Error> {
// TODO: retries?
// TODO: move to config
let url = easyenv::get_env_string_or_default(
"THUMBNAIL_GENERATOR_API_URL",
"http://media-server.thumbnail-generator/tasks",
);
let client = reqwest::Client::new();
let task_json = self.request_json();
client.post(url)
.json(&task_json)
.send()
.await?
.error_for_status()?;
Ok(())
}
}
@@ -20,6 +20,7 @@ bootstrap = { path = "../../../lib/bootstrap" }
buckets = { path = "../../../_types/buckets" }
cloud_storage = { path = "../../../lib/api_clients/cloud_storage" }
google_drive_common = { path = "../../../lib/api_clients/google_drive_common" }
thumbnail_generator = { path = "../../../lib/api_clients/thumbnail_generator"}
collections = { path = "../../../lib/collections" }
composite_identifiers = { path = "../../../_types/composite_identifiers" }
concurrency = { path = "../../../lib/concurrency" }
@@ -26,6 +26,7 @@ use mysql_queries::queries::generic_inference::job::list_available_generic_infer
use mysql_queries::queries::media_files::create::insert_media_file_from_comfy_ui::{insert_media_file_from_comfy_ui, InsertArgs};
use mysql_queries::queries::media_files::get_media_file::get_media_file;
use mysql_queries::queries::model_weights::get::get_weight::get_weight_by_token;
use thumbnail_generator::task_client::thumbnail_task::ThumbnailTaskBuilder;
use crate::job::job_loop::job_success_result::{JobSuccessResult, ResultEntity};
use crate::job::job_loop::process_single_job_error::ProcessSingleJobError;
@@ -59,69 +60,6 @@ fn recursively_delete_files_in(path: &Path) -> std::io::Result<()> {
Ok(())
}
struct ThumbnailTask{
bucket: String,
path: String,
source_mimetype: String,
output_mimetype: String,
output_extension: String,
event_id: String,
}
impl ThumbnailTask{
fn new(bucket: &str, path: &str, source_mimetype: &str, output_mimetype: &str, event_id: String) -> Result<Self> {
let output_ext = get_file_extension(output_mimetype)?;
Ok(Self {
bucket: bucket.to_string(),
path: path.to_string(),
source_mimetype: source_mimetype.to_string(),
output_mimetype: output_mimetype.to_string(),
output_extension: output_ext.to_string(),
event_id: event_id.to_string(),
})
}
// Method to generate the JSON representation of the thumbnail task
fn create_json(&self) -> Value {
let output_path = format!("{}.{}", self.path, self.output_extension);
let input = json!({
"bucket": self.bucket,
"path": self.path,
"type": self.source_mimetype,
});
let output = json!({
"bucket": self.bucket,
"path": output_path,
"type": self.output_mimetype,
});
// TODO@madhukar: add tags -> metadata for gcs objects
let tags = json!([]);
json!({
"event_id": self.event_id,
"input": input,
"output": output,
"tags": tags,
})
}
async fn send(&self) -> Result<(), reqwest::Error> {
// TODO: retries?
// TODO: move to config
let url = "http://media-server.thumbnail-generator/tasks";
let client = reqwest::Client::new();
let task_json = self.create_json();
client.post(url)
.json(&task_json)
.send()
.await?
.error_for_status()?;
Ok(())
}
}
pub async fn process_job(args: ComfyProcessJobArgs<'_>) -> Result<JobSuccessResult, ProcessSingleJobError> {
let job = args.job;
@@ -529,21 +467,23 @@ pub async fn process_job(args: ComfyProcessJobArgs<'_>) -> Result<JobSuccessResu
};
for output_type in thumbnail_types {
// Attempt to create a ThumbnailTask
match ThumbnailTask::new(
&*args.job_dependencies.buckets.public_bucket_client.bucket().name(),
&*path_to_string(result_bucket_object_pathbuf.clone()),
mimetype.as_str(),
output_type,
job.id.0.to_string(),
) {
let thumbnail_task_result = ThumbnailTaskBuilder::new()
.with_bucket(&*args.job_dependencies.buckets.public_bucket_client.bucket_name())
.with_path(&*path_to_string(result_bucket_object_pathbuf.clone()))
.with_source_mimetype(mimetype.as_str())
.with_output_mimetype(output_type)
.with_output_suffix("thumb")
.with_output_extension(get_file_extension(output_type).unwrap())
.with_event_id(&job.id.0.to_string())
.send()
.await;
match (thumbnail_task_result) {
Ok(thumbnail_task) => {
if let Err(e) = thumbnail_task.send().await {
error!("Failed to send thumbnail task: {}", e);
}
debug!("Thumbnail task created: {:?}", thumbnail_task);
},
Err(e) => {
error!("Failed to create thumbnail task: {}", e);
error!("Failed to create thumbnail task: {:?}", e);
}
}
}