@@ -29,6 +29,7 @@ use bytesize::ByteSize;
29
29
use flate2:: write:: GzEncoder ;
30
30
use flate2:: Compression ;
31
31
use futures_util:: TryStreamExt ;
32
+ use http:: header:: CONTENT_LENGTH ;
32
33
use indicatif:: { ProgressBar , ProgressStyle } ;
33
34
34
35
pub struct ChunkParams {
@@ -954,6 +955,104 @@ pub async fn upload_data_chunk_to_server_with_retry(
954
955
) ) )
955
956
}
956
957
958
+ pub async fn upload_data_chunk_to_server_with_client_with_retry (
959
+ client : & reqwest:: Client ,
960
+ remote_repo : & RemoteRepository ,
961
+ chunk : & [ u8 ] ,
962
+ hash : & str ,
963
+ params : & ChunkParams ,
964
+ is_compressed : bool ,
965
+ filename : & Option < String > ,
966
+ ) -> Result < ( ) , OxenError > {
967
+ let mut total_tries = 0 ;
968
+ let mut last_error = String :: from ( "" ) ;
969
+ while total_tries < constants:: NUM_HTTP_RETRIES {
970
+ match upload_data_chunk_to_server_with_client (
971
+ client,
972
+ remote_repo,
973
+ chunk,
974
+ hash,
975
+ params,
976
+ is_compressed,
977
+ filename,
978
+ )
979
+ . await
980
+ {
981
+ Ok ( _) => {
982
+ return Ok ( ( ) ) ;
983
+ }
984
+ Err ( err) => {
985
+ total_tries += 1 ;
986
+ // Exponentially back off
987
+ let sleep_time = total_tries * total_tries;
988
+ log:: debug!(
989
+ "upload_data_chunk_to_server_with_client_with_retry upload failed sleeping {}: {}" ,
990
+ sleep_time,
991
+ err
992
+ ) ;
993
+ last_error = format ! ( "{}" , err) ;
994
+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( sleep_time) ) ;
995
+ }
996
+ }
997
+ }
998
+
999
+ Err ( OxenError :: basic_str ( format ! (
1000
+ "Upload chunk retry failed. {}" ,
1001
+ last_error
1002
+ ) ) )
1003
+ }
1004
+
1005
+ async fn upload_data_chunk_to_server_with_client (
1006
+ client : & reqwest:: Client ,
1007
+ remote_repo : & RemoteRepository ,
1008
+ chunk : & [ u8 ] ,
1009
+ hash : & str ,
1010
+ params : & ChunkParams ,
1011
+ is_compressed : bool ,
1012
+ filename : & Option < String > ,
1013
+ ) -> Result < StatusMessage , OxenError > {
1014
+ let maybe_filename = if !is_compressed {
1015
+ format ! (
1016
+ "&filename={}" ,
1017
+ urlencoding:: encode(
1018
+ filename
1019
+ . as_ref( )
1020
+ . expect( "Must provide filename if !compressed" )
1021
+ )
1022
+ )
1023
+ } else {
1024
+ String :: from ( "" )
1025
+ } ;
1026
+
1027
+ let uri = format ! (
1028
+ "/commits/upload_chunk?chunk_num={}&total_size={}&hash={}&total_chunks={}&is_compressed={}{}" ,
1029
+ params. chunk_num, params. total_size, hash, params. total_chunks, is_compressed, maybe_filename) ;
1030
+ let url = api:: endpoint:: url_from_repo ( remote_repo, & uri) ?;
1031
+ let total_size = chunk. len ( ) as u64 ;
1032
+ log:: debug!(
1033
+ "upload_data_chunk_to_server posting {} to url {}" ,
1034
+ ByteSize :: b( total_size) ,
1035
+ url
1036
+ ) ;
1037
+
1038
+ let res = client
1039
+ . post ( & url)
1040
+ . header ( CONTENT_LENGTH , total_size. to_string ( ) )
1041
+ . body ( chunk. to_owned ( ) )
1042
+ . send ( )
1043
+ . await ?;
1044
+ let body = client:: parse_json_body ( & url, res) . await ?;
1045
+
1046
+ log:: debug!( "upload_data_chunk_to_server got response {}" , body) ;
1047
+ let response: Result < StatusMessage , serde_json:: Error > = serde_json:: from_str ( & body) ;
1048
+ match response {
1049
+ Ok ( response) => Ok ( response) ,
1050
+ Err ( err) => Err ( OxenError :: basic_str ( format ! (
1051
+ "upload_data_chunk_to_server Err deserializing: {err}"
1052
+ ) ) ) ,
1053
+ }
1054
+ }
1055
+
957
1056
async fn upload_data_chunk_to_server (
958
1057
remote_repo : & RemoteRepository ,
959
1058
chunk : & [ u8 ] ,
@@ -990,23 +1089,16 @@ async fn upload_data_chunk_to_server(
990
1089
. timeout ( time:: Duration :: from_secs ( 120 ) )
991
1090
. build ( ) ?;
992
1091
993
- match client. post ( & url) . body ( chunk. to_owned ( ) ) . send ( ) . await {
994
- Ok ( res) => {
995
- let body = client:: parse_json_body ( & url, res) . await ?;
1092
+ let res = client. post ( & url) . body ( chunk. to_owned ( ) ) . send ( ) . await ?;
1093
+ let body = client:: parse_json_body ( & url, res) . await ?;
996
1094
997
- log:: debug!( "upload_data_chunk_to_server got response {}" , body) ;
998
- let response: Result < StatusMessage , serde_json:: Error > = serde_json:: from_str ( & body) ;
999
- match response {
1000
- Ok ( response) => Ok ( response) ,
1001
- Err ( err) => Err ( OxenError :: basic_str ( format ! (
1002
- "upload_data_chunk_to_server Err deserializing: {err}"
1003
- ) ) ) ,
1004
- }
1005
- }
1006
- Err ( e) => {
1007
- let err_str = format ! ( "Err upload_data_chunk_to_server: {e:?}" ) ;
1008
- Err ( OxenError :: basic_str ( err_str) )
1009
- }
1095
+ log:: debug!( "upload_data_chunk_to_server got response {}" , body) ;
1096
+ let response: Result < StatusMessage , serde_json:: Error > = serde_json:: from_str ( & body) ;
1097
+ match response {
1098
+ Ok ( response) => Ok ( response) ,
1099
+ Err ( err) => Err ( OxenError :: basic_str ( format ! (
1100
+ "upload_data_chunk_to_server Err deserializing: {err}"
1101
+ ) ) ) ,
1010
1102
}
1011
1103
}
1012
1104
0 commit comments