From 206f5516634d1ec195f2d1b06c28a8481e131f05 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 16 Aug 2024 17:24:44 -0700 Subject: [PATCH] cloud: create_asset returns a queryable object --- rbx_asset/src/cloud.rs | 33 ++++++++++++++++++++++++++++++--- src/main.rs | 28 ++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/rbx_asset/src/cloud.rs b/rbx_asset/src/cloud.rs index de05590..45b7ae4 100644 --- a/rbx_asset/src/cloud.rs +++ b/rbx_asset/src/cloud.rs @@ -14,6 +14,29 @@ pub struct CreateAssetRequest{ pub displayName:String, } #[derive(Debug)] +pub enum CreateAssetResponseGetAssetError{ + Operation(OperationError), + Serialize(serde_json::Error), +} +impl std::fmt::Display for CreateAssetResponseGetAssetError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for CreateAssetResponseGetAssetError{} +pub struct CreateAssetResponse{ + operation:RobloxOperation, +} +impl CreateAssetResponse{ + pub async fn try_get_asset(&self,context:&CloudContext)->Result{ + serde_json::from_value( + self.operation + .try_get_reponse(context).await + .map_err(CreateAssetResponseGetAssetError::Operation)? + ).map_err(CreateAssetResponseGetAssetError::Serialize) + } +} +#[derive(Debug)] pub enum CreateError{ Parse(url::ParseError), Serialize(serde_json::Error), @@ -331,7 +354,7 @@ impl CloudContext{ .multipart(form) .send().await } - pub async fn create_asset(&self,config:CreateAssetRequest,body:impl Into>)->Result{ + pub async fn create_asset(&self,config:CreateAssetRequest,body:impl Into>)->Result{ let url=reqwest::Url::parse("https://apis.roblox.com/assets/v1/assets").map_err(CreateError::Parse)?; let request_config=serde_json::to_string(&config).map_err(CreateError::Serialize)?; @@ -344,9 +367,13 @@ impl CloudContext{ .text("request",request_config) .part("fileContent",part); - self.post_form(url,form).await.map_err(CreateError::Reqwest)? + let operation=self.post_form(url,form).await.map_err(CreateError::Reqwest)? .error_for_status().map_err(CreateError::Reqwest)? - .json::().await.map_err(CreateError::Reqwest) + .json::().await.map_err(CreateError::Reqwest)?; + + Ok(CreateAssetResponse{ + operation, + }) } pub async fn update_asset(&self,config:UpdateAssetRequest,body:impl Into>)->Result{ let raw_url=format!("https://apis.roblox.com/assets/v1/assets/{}",config.assetId); diff --git a/src/main.rs b/src/main.rs index ff0ee97..b967d55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -575,8 +575,28 @@ struct CreateAssetMediaConfig{ expected_price:Option, } +async fn get_asset_exp_backoff( + context:&CloudContext, + create_asset_response:&rbx_asset::cloud::CreateAssetResponse +)->Result{ + let mut backoff:u64=0; + loop{ + match create_asset_response.try_get_asset(&context).await{ + //try again when the operation is not done + Err(rbx_asset::cloud::CreateAssetResponseGetAssetError::Operation(rbx_asset::cloud::OperationError::NotDone))=>(), + //return all other results + other_result=>return other_result, + } + let wait=f32::exp(backoff as f32/3.0)*1000f32; + println!("Operation not complete; waiting {:.0}ms...",wait); + tokio::time::sleep(std::time::Duration::from_millis(wait as u64)).await; + backoff+=1; + } +} + async fn create_asset_media(config:CreateAssetMediaConfig)->AResult<()>{ - let resp=CloudContext::new(config.api_key) + let context=CloudContext::new(config.api_key); + let asset_response=context .create_asset(rbx_asset::cloud::CreateAssetRequest{ assetType:config.asset_type, displayName:config.model_name, @@ -586,7 +606,11 @@ async fn create_asset_media(config:CreateAssetMediaConfig)->AResult<()>{ expectedPrice:Some(config.expected_price.unwrap_or(0)), } },tokio::fs::read(config.input_file).await?).await?; - println!("CreateResponse={:?}",resp); + //hardcode a 2 second sleep because roblox be slow + println!("Asset submitted, waiting 2s..."); + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + let asset=get_asset_exp_backoff(&context,&asset_response).await?; + println!("CreateResponse={:?}",asset); Ok(()) }