redo it without filter_map - errors are propagated through

This commit is contained in:
Quaternions 2024-08-16 23:47:46 -07:00
parent 57a163dfb1
commit b9d2a1fbc7

View File

@ -626,7 +626,7 @@ async fn get_asset_exp_backoff(
context:&CloudContext, context:&CloudContext,
create_asset_response:&rbx_asset::cloud::CreateAssetResponse create_asset_response:&rbx_asset::cloud::CreateAssetResponse
)->Result<rbx_asset::cloud::AssetResponse,rbx_asset::cloud::CreateAssetResponseGetAssetError>{ )->Result<rbx_asset::cloud::AssetResponse,rbx_asset::cloud::CreateAssetResponseGetAssetError>{
let mut backoff:u64=0; let mut backoff:u16=0;
loop{ loop{
match create_asset_response.try_get_asset(&context).await{ match create_asset_response.try_get_asset(&context).await{
//try again when the operation is not done //try again when the operation is not done
@ -672,9 +672,12 @@ struct CreateAssetMediasConfig{
} }
#[derive(Debug)] #[derive(Debug)]
#[allow(dead_code)]
enum CreateAssetMediasError{ enum CreateAssetMediasError{
NoFileStem(PathBuf), NoFileStem(PathBuf),
UnknownFourCC(Option<Vec<u8>>), IO(std::io::Error),
UnknownFourCC(Option<[u8;4]>),
Create(rbx_asset::cloud::CreateError),
} }
impl std::fmt::Display for CreateAssetMediasError{ impl std::fmt::Display for CreateAssetMediasError{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)->std::fmt::Result{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>)->std::fmt::Result{
@ -684,7 +687,22 @@ impl std::fmt::Display for CreateAssetMediasError{
impl std::error::Error for CreateAssetMediasError{} impl std::error::Error for CreateAssetMediasError{}
#[derive(Debug)] #[derive(Debug)]
#[allow(dead_code)]
enum PollOperationError{
CreateAssetMedias(CreateAssetMediasError),
CreateAssetResponseGetAsset(rbx_asset::cloud::CreateAssetResponseGetAssetError),
}
impl std::fmt::Display for PollOperationError{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for PollOperationError{}
#[derive(Debug)]
#[allow(dead_code)]
enum DownloadDecalError{ enum DownloadDecalError{
PollOperation(PollOperationError),
ParseInt(std::num::ParseIntError), ParseInt(std::num::ParseIntError),
Get(rbx_asset::cookie::GetError), Get(rbx_asset::cookie::GetError),
LoadDom(LoadDomError), LoadDom(LoadDomError),
@ -703,7 +721,7 @@ async fn create_asset_medias(config:CreateAssetMediasConfig)->AResult<()>{
let context=CloudContext::new(config.api_key); let context=CloudContext::new(config.api_key);
let cookie_context=CookieContext::new(config.cookie); let cookie_context=CookieContext::new(config.cookie);
let expected_price=Some(config.expected_price.unwrap_or(0)); let expected_price=Some(config.expected_price.unwrap_or(0));
let asset_id_list=futures::stream::iter(config.input_files.into_iter() futures::stream::iter(config.input_files.into_iter()
//step 1: read file, make create request //step 1: read file, make create request
.map(|path|{ .map(|path|{
let description=&config.description; let description=&config.description;
@ -712,9 +730,9 @@ async fn create_asset_medias(config:CreateAssetMediasConfig)->AResult<()>{
async move{ async move{
let model_name=path.file_stem() let model_name=path.file_stem()
.and_then(std::ffi::OsStr::to_str) .and_then(std::ffi::OsStr::to_str)
.ok_or(CreateAssetMediasError::NoFileStem(path.clone()))? .ok_or_else(||CreateAssetMediasError::NoFileStem(path.clone()))?
.to_owned(); .to_owned();
let file=tokio::fs::read(path).await?; let file=tokio::fs::read(path).await.map_err(CreateAssetMediasError::IO)?;
let asset_type=match file.get(0..4){ let asset_type=match file.get(0..4){
//png //png
Some(b"\x89PNG")=>rbx_asset::cloud::AssetType::Decal, Some(b"\x89PNG")=>rbx_asset::cloud::AssetType::Decal,
@ -722,9 +740,9 @@ async fn create_asset_medias(config:CreateAssetMediasConfig)->AResult<()>{
Some(b"\xFF\xD8\xFF\xE0")=>rbx_asset::cloud::AssetType::Decal, Some(b"\xFF\xD8\xFF\xE0")=>rbx_asset::cloud::AssetType::Decal,
//Some("fbx")=>rbx_asset::cloud::AssetType::Model, //Some("fbx")=>rbx_asset::cloud::AssetType::Model,
//Some("ogg")=>rbx_asset::cloud::AssetType::Audio, //Some("ogg")=>rbx_asset::cloud::AssetType::Audio,
fourcc=>Err(CreateAssetMediasError::UnknownFourCC(fourcc.map(<[u8]>::to_owned)))?, fourcc=>Err(CreateAssetMediasError::UnknownFourCC(fourcc.map(|s|s.try_into().unwrap())))?,
}; };
Ok(context.create_asset(rbx_asset::cloud::CreateAssetRequest{ context.create_asset(rbx_asset::cloud::CreateAssetRequest{
assetType:asset_type, assetType:asset_type,
displayName:model_name, displayName:model_name,
description:description.clone(), description:description.clone(),
@ -732,59 +750,46 @@ async fn create_asset_medias(config:CreateAssetMediasConfig)->AResult<()>{
creator:creator.clone(), creator:creator.clone(),
expectedPrice:expected_price, expectedPrice:expected_price,
} }
},file).await?) },file).await.map_err(CreateAssetMediasError::Create)
} }
})) }))
//parallel requests //parallel requests
.buffer_unordered(CONCURRENT_REQUESTS) .buffer_unordered(CONCURRENT_REQUESTS)
//step 2: poll operation until it completes //step 2: poll operation until it completes
.filter_map(|create_result:AResult<_>|{ .then(|create_result|{
let context=&context; let context=&context;
async{ async{
match create_result{ let create_asset_response=create_result.map_err(PollOperationError::CreateAssetMedias)?;
Ok(create_asset_response)=>match get_asset_exp_backoff(context,&create_asset_response).await{ get_asset_exp_backoff(context,&create_asset_response).await.map_err(PollOperationError::CreateAssetResponseGetAsset)
Ok(asset_response)=>Some(asset_response),
Err(e)=>{
eprintln!("operation error: {}",e);
None
},
},
Err(e)=>{
eprintln!("create_asset error: {}",e);
None
},
}
} }
}) })
//step 3: read decal id from operation and download it, decode it as a roblox file and extract the texture content url //step 3: read decal id from operation and download it, decode it as a roblox file and extract the texture content url
.filter_map(|asset_response|{ .then(|asset_response_result|{
let parse_result=asset_response.assetId.parse(); let cookie_context=&cookie_context;
async{ async move{
match async{ let asset_response=asset_response_result.map_err(DownloadDecalError::PollOperation)?;
let file=cookie_context.get_asset(rbx_asset::cookie::GetAssetRequest{ let file=cookie_context.get_asset(rbx_asset::cookie::GetAssetRequest{
asset_id:parse_result.map_err(DownloadDecalError::ParseInt)?, asset_id:asset_response.assetId.parse().map_err(DownloadDecalError::ParseInt)?,
version:None, version:None,
}).await.map_err(DownloadDecalError::Get)?; }).await.map_err(DownloadDecalError::Get)?;
let dom=load_dom(std::io::Cursor::new(file)).map_err(DownloadDecalError::LoadDom)?; let dom=load_dom(std::io::Cursor::new(file)).map_err(DownloadDecalError::LoadDom)?;
let instance=dom.get_by_ref( let instance=dom.get_by_ref(
*dom.root().children().first().ok_or(DownloadDecalError::NoFirstInstance)? *dom.root().children().first().ok_or(DownloadDecalError::NoFirstInstance)?
).ok_or(DownloadDecalError::NoFirstInstance)?; ).ok_or(DownloadDecalError::NoFirstInstance)?;
match instance.properties.get("Texture").ok_or(DownloadDecalError::NoTextureProperty)?{ let texture=instance.properties.get("Texture").ok_or(DownloadDecalError::NoTextureProperty)?;
rbx_dom_weak::types::Variant::Content(url)=>Ok(url.clone().into_string()), let asset_url=match texture{
_=>Err(DownloadDecalError::TexturePropertyInvalid), rbx_dom_weak::types::Variant::Content(url)=>url.clone().into_string(),
} _=>Err(DownloadDecalError::TexturePropertyInvalid)?,
}.await{ };
Ok(asset_url)=>Some((asset_response.displayName,asset_url)), Ok::<_,DownloadDecalError>((asset_response.displayName,asset_url))
Err(e)=>{
eprintln!("get_asset error: {}",e);
None
},
}
} }
}).collect::<Vec<(String,String)>>().await; })
for (file_name,asset_url) in asset_id_list{ .for_each(|download_decal_result|async{
println!("{}={}",file_name,asset_url); match download_decal_result{
} Ok((file_name,asset_url))=>println!("{}={}",file_name,asset_url),
Err(e)=>eprintln!("ERROR error={e}"),
}
}).await;
Ok(()) Ok(())
} }