@@ -428,21 +428,35 @@ impl AsyncStorage {
428428 // remote/folder/and/x.zip.index
429429 let remote_index_path = format ! ( "{archive_path}.{ARCHIVE_INDEX_FILE_EXTENSION}" ) ;
430430
431- tokio:: fs:: create_dir_all (
432- local_index_path
433- . parent ( )
434- . ok_or_else ( || anyhow ! ( "index path without parent" ) ) ?,
435- )
431+ let parent = local_index_path
432+ . parent ( )
433+ . ok_or_else ( || anyhow ! ( "index path without parent" ) ) ?
434+ . to_path_buf ( ) ;
435+ tokio:: fs:: create_dir_all ( & parent) . await ?;
436+
437+ let mut temp_path = spawn_blocking ( {
438+ // this creates the tempfile and directly drops it again,
439+ // just to return a valid temp-path.
440+ // This could be optimized.
441+ let folder = self . config . local_archive_cache_path . clone ( ) ;
442+ move || Ok ( tempfile:: NamedTempFile :: new_in ( & folder) ?. into_temp_path ( ) )
443+ } )
436444 . await ?;
437445
438- {
439- let mut file = tokio:: fs:: File :: create ( & local_index_path) . await ?;
440- let mut stream = self . get_stream ( & remote_index_path) . await ?. content ;
446+ let mut file = tokio:: fs:: File :: create ( & temp_path) . await ?;
447+ let mut stream = self . get_stream ( & remote_index_path) . await ?. content ;
448+ tokio:: io:: copy ( & mut stream, & mut file) . await ?;
449+ file. sync_all ( ) . await ?;
441450
442- tokio:: io:: copy ( & mut stream, & mut file) . await ?;
451+ temp_path. disable_cleanup ( true ) ;
452+ tokio:: fs:: rename ( & temp_path, & local_index_path) . await ?;
443453
444- file. flush ( ) . await ?;
445- }
454+ // fsync parent dir to make rename durable (blocking)
455+ spawn_blocking ( move || {
456+ let dir = std:: fs:: File :: open ( parent) ?;
457+ dir. sync_all ( ) . map_err ( Into :: into)
458+ } )
459+ . await ?;
446460 }
447461
448462 _read_guard = _write_guard. downgrade ( ) ;
0 commit comments