From ec2b51539d2d2af267bcc1779694e6ec104e4a81 Mon Sep 17 00:00:00 2001 From: ChainsightAnalytics <97004363+ChainsightAnalytics@users.noreply.github.com> Date: Fri, 28 Jan 2022 02:17:54 -0500 Subject: [PATCH] fix(solc): use already instantiated tokio runtime if exists (#811) Co-authored-by: Georgios Konstantopoulos --- ethers-solc/src/compile.rs | 62 ++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/ethers-solc/src/compile.rs b/ethers-solc/src/compile.rs index 0acbfc9d..006e9c27 100644 --- a/ethers-solc/src/compile.rs +++ b/ethers-solc/src/compile.rs @@ -5,6 +5,7 @@ use crate::{ }; use semver::{Version, VersionReq}; use serde::{de::DeserializeOwned, Serialize}; + use std::{ fmt, fmt::Formatter, @@ -47,6 +48,32 @@ use std::sync::Mutex; #[allow(unused)] static LOCK: Lazy> = Lazy::new(|| Mutex::new(())); +#[cfg(all(feature = "svm", feature = "async"))] +#[allow(clippy::large_enum_variant)] +pub enum RuntimeOrHandle { + Runtime(tokio::runtime::Runtime), + Handle(tokio::runtime::Handle), +} + +#[cfg(all(feature = "svm", feature = "async"))] +impl Default for RuntimeOrHandle { + fn default() -> Self { + Self::new() + } +} + +#[cfg(all(feature = "svm", feature = "async"))] +impl RuntimeOrHandle { + pub fn new() -> RuntimeOrHandle { + match tokio::runtime::Handle::try_current() { + Ok(handle) => RuntimeOrHandle::Handle(handle), + Err(_) => RuntimeOrHandle::Runtime( + tokio::runtime::Runtime::new().expect("Failed to start runtime"), + ), + } + } +} + /// take the lock in tests, we use this to enforce that /// a test does not run while a compiler version is being installed /// @@ -65,17 +92,34 @@ pub(crate) fn take_solc_installer_lock() -> std::sync::MutexGuard<'static, ()> { /// The boolean value marks whether there was an error. pub static RELEASES: Lazy<(svm::Releases, Vec, bool)> = Lazy::new(|| { // Try to download the releases, if it fails default to empty - match tokio::runtime::Runtime::new() - .expect("could not create tokio rt to get remote releases") + let releases_result = match RuntimeOrHandle::new() { + RuntimeOrHandle::Runtime(runtime) => // we do not degrade startup performance if the consumer has a weak network? // use a 3 sec timeout for the request which should still be fine for slower connections - .block_on(async { - tokio::time::timeout( - std::time::Duration::from_millis(3000), - svm::all_releases(svm::platform()), - ) - .await - }) { + { + runtime.block_on(async { + tokio::time::timeout( + std::time::Duration::from_millis(3000), + svm::all_releases(svm::platform()), + ) + .await + }) + } + RuntimeOrHandle::Handle(handle) => + // we do not degrade startup performance if the consumer has a weak network? + // use a 3 sec timeout for the request which should still be fine for slower connections + { + handle.block_on(async { + tokio::time::timeout( + std::time::Duration::from_millis(3000), + svm::all_releases(svm::platform()), + ) + .await + }) + } + }; + + match releases_result { Ok(Ok(releases)) => { let mut sorted_releases = releases.releases.keys().cloned().collect::>(); sorted_releases.sort();