fn compute(&self, path: &Path) -> BoxFuture<'static, Result<CacheStatus, Self::Error>> {
        let cache_key = self.get_cache_key();
        log::trace!("Fetching file data for {}", cache_key);

        let path = path.to_owned();
        let object_id = self.0.object_id.clone();

        sentry::configure_scope(|scope| {
            scope.set_transaction(Some("download_file"));
            self.0.file_source.to_scope(scope);
            self.0.object_id.to_scope(scope);
        });

        let file_id = self.0.file_source.clone();
        let downloader = self.0.download_svc.clone();
        let tempfile = self.0.data_cache.tempfile();

        let future = async move {
            let download_file = tempfile?;
            let download_dir = download_file
                .path()
                .parent()
                .ok_or(ObjectError::NoTempDir)?;

            let status = downloader
                .download(file_id, download_file.path().to_owned())
                .await;

            match status {
                Ok(DownloadStatus::NotFound) => {
                    log::debug!("No debug file found for {}", cache_key);
                    return Ok(CacheStatus::Negative);
                }

                Err(e) => {
                    // We want to error-log "interesting" download errors so we can look them up
                    // in our internal sentry. We downgrade to debug-log for unactionable
                    // permissions errors. Since this function does a fresh download, it will never
                    // hit `CachedError`, but listing it for completeness is not a bad idea either.
                    match e {
                        DownloadError::Permissions | DownloadError::CachedError(_) => {
                            log::debug!("Error while downloading file: {}", LogError(&e))
                        }
                        _ => log::error!("Error while downloading file: {}", LogError(&e)),
                    }

                    return Ok(CacheStatus::CacheSpecificError(e.for_cache()));
                }

                Ok(DownloadStatus::Completed) => {
                    // fall-through
                }
            }

            log::trace!("Finished download of {}", cache_key);
            let decompress_result =
                decompress_object_file(&download_file, tempfile_in(download_dir)?);

            // Treat decompression errors as malformed files. It is more likely that
            // the error comes from a corrupt file than a local file system error.
            let mut decompressed = match decompress_result {
                Ok(decompressed) => decompressed,
                Err(e) => return Ok(CacheStatus::Malformed(e.to_string())),
            };

            // Seek back to the start and parse this object so we can deal with it.
            // Since objects in Sentry (and potentially also other sources) might be
            // multi-arch files (e.g. FatMach), we parse as Archive and try to
            // extract the wanted file.
            decompressed.seek(SeekFrom::Start(0))?;
            let view = ByteView::map_file(decompressed)?;
            let archive = match Archive::parse(&view) {
                Ok(archive) => archive,
                Err(e) => return Ok(CacheStatus::Malformed(e.to_string())),
            };
            let mut persist_file = fs::File::create(&path)?;
            if archive.is_multi() {
                let object_opt = archive
                    .objects()
                    .filter_map(Result::ok)
                    .find(|object| object_id.match_object(object));

                let object = match object_opt {
                    Some(object) => object,
                    None => {
                        if let Some(Err(err)) = archive.objects().find(|r| r.is_err()) {
                            return Ok(CacheStatus::Malformed(err.to_string()));
                        } else {
                            return Ok(CacheStatus::Negative);
                        }
                    }
                };

                io::copy(&mut object.data(), &mut persist_file)?;
            } else {
                // Attempt to parse the object to capture errors. The result can be
                // discarded as the object's data is the entire ByteView.
                if let Err(err) = archive.object_by_index(0) {
                    return Ok(CacheStatus::Malformed(err.to_string()));
                }

                io::copy(&mut view.as_ref(), &mut persist_file)?;
            }

            Ok(CacheStatus::Positive)
        };

        let future = async move {
            future.await.map_err(|e| {
                sentry::capture_error(&e);
                e
            })
        }
        .bind_hub(Hub::current());

        let type_name = self.0.file_source.source_type_name().into();

        let future = tokio::time::timeout(Duration::from_secs(600), future);
        let future = measure(
            "objects",
            m::timed_result,
            Some(("source_type", type_name)),
            future,
        );
        Box::pin(async move { future.await.map_err(|_| ObjectError::Timeout)? })
    }
/// Downloads the object file, processes it and returns whether the file is in the cache.
///
/// If the object file was successfully downloaded it is first decompressed.  If it is
/// an archive containing multiple objects, then next the object matching the code or
/// debug ID of our request is extracted first.  Finally the object is parsed with
/// symbolic to ensure it is not malformed.
///
/// If there is an error decompression then an `Err` of [`ObjectError`] is returned.  If the
/// parsing the final object file failed, or there is an error downloading the file an `Ok` with
/// [`CacheStatus::Malformed`] is returned.
///
/// If the object file did not exist on the source a [`CacheStatus::Negative`] will be
/// returned.
///
/// If there was an error downloading the object file, an `Ok` with
/// [`CacheStatus::CacheSpecificError`] is returned.
///
/// If the object file did not exist on the source an `Ok` with [`CacheStatus::Negative`] will
/// be returned.
Downloads the object file, processes it and returns whether the file is in the cache.
If the object file was successfully downloaded it is first decompressed.  If it is
an archive containing multiple objects, then next the object matching the code or
debug ID of our request is extracted first.  Finally the object is parsed with
symbolic to ensure it is not malformed.

If there is an error decompression then an `Err` of [`ObjectError`] is returned.  If the
parsing the final object file failed, or there is an error downloading the file an `Ok` with
[`CacheStatus::Malformed`] is returned.

If the object file did not exist on the source a [`CacheStatus::Negative`] will be
returned.

If there was an error downloading the object file, an `Ok` with
[`CacheStatus::CacheSpecificError`] is returned.

If the object file did not exist on the source an `Ok` with [`CacheStatus::Negative`] will
be returned.
Downloads the object file processes it and returns whether the file is in the cache . If the object file was successfully downloaded it is first decompressed . If it is an archive containing multiple objects then next the object matching the code or debug ID of our request is extracted first . Finally the object is parsed with symbolic to ensure it is not malformed . If there is an error decompression then an ` Err ` of [ ` ObjectError ` ] is returned . If the parsing the final object file failed or there is an error downloading the file an ` Ok ` with [ ` CacheStatus :: Malformed ` ] is returned . If the object file did not exist on the source a [ ` CacheStatus :: Negative ` ] will be returned . If there was an error downloading the object file an ` Ok ` with [ ` CacheStatus :: CacheSpecificError ` ] is returned . If the object file did not exist on the source an ` Ok ` with [ ` CacheStatus :: Negative ` ] will be returned .
fn compute(&self, path: &Path) -> BoxFuture<'static, Result<CacheStatus, Self::Error>> {
        let cache_key = self.get_cache_key();
        log::trace!("Fetching file data for {}", cache_key);
        let path = path.to_owned();
        let object_id = self.0.object_id.clone();
        sentry::configure_scope(|scope| {
            scope.set_transaction(Some("download_file"));
            self.0.file_source.to_scope(scope);
            self.0.object_id.to_scope(scope);
        });
        let file_id = self.0.file_source.clone();
        let downloader = self.0.download_svc.clone();
        let tempfile = self.0.data_cache.tempfile();
        let future = async move {
            let download_file = tempfile?;
            let download_dir = download_file
                .path()
                .parent()
                .ok_or(ObjectError::NoTempDir)?;
            let status = downloader
                .download(file_id, download_file.path().to_owned())
                .await;
            match status {
                Ok(DownloadStatus::NotFound) => {
                    log::debug!("No debug file found for {}", cache_key);
                    return Ok(CacheStatus::Negative);
                }
                Err(e) => {
                    // We want to error-log "interesting" download errors so we can look them up
                    // in our internal sentry. We downgrade to debug-log for unactionable
                    // permissions errors. Since this function does a fresh download, it will never
                    // hit `CachedError`, but listing it for completeness is not a bad idea either.
                    match e {
                        DownloadError::Permissions | DownloadError::CachedError(_) => {
                            log::debug!("Error while downloading file: {}", LogError(&e))
                        }
                        _ => log::error!("Error while downloading file: {}", LogError(&e)),
                    }
                    return Ok(CacheStatus::CacheSpecificError(e.for_cache()));
                }
                Ok(DownloadStatus::Completed) => {
                    // fall-through
                }
            }
            log::trace!("Finished download of {}", cache_key);
            let decompress_result =
                decompress_object_file(&download_file, tempfile_in(download_dir)?);
            // Treat decompression errors as malformed files. It is more likely that
            // the error comes from a corrupt file than a local file system error.
            let mut decompressed = match decompress_result {
                Ok(decompressed) => decompressed,
                Err(e) => return Ok(CacheStatus::Malformed(e.to_string())),
            };
            // Seek back to the start and parse this object so we can deal with it.
            // Since objects in Sentry (and potentially also other sources) might be
            // multi-arch files (e.g. FatMach), we parse as Archive and try to
            // extract the wanted file.
            decompressed.seek(SeekFrom::Start(0))?;
            let view = ByteView::map_file(decompressed)?;
            let archive = match Archive::parse(&view) {
                Ok(archive) => archive,
                Err(e) => return Ok(CacheStatus::Malformed(e.to_string())),
            };
            let mut persist_file = fs::File::create(&path)?;
            if archive.is_multi() {
                let object_opt = archive
                    .objects()
                    .filter_map(Result::ok)
                    .find(|object| object_id.match_object(object));
                let object = match object_opt {
                    Some(object) => object,
                    None => {
                        if let Some(Err(err)) = archive.objects().find(|r| r.is_err()) {
                            return Ok(CacheStatus::Malformed(err.to_string()));
                        } else {
                            return Ok(CacheStatus::Negative);
                        }
                    }
                };
                io::copy(&mut object.data(), &mut persist_file)?;
            } else {
                // Attempt to parse the object to capture errors. The result can be
                // discarded as the object's data is the entire ByteView.
                if let Err(err) = archive.object_by_index(0) {
                    return Ok(CacheStatus::Malformed(err.to_string()));
                }
                io::copy(&mut view.as_ref(), &mut persist_file)?;
            }
            Ok(CacheStatus::Positive)
        };
        let future = async move {
            future.await.map_err(|e| {
                sentry::capture_error(&e);
                e
            })
        }
        .bind_hub(Hub::current());
        let type_name = self.0.file_source.source_type_name().into();
        let future = tokio::time::timeout(Duration::from_secs(600), future);
        let future = measure(
            "objects",
            m::timed_result,
            Some(("source_type", type_name)),
            future,
        );
        Box::pin(async move { future.await.map_err(|_| ObjectError::Timeout)? })
    }
fn compute ( & self , path : & Path ) -> BoxFuture < ' static , Result < CacheStatus , Self :: Error > > { let cache_key = self . get_cache_key ( ) ; log :: trace ! ( " " cache_key ) ; let path = path . to_owned ( ) ; let object_id = self . 0 . object_id . clone ( ) ; sentry :: configure_scope ( | scope | { scope . set_transaction ( Some ( " " ) ) ; self . 0 . file_source . to_scope ( scope ) ; self . 0 . object_id . to_scope ( scope ) ; } ) ; let file_id = self . 0 . file_source . clone ( ) ; let downloader = self . 0 . download_svc . clone ( ) ; let tempfile = self . 0 . data_cache . tempfile ( ) ; let future = async move { let download_file = tempfile ? ; let download_dir = download_file . path ( ) . parent ( ) . ok_or ( ObjectError :: NoTempDir ) ? ; let status = downloader . download ( file_id , download_file . path ( ) . to_owned ( ) ) . await ; match status { Ok ( DownloadStatus :: NotFound ) => { log :: debug ! ( " " cache_key ) ; return Ok ( CacheStatus :: Negative ) ; } Err ( e ) => { // We want to error-log "interesting" download errors so we can look them up // in our internal sentry. We downgrade to debug-log for unactionable // permissions errors. Since this function does a fresh download, it will never // hit `CachedError`, but listing it for completeness is not a bad idea either. match e { DownloadError :: Permissions | DownloadError :: CachedError ( _ ) => { log :: debug ! ( " " LogError ( e ) ) } _ => log :: error ! ( " " LogError ( e ) ) , } return Ok ( CacheStatus :: CacheSpecificError ( e . for_cache ( ) ) ) ; } Ok ( DownloadStatus :: Completed ) => { // fall-through } } log :: trace ! ( " " cache_key ) ; let decompress_result = decompress_object_file ( & download_file , tempfile_in ( download_dir ) ? ) ; // Treat decompression errors as malformed files. It is more likely that // the error comes from a corrupt file than a local file system error. let mut decompressed = match decompress_result { Ok ( decompressed ) => decompressed , Err ( e ) => return Ok ( CacheStatus :: Malformed ( e . to_string ( ) ) ) , } ; // Seek back to the start and parse this object so we can deal with it. // Since objects in Sentry (and potentially also other sources) might be // multi-arch files (e.g. FatMach), we parse as Archive and try to // extract the wanted file. decompressed . seek ( SeekFrom :: Start ( 0 ) ) ? ; let view = ByteView :: map_file ( decompressed ) ? ; let archive = match Archive :: parse ( & view ) { Ok ( archive ) => archive , Err ( e ) => return Ok ( CacheStatus :: Malformed ( e . to_string ( ) ) ) , } ; let mut persist_file = fs :: File :: create ( & path ) ? ; if archive . is_multi ( ) { let object_opt = archive . objects ( ) . filter_map ( Result :: ok ) . find ( | object | object_id . match_object ( object ) ) ; let object = match object_opt { Some ( object ) => object , None => { if let Some ( Err ( err ) ) = archive . objects ( ) . find ( | r | r . is_err ( ) ) { return Ok ( CacheStatus :: Malformed ( err . to_string ( ) ) ) ; } else { return Ok ( CacheStatus :: Negative ) ; } } } ; io :: copy ( & mut object . data ( ) , & mut persist_file ) ? ; } else { // Attempt to parse the object to capture errors. The result can be // discarded as the object's data is the entire ByteView. if let Err ( err ) = archive . object_by_index ( 0 ) { return Ok ( CacheStatus :: Malformed ( err . to_string ( ) ) ) ; } io :: copy ( & mut view . as_ref ( ) , & mut persist_file ) ? ; } Ok ( CacheStatus :: Positive ) } ; let future = async move { future . await . map_err ( | e | { sentry :: capture_error ( & e ) ; e } ) } . bind_hub ( Hub :: current ( ) ) ; let type_name = self . 0 . file_source . source_type_name ( ) . into ( ) ; let future = tokio :: time :: timeout ( Duration :: from_secs ( 600 ) , future ) ; let future = measure ( " " , m :: timed_result , Some ( ( " " , type_name ) ) , future , ) ; Box :: pin ( async move { future . await . map_err ( | _ | ObjectError :: Timeout ) ? } ) }
Downloads the object file, processes it and returns whether the file is in the cache.
Downloads the object file processes it and returns whether the file is in the cache .
&self
path
&Path
&self
path
&Path