Transaction pool: Remove futures-diagnose and thread pool (#9074)

* Transaction pool: Remove futures-diagnose and thread pool

This pr removes `futures-diagnose` as this isn't used anymore. Besides
that the pr also removes the thread pool that was used to validate the
transactions in the background. Instead of this thread pool we now spawn
two separate long running tasks that we use to validate the
transactions. All tasks of the transaction pool are now also spawned as
essential tasks. This means, if any of these tasks is stopping, the node
will stop as well.

* Update client/transaction-pool/src/api.rs
This commit is contained in:
Bastian Köcher
2021-06-11 18:24:30 +01:00
committed by GitHub
parent ed448ef28b
commit 68833498c6
8 changed files with 77 additions and 54 deletions
+48 -21
View File
@@ -21,7 +21,8 @@
use std::{marker::PhantomData, pin::Pin, sync::Arc};
use codec::{Decode, Encode};
use futures::{
channel::oneshot, executor::{ThreadPool, ThreadPoolBuilder}, future::{Future, FutureExt, ready, Ready},
channel::{oneshot, mpsc}, future::{Future, FutureExt, ready, Ready}, lock::Mutex, SinkExt,
StreamExt,
};
use sc_client_api::{
@@ -34,15 +35,36 @@ use sp_runtime::{
use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
use sp_api::{ProvideRuntimeApi, ApiExt};
use prometheus_endpoint::Registry as PrometheusRegistry;
use sp_core::traits::SpawnEssentialNamed;
use crate::{metrics::{ApiMetrics, ApiMetricsExt}, error::{self, Error}};
/// The transaction pool logic for full client.
pub struct FullChainApi<Client, Block> {
client: Arc<Client>,
pool: ThreadPool,
_marker: PhantomData<Block>,
metrics: Option<Arc<ApiMetrics>>,
validation_pool: Arc<Mutex<mpsc::Sender<Pin<Box<dyn Future<Output = ()> + Send>>>>>,
}
/// Spawn a validation task that will be used by the transaction pool to validate transactions.
fn spawn_validation_pool_task(
name: &'static str,
receiver: Arc<Mutex<mpsc::Receiver<Pin<Box<dyn Future<Output = ()> + Send>>>>>,
spawner: &impl SpawnEssentialNamed,
) {
spawner.spawn_essential_blocking(
name,
async move {
loop {
let task = receiver.lock().await.next().await;
match task {
None => return,
Some(task) => task.await,
}
}
}.boxed(),
);
}
impl<Client, Block> FullChainApi<Client, Block> {
@@ -50,6 +72,7 @@ impl<Client, Block> FullChainApi<Client, Block> {
pub fn new(
client: Arc<Client>,
prometheus: Option<&PrometheusRegistry>,
spawner: &impl SpawnEssentialNamed,
) -> Self {
let metrics = prometheus.map(ApiMetrics::register).and_then(|r| {
match r {
@@ -65,13 +88,15 @@ impl<Client, Block> FullChainApi<Client, Block> {
}
});
let (sender, receiver) = mpsc::channel(0);
let receiver = Arc::new(Mutex::new(receiver));
spawn_validation_pool_task("transaction-pool-task-0", receiver.clone(), spawner);
spawn_validation_pool_task("transaction-pool-task-1", receiver, spawner);
FullChainApi {
client,
pool: ThreadPoolBuilder::new()
.pool_size(2)
.name_prefix("txpool-verifier")
.create()
.expect("Failed to spawn verifier threads, that are critical for node operation."),
validation_pool: Arc::new(Mutex::new(sender)),
_marker: Default::default(),
metrics,
}
@@ -105,27 +130,29 @@ where
let (tx, rx) = oneshot::channel();
let client = self.client.clone();
let at = at.clone();
let validation_pool = self.validation_pool.clone();
let metrics = self.metrics.clone();
metrics.report(|m| m.validations_scheduled.inc());
self.pool.spawn_ok(futures_diagnose::diagnose(
"validate-transaction",
async move {
let res = validate_transaction_blocking(&*client, &at, source, uxt);
if let Err(e) = tx.send(res) {
log::warn!("Unable to send a validate transaction result: {:?}", e);
}
metrics.report(|m| m.validations_finished.inc());
},
));
async move {
metrics.report(|m| m.validations_scheduled.inc());
validation_pool.lock()
.await
.send(
async move {
let res = validate_transaction_blocking(&*client, &at, source, uxt);
let _ = tx.send(res);
metrics.report(|m| m.validations_finished.inc());
}.boxed()
)
.await
.map_err(|e| Error::RuntimeApi(format!("Validation pool down: {:?}", e)))?;
Box::pin(async move {
match rx.await {
Ok(r) => r,
Err(_) => Err(Error::RuntimeApi("Validation was canceled".into())),
}
})
}.boxed()
}
fn block_id_to_number(