minor improvement
This commit is contained in:
parent
7510db4989
commit
1669c15a32
104
src/main.rs
104
src/main.rs
@ -373,66 +373,80 @@ impl Web3ProxyApp {
|
|||||||
.ok_or_else(|| anyhow::anyhow!("no params"))?
|
.ok_or_else(|| anyhow::anyhow!("no params"))?
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
// TODO: lets just use a usize index or something
|
if rpc_servers.len() == 1 {
|
||||||
let method = Arc::new(method);
|
let rpc = rpc_servers.first().unwrap();
|
||||||
|
|
||||||
let mut unordered_futures = FuturesUnordered::new();
|
let provider = connections.get(rpc).unwrap().clone_provider();
|
||||||
|
|
||||||
for rpc in rpc_servers {
|
let response = provider.request(&method, params).await;
|
||||||
let connections = connections.clone();
|
|
||||||
let method = method.clone();
|
|
||||||
let params = params.clone();
|
|
||||||
let tx = tx.clone();
|
|
||||||
|
|
||||||
let handle = tokio::spawn(async move {
|
connections.get(rpc).unwrap().dec_active_requests();
|
||||||
// get the client for this rpc server
|
|
||||||
let provider = connections.get(&rpc).unwrap().clone_provider();
|
|
||||||
|
|
||||||
let response = provider.request(&method, params).await;
|
tx.send(response.map_err(Into::into))?;
|
||||||
|
|
||||||
connections.get(&rpc).unwrap().dec_active_requests();
|
Ok(())
|
||||||
|
} else {
|
||||||
|
// TODO: lets just use a usize index or something
|
||||||
|
let method = Arc::new(method);
|
||||||
|
|
||||||
let response = response?;
|
let mut unordered_futures = FuturesUnordered::new();
|
||||||
|
|
||||||
// TODO: if "no block with that header" or some other jsonrpc errors, skip this response
|
for rpc in rpc_servers {
|
||||||
|
let connections = connections.clone();
|
||||||
|
let method = method.clone();
|
||||||
|
let params = params.clone();
|
||||||
|
let tx = tx.clone();
|
||||||
|
|
||||||
// send the first good response to a one shot channel. that way we respond quickly
|
let handle = tokio::spawn(async move {
|
||||||
// drop the result because errors are expected after the first send
|
// get the client for this rpc server
|
||||||
let _ = tx.send(Ok(response));
|
let provider = connections.get(&rpc).unwrap().clone_provider();
|
||||||
|
|
||||||
Ok::<(), anyhow::Error>(())
|
let response = provider.request(&method, params).await;
|
||||||
});
|
|
||||||
|
|
||||||
unordered_futures.push(handle);
|
connections.get(&rpc).unwrap().dec_active_requests();
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: use iterators instead of pushing into a vec
|
let response = response?;
|
||||||
let mut errs = vec![];
|
|
||||||
if let Some(x) = unordered_futures.next().await {
|
// TODO: if "no block with that header" or some other jsonrpc errors, skip this response
|
||||||
match x.unwrap() {
|
|
||||||
Ok(_) => {}
|
// send the first good response to a one shot channel. that way we respond quickly
|
||||||
Err(e) => {
|
// drop the result because errors are expected after the first send
|
||||||
// TODO: better errors
|
let _ = tx.send(Ok(response));
|
||||||
warn!("Got an error sending request: {}", e);
|
|
||||||
errs.push(e);
|
Ok::<(), anyhow::Error>(())
|
||||||
|
});
|
||||||
|
|
||||||
|
unordered_futures.push(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: use iterators instead of pushing into a vec
|
||||||
|
let mut errs = vec![];
|
||||||
|
if let Some(x) = unordered_futures.next().await {
|
||||||
|
match x.unwrap() {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
// TODO: better errors
|
||||||
|
warn!("Got an error sending request: {}", e);
|
||||||
|
errs.push(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// get the first error (if any)
|
// get the first error (if any)
|
||||||
let e: anyhow::Result<serde_json::Value> = if !errs.is_empty() {
|
let e: anyhow::Result<serde_json::Value> = if !errs.is_empty() {
|
||||||
Err(errs.pop().unwrap())
|
Err(errs.pop().unwrap())
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow::anyhow!("no successful responses"))
|
Err(anyhow::anyhow!("no successful responses"))
|
||||||
};
|
};
|
||||||
|
|
||||||
// send the error to the channel
|
// send the error to the channel
|
||||||
if tx.send(e).is_ok() {
|
if tx.send(e).is_ok() {
|
||||||
// if we were able to send an error, then we never sent a success
|
// if we were able to send an error, then we never sent a success
|
||||||
return Err(anyhow::anyhow!("no successful responses"));
|
return Err(anyhow::anyhow!("no successful responses"));
|
||||||
} else {
|
} else {
|
||||||
// if sending the error failed. the other side must be closed (which means we sent a success earlier)
|
// if sending the error failed. the other side must be closed (which means we sent a success earlier)
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user