|
|
|
@ -1,6 +1,10 @@ |
|
|
|
|
use async_trait::async_trait; |
|
|
|
|
use color_eyre::{eyre::WrapErr, Result}; |
|
|
|
|
use color_eyre::{ |
|
|
|
|
eyre::{eyre, WrapErr}, |
|
|
|
|
Result, |
|
|
|
|
}; |
|
|
|
|
use futures_util::future::{join_all, select_all}; |
|
|
|
|
use log::error; |
|
|
|
|
use std::sync::Arc; |
|
|
|
|
|
|
|
|
|
use crate::settings::Settings; |
|
|
|
@ -13,25 +17,36 @@ pub trait OpticsAgent: Send + Sync + std::fmt::Debug { |
|
|
|
|
/// Run the agent with the given home and replica
|
|
|
|
|
async fn run(home: Arc<Box<dyn Home>>, replica: Box<dyn Replica>) -> Result<()>; |
|
|
|
|
|
|
|
|
|
/// Run the Agent, and tag errors with the slip44 ID of the replica
|
|
|
|
|
async fn run_report_error(home: Arc<Box<dyn Home>>, replica: Box<dyn Replica>) -> Result<()> { |
|
|
|
|
let slip44 = replica.destination_slip44(); |
|
|
|
|
Self::run(home, replica) |
|
|
|
|
.await |
|
|
|
|
.wrap_err_with(|| format!("Replica with ID {} failed", slip44)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[allow(unreachable_code)] |
|
|
|
|
/// Run several agents
|
|
|
|
|
async fn run_many(home: Box<dyn Home>, replicas: Vec<Box<dyn Replica>>) -> Result<()> { |
|
|
|
|
let home = Arc::new(home); |
|
|
|
|
|
|
|
|
|
let mut replica_tasks: Vec<_> = replicas |
|
|
|
|
let mut futs: Vec<_> = replicas |
|
|
|
|
.into_iter() |
|
|
|
|
.map(|replica| Self::run(home.clone(), replica)) |
|
|
|
|
.map(|replica| Self::run_report_error(home.clone(), replica)) |
|
|
|
|
.collect(); |
|
|
|
|
|
|
|
|
|
loop { |
|
|
|
|
let (_res, _, rem) = select_all(replica_tasks).await; |
|
|
|
|
// TODO: report failure
|
|
|
|
|
replica_tasks = rem; |
|
|
|
|
if replica_tasks.is_empty() { |
|
|
|
|
break; |
|
|
|
|
// This gets the first future to resolve.
|
|
|
|
|
let (res, _, remaining) = select_all(futs).await; |
|
|
|
|
if res.is_err() { |
|
|
|
|
error!("Replica shut down: {:#}", res.unwrap_err()); |
|
|
|
|
} |
|
|
|
|
futs = remaining; |
|
|
|
|
if futs.is_empty() { |
|
|
|
|
return Err(eyre!("All replicas have shut down")); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
unreachable!() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Run several agents based on the settings
|
|
|
|
|