Skip to content

Commit b57925e

Browse files
committed
Fix race condition
If we download first time url, it will create cache file and keep updating it until download complete. Race condition exist, when second request for same file comes, and it will pickup incomplete file. Signed-off-by: Denys Fedoryshchenko <denys.f@collabora.com>
1 parent 0f3cbb1 commit b57925e

1 file changed

Lines changed: 23 additions & 2 deletions

File tree

src/azure.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ async fn get_file_from_blob(filename: String) -> ReceivedFile {
199199
}
200200
Err(e) => {
201201
eprintln!("Error getting blob URL: {:?}", e);
202+
return received_file;
202203
}
203204
}
204205
// append SAS token to blob URL
@@ -210,8 +211,26 @@ async fn get_file_from_blob(filename: String) -> ReceivedFile {
210211
let cache_filename_headers = format!("cache/{}.headers", digest.to_hex_lowercase());
211212
// check if cache file exists
212213
if std::path::Path::new(&cache_filename).exists() {
214+
// check if headers file exists, and if not wait up to 300 seconds
215+
// This is to avoid race condition, when we start to download file, but it is not yet completed
216+
// and second request to same file downloads incomplete file
217+
let mut headers_file_exists = false;
218+
for seconds in 0..300 {
219+
if std::path::Path::new(&cache_filename_headers).exists() {
220+
headers_file_exists = true;
221+
break;
222+
}
223+
std::thread::sleep(std::time::Duration::from_millis(1000));
224+
println!("Waiting for headers file {} to exist: {} seconds", cache_filename_headers, seconds);
225+
}
226+
227+
if !headers_file_exists {
228+
eprintln!("Headers file {} does not exist", cache_filename_headers);
229+
return received_file;
230+
}
213231
//println!("Cache file {} exists", cache_filename);
214232
// is cached file non-zero length?
233+
// is cached file non-zero length?
215234
let metadata = std::fs::metadata(&cache_filename).unwrap();
216235
if metadata.len() > 0 {
217236
//println!("Cache file {} is non-zero length", cache_filename);
@@ -229,6 +248,7 @@ async fn get_file_from_blob(filename: String) -> ReceivedFile {
229248
"Error deleting cached file {}: {:?}",
230249
cache_filename_headers, e
231250
);
251+
return received_file;
232252
}
233253
}
234254
match std::fs::remove_file(&cache_filename_headers) {
@@ -238,6 +258,7 @@ async fn get_file_from_blob(filename: String) -> ReceivedFile {
238258
"Error deleting cached file {}: {:?}",
239259
cache_filename_headers, e
240260
);
261+
return received_file;
241262
}
242263
}
243264
}
@@ -259,14 +280,14 @@ async fn get_file_from_blob(filename: String) -> ReceivedFile {
259280
eprintln!("Error getting blob: {:?}", response.status());
260281
return received_file;
261282
}
262-
save_headers_to_file(cache_filename_headers, response.headers().clone());
263283
received_file.headers = response.headers().clone();
284+
let resp_headers = response.headers().clone();
264285
let body = response.bytes().await.unwrap();
265286
// just write all to cache file
266287
let mut f = File::create(&cache_filename).unwrap();
267288
f.write_all(&body).unwrap();
268289
// write headers
269-
290+
save_headers_to_file(cache_filename_headers, resp_headers);
270291
received_file.cached_filename = cache_filename;
271292
received_file.valid = true;
272293
}

0 commit comments

Comments
 (0)