Create multiple assets concurrently #5

Merged
Quaternions merged 16 commits from staging into master 2024-08-17 18:00:28 +00:00
2 changed files with 31 additions and 25 deletions
Showing only changes of commit 7870723b31 - Show all commits

View File

@ -14,26 +14,27 @@ pub struct CreateAssetRequest{
pub displayName:String, pub displayName:String,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum CreateAssetResponseGetAssetError{ pub enum AssetOperationError{
Operation(OperationError), Operation(OperationError),
Serialize(serde_json::Error), Serialize(serde_json::Error),
} }
impl std::fmt::Display for CreateAssetResponseGetAssetError{ impl std::fmt::Display for AssetOperationError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}") write!(f,"{self:?}")
} }
} }
impl std::error::Error for CreateAssetResponseGetAssetError{} impl std::error::Error for AssetOperationError{}
pub struct CreateAssetResponse{ #[derive(Debug)]
pub struct AssetOperation{
operation:RobloxOperation, operation:RobloxOperation,
} }
impl CreateAssetResponse{ impl AssetOperation{
pub async fn try_get_asset(&self,context:&CloudContext)->Result<AssetResponse,CreateAssetResponseGetAssetError>{ pub async fn try_get_asset(&self,context:&CloudContext)->Result<AssetResponse,AssetOperationError>{
serde_json::from_value( serde_json::from_value(
self.operation self.operation
.try_get_reponse(context).await .try_get_reponse(context).await
.map_err(CreateAssetResponseGetAssetError::Operation)? .map_err(AssetOperationError::Operation)?
).map_err(CreateAssetResponseGetAssetError::Serialize) ).map_err(AssetOperationError::Serialize)
} }
} }
#[derive(Debug)] #[derive(Debug)]
@ -111,8 +112,8 @@ impl std::fmt::Display for UpdateError{
} }
impl std::error::Error for UpdateError{} impl std::error::Error for UpdateError{}
pub struct GetAssetOperationRequest{ struct GetAssetOperationRequest{
pub operation_id:String, operation_id:String,
} }
pub struct GetAssetInfoRequest{ pub struct GetAssetInfoRequest{
pub asset_id:u64, pub asset_id:u64,
@ -260,7 +261,7 @@ impl std::fmt::Display for OperationError{
impl std::error::Error for OperationError{} impl std::error::Error for OperationError{}
#[derive(Debug,serde::Deserialize,serde::Serialize)] #[derive(Debug,serde::Deserialize,serde::Serialize)]
#[allow(nonstandard_style,dead_code)] #[allow(nonstandard_style,dead_code)]
pub struct RobloxOperation{ struct RobloxOperation{
pub path:Option<String>, pub path:Option<String>,
pub metadata:Option<String>, pub metadata:Option<String>,
pub done:Option<bool>, pub done:Option<bool>,
@ -354,7 +355,7 @@ impl CloudContext{
.multipart(form) .multipart(form)
.send().await .send().await
} }
pub async fn create_asset(&self,config:CreateAssetRequest,body:impl Into<std::borrow::Cow<'static,[u8]>>)->Result<CreateAssetResponse,CreateError>{ pub async fn create_asset(&self,config:CreateAssetRequest,body:impl Into<std::borrow::Cow<'static,[u8]>>)->Result<AssetOperation,CreateError>{
let url=reqwest::Url::parse("https://apis.roblox.com/assets/v1/assets").map_err(CreateError::Parse)?; 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)?; let request_config=serde_json::to_string(&config).map_err(CreateError::Serialize)?;
@ -367,15 +368,16 @@ impl CloudContext{
.text("request",request_config) .text("request",request_config)
.part("fileContent",part); .part("fileContent",part);
let operation=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)? .error_for_status().map_err(CreateError::Reqwest)?
.json::<RobloxOperation>().await.map_err(CreateError::Reqwest)?; .json::<RobloxOperation>().await.map_err(CreateError::Reqwest)?;
Ok(CreateAssetResponse{ Ok(AssetOperation{
operation, operation,
}) })
} }
pub async fn update_asset(&self,config:UpdateAssetRequest,body:impl Into<std::borrow::Cow<'static,[u8]>>)->Result<RobloxOperation,UpdateError>{ pub async fn update_asset(&self,config:UpdateAssetRequest,body:impl Into<std::borrow::Cow<'static,[u8]>>)->Result<AssetOperation,UpdateError>{
let raw_url=format!("https://apis.roblox.com/assets/v1/assets/{}",config.assetId); let raw_url=format!("https://apis.roblox.com/assets/v1/assets/{}",config.assetId);
let url=reqwest::Url::parse(raw_url.as_str()).map_err(UpdateError::ParseError)?; let url=reqwest::Url::parse(raw_url.as_str()).map_err(UpdateError::ParseError)?;
@ -385,13 +387,17 @@ impl CloudContext{
.text("request",request_config) .text("request",request_config)
.part("fileContent",reqwest::multipart::Part::bytes(body)); .part("fileContent",reqwest::multipart::Part::bytes(body));
self.patch_form(url,form).await let operation=self.patch_form(url,form).await
.map_err(UpdateError::Reqwest)? .map_err(UpdateError::Reqwest)?
//roblox api documentation is very poor, just give the status code and drop the json //roblox api documentation is very poor, just give the status code and drop the json
.error_for_status().map_err(UpdateError::Reqwest)? .error_for_status().map_err(UpdateError::Reqwest)?
.json::<RobloxOperation>().await.map_err(UpdateError::Reqwest) .json::<RobloxOperation>().await.map_err(UpdateError::Reqwest)?;
Ok(AssetOperation{
operation,
})
} }
pub async fn get_asset_operation(&self,config:GetAssetOperationRequest)->Result<RobloxOperation,GetError>{ async fn get_asset_operation(&self,config:GetAssetOperationRequest)->Result<RobloxOperation,GetError>{
let raw_url=format!("https://apis.roblox.com/assets/v1/operations/{}",config.operation_id); let raw_url=format!("https://apis.roblox.com/assets/v1/operations/{}",config.operation_id);
let url=reqwest::Url::parse(raw_url.as_str()).map_err(GetError::ParseError)?; let url=reqwest::Url::parse(raw_url.as_str()).map_err(GetError::ParseError)?;

View File

@ -624,13 +624,13 @@ struct CreateAssetMediaConfig{
async fn get_asset_exp_backoff( async fn get_asset_exp_backoff(
context:&CloudContext, context:&CloudContext,
create_asset_response:&rbx_asset::cloud::CreateAssetResponse asset_operation:&rbx_asset::cloud::AssetOperation
)->Result<rbx_asset::cloud::AssetResponse,rbx_asset::cloud::CreateAssetResponseGetAssetError>{ )->Result<rbx_asset::cloud::AssetResponse,rbx_asset::cloud::AssetOperationError>{
let mut backoff:u16=0; let mut backoff:u16=0;
loop{ loop{
match create_asset_response.try_get_asset(&context).await{ match asset_operation.try_get_asset(&context).await{
//try again when the operation is not done //try again when the operation is not done
Err(rbx_asset::cloud::CreateAssetResponseGetAssetError::Operation(rbx_asset::cloud::OperationError::NotDone))=>(), Err(rbx_asset::cloud::AssetOperationError::Operation(rbx_asset::cloud::OperationError::NotDone))=>(),
//return all other results //return all other results
other_result=>return other_result, other_result=>return other_result,
} }
@ -690,7 +690,7 @@ impl std::error::Error for CreateAssetMediasError{}
#[allow(dead_code)] #[allow(dead_code)]
enum PollOperationError{ enum PollOperationError{
CreateAssetMedias(CreateAssetMediasError), CreateAssetMedias(CreateAssetMediasError),
CreateAssetResponseGetAsset(rbx_asset::cloud::CreateAssetResponseGetAssetError), AssetOperation(rbx_asset::cloud::AssetOperationError),
} }
impl std::fmt::Display for PollOperationError{ impl std::fmt::Display for PollOperationError{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)->std::fmt::Result{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>)->std::fmt::Result{
@ -762,8 +762,8 @@ async fn create_asset_medias(config:CreateAssetMediasConfig)->AResult<()>{
let context=&context; let context=&context;
async{(path, async{(path,
async{ async{
let create_asset_response=create_result.map_err(PollOperationError::CreateAssetMedias)?; let asset_operation=create_result.map_err(PollOperationError::CreateAssetMedias)?;
get_asset_exp_backoff(context,&create_asset_response).await.map_err(PollOperationError::CreateAssetResponseGetAsset) get_asset_exp_backoff(context,&asset_operation).await.map_err(PollOperationError::AssetOperation)
} }
.await)} .await)}
}) })