Browse Source

net/ seed_session: fix bug which caused seed to drop

previously we were looping through all start_seed tasks linearily and
applying a global timer for all tasks. if any tasks exceeded the timer,
all tasks after the timeout were dropped.

here we implement a unique timer for every unique task. if the task
exceeds a timer, that task is dropped, with no impact on any future
tasks.
lunar-mining 4 years ago
parent
commit
fcc6964692
1 changed files with 26 additions and 20 deletions
  1. 26 20
      src/net/session/seed_session.rs

+ 26 - 20
src/net/session/seed_session.rs

@@ -2,6 +2,7 @@ use async_std::{
     future::timeout,
     sync::{Arc, Weak},
 };
+use futures::future;
 use std::time::Duration;
 
 use async_executor::Executor;
@@ -49,29 +50,34 @@ impl SeedSession {
 
         let mut tasks = Vec::new();
 
+        // This loops through all the seeds and tries to start them.
+        // If the seed_query_timeout_seconds times out before they are finished,
+        // it will return an error.
         for (i, seed) in settings.seeds.iter().enumerate() {
-            tasks.push(executor.spawn(self.clone().start_seed(i, seed.clone(), executor.clone())));
-        }
-
-        // This line loops through all the tasks and waits for them to finish.
-        // But if the seed_query_timeout_seconds times out before they are finished,
-        // then it will simply quit and the tasks will get dropped.
-        let result =
-            timeout(Duration::from_secs(settings.seed_query_timeout_seconds.into()), async move {
-                for (i, task) in tasks.into_iter().enumerate() {
-                    // Ignore errors
-                    match task.await {
-                        Ok(()) => info!("Successfully queried seed #{}", i),
-                        Err(err) => warn!("Seed query #{} failed for reason: {}", i, err),
-                    }
+            let ex2 = executor.clone();
+            let self2 = self.clone();
+            let sett2 = settings.clone();
+            tasks.push(async move {
+                let task = self2.clone().start_seed(i, seed.clone(), ex2.clone());
+
+                let result =
+                    timeout(Duration::from_secs(sett2.seed_query_timeout_seconds.into()), task)
+                        .await;
+
+                match result {
+                    Ok(t) => match t {
+                        Ok(()) => {
+                            info!("Seed #{} connected successfully", i)
+                        }
+                        Err(err) => {
+                            warn!("Seed #{} failed for reason {}", i, err)
+                        }
+                    },
+                    Err(_err) => error!("Seed #{} timed out", i),
                 }
-            })
-            .await;
-
-        if result.is_err() {
-            error!("Querying seeds timed out");
-            return Err(Error::NetworkOperationFailed)
+            });
         }
+        future::join_all(tasks).await;
 
         // Seed process complete
         if self.p2p().hosts().is_empty().await {