mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 08:51:09 +00:00
Move spawning tasks from thread pools to Service's TaskManager for block importing (#5647)
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Service, NetworkStatus, NetworkState, error::Error, DEFAULT_PROTOCOL_ID, MallocSizeOfWasm};
|
||||
use crate::{start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager};
|
||||
use crate::{start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager, SpawnTaskHandle};
|
||||
use crate::status_sinks;
|
||||
use crate::config::{Configuration, KeystoreConfig, PrometheusConfig, OffchainWorkerConfig};
|
||||
use crate::metrics::MetricsService;
|
||||
@@ -97,7 +97,7 @@ pub struct ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp,
|
||||
remote_backend: Option<Arc<dyn RemoteBlockchain<TBl>>>,
|
||||
marker: PhantomData<(TBl, TRtApi)>,
|
||||
background_tasks: Vec<(&'static str, BackgroundTask)>,
|
||||
block_announce_validator_builder: Option<Box<dyn FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send>>>,
|
||||
block_announce_validator_builder: Option<Box<dyn FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + Send>>,
|
||||
}
|
||||
|
||||
/// Full client type.
|
||||
@@ -487,7 +487,7 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
|
||||
/// Defines which import queue to use.
|
||||
pub fn with_import_queue<UImpQu>(
|
||||
self,
|
||||
builder: impl FnOnce(&Configuration, Arc<TCl>, Option<TSc>, Arc<TExPool>)
|
||||
builder: impl FnOnce(&Configuration, Arc<TCl>, Option<TSc>, Arc<TExPool>, &SpawnTaskHandle)
|
||||
-> Result<UImpQu, Error>
|
||||
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, UImpQu, TFprb, TFpp,
|
||||
TExPool, TRpc, Backend>, Error>
|
||||
@@ -496,7 +496,8 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
|
||||
&self.config,
|
||||
self.client.clone(),
|
||||
self.select_chain.clone(),
|
||||
self.transaction_pool.clone()
|
||||
self.transaction_pool.clone(),
|
||||
&self.task_manager.spawn_handle(),
|
||||
)?;
|
||||
|
||||
Ok(ServiceBuilder {
|
||||
@@ -588,6 +589,7 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
|
||||
Option<TFchr>,
|
||||
Option<TSc>,
|
||||
Arc<TExPool>,
|
||||
&SpawnTaskHandle,
|
||||
) -> Result<(UImpQu, Option<UFprb>), Error>
|
||||
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, UImpQu, UFprb, TFpp,
|
||||
TExPool, TRpc, Backend>, Error>
|
||||
@@ -598,7 +600,8 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
|
||||
self.backend.clone(),
|
||||
self.fetcher.clone(),
|
||||
self.select_chain.clone(),
|
||||
self.transaction_pool.clone()
|
||||
self.transaction_pool.clone(),
|
||||
&self.task_manager.spawn_handle(),
|
||||
)?;
|
||||
|
||||
Ok(ServiceBuilder {
|
||||
@@ -631,12 +634,13 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
|
||||
Option<TFchr>,
|
||||
Option<TSc>,
|
||||
Arc<TExPool>,
|
||||
&SpawnTaskHandle,
|
||||
) -> Result<(UImpQu, UFprb), Error>
|
||||
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, UImpQu, UFprb, TFpp,
|
||||
TExPool, TRpc, Backend>, Error>
|
||||
where TSc: Clone, TFchr: Clone {
|
||||
self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx|
|
||||
builder(cfg, cl, b, f, sc, tx)
|
||||
self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx, tb|
|
||||
builder(cfg, cl, b, f, sc, tx, tb)
|
||||
.map(|(q, f)| (q, Some(f)))
|
||||
)
|
||||
}
|
||||
@@ -718,7 +722,7 @@ impl<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend>
|
||||
pub fn with_block_announce_validator(
|
||||
self,
|
||||
block_announce_validator_builder:
|
||||
impl FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + 'static,
|
||||
impl FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + Send + 'static,
|
||||
) -> Result<ServiceBuilder<TBl, TRtApi, TCl, TFchr, TSc, TImpQu, TFprb, TFpp,
|
||||
TExPool, TRpc, Backend>, Error>
|
||||
where TSc: Clone, TFchr: Clone {
|
||||
|
||||
@@ -56,12 +56,13 @@ impl<
|
||||
TExecDisp: 'static + NativeExecutionDispatch,
|
||||
TImpQu: 'static + ImportQueue<TBl>,
|
||||
TRtApi: 'static + Send + Sync,
|
||||
Self: Send + 'static,
|
||||
{
|
||||
type Block = TBl;
|
||||
type NativeDispatch = TExecDisp;
|
||||
|
||||
fn import_blocks(
|
||||
self,
|
||||
mut self,
|
||||
input: impl Read + Seek + Send + 'static,
|
||||
force: bool,
|
||||
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>> {
|
||||
@@ -98,9 +99,6 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
let client = self.client;
|
||||
let mut queue = self.import_queue;
|
||||
|
||||
let mut io_reader_input = IoReader(input);
|
||||
let mut count = None::<u64>;
|
||||
let mut read_block_count = 0;
|
||||
@@ -114,6 +112,9 @@ impl<
|
||||
// This makes it possible either to interleave other operations in-between the block imports,
|
||||
// or to stop the operation completely.
|
||||
let import = future::poll_fn(move |cx| {
|
||||
let client = &self.client;
|
||||
let queue = &mut self.import_queue;
|
||||
|
||||
// Start by reading the number of blocks if not done so already.
|
||||
let count = match count {
|
||||
Some(c) => c,
|
||||
@@ -203,13 +204,12 @@ impl<
|
||||
to: Option<NumberFor<TBl>>,
|
||||
binary: bool
|
||||
) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
|
||||
let client = self.client;
|
||||
let mut block = from;
|
||||
|
||||
let last = match to {
|
||||
Some(v) if v.is_zero() => One::one(),
|
||||
Some(v) => v,
|
||||
None => client.chain_info().best_number,
|
||||
None => self.client.chain_info().best_number,
|
||||
};
|
||||
|
||||
let mut wrote_header = false;
|
||||
@@ -222,6 +222,8 @@ impl<
|
||||
// This makes it possible either to interleave other operations in-between the block exports,
|
||||
// or to stop the operation completely.
|
||||
let export = future::poll_fn(move |cx| {
|
||||
let client = &self.client;
|
||||
|
||||
if last < block {
|
||||
return std::task::Poll::Ready(Err("Invalid block range specified".into()));
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ pub struct Configuration {
|
||||
/// Node role.
|
||||
pub role: Role,
|
||||
/// How to spawn background tasks. Mandatory, otherwise creating a `Service` will error.
|
||||
pub task_executor: Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>,
|
||||
pub task_executor: Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>, TaskType) + Send + Sync>,
|
||||
/// Extrinsic pool configuration.
|
||||
pub transaction_pool: TransactionPoolOptions,
|
||||
/// Network configuration.
|
||||
@@ -102,6 +102,15 @@ pub struct Configuration {
|
||||
pub announce_block: bool,
|
||||
}
|
||||
|
||||
/// Type for tasks spawned by the executor.
|
||||
#[derive(PartialEq)]
|
||||
pub enum TaskType {
|
||||
/// Regular non-blocking futures. Polling the task is expected to be a lightweight operation.
|
||||
Async,
|
||||
/// The task might perform a lot of expensive CPU operations and/or call `thread::sleep`.
|
||||
Blocking,
|
||||
}
|
||||
|
||||
/// Configuration of the client keystore.
|
||||
#[derive(Clone)]
|
||||
pub enum KeystoreConfig {
|
||||
|
||||
@@ -64,7 +64,7 @@ pub use self::builder::{
|
||||
ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend,
|
||||
TFullCallExecutor, TLightCallExecutor,
|
||||
};
|
||||
pub use config::{Configuration, Role, PruningMode, DatabaseConfig};
|
||||
pub use config::{Configuration, Role, PruningMode, DatabaseConfig, TaskType};
|
||||
pub use sc_chain_spec::{
|
||||
ChainSpec, GenericChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension,
|
||||
NoExtension, ChainType,
|
||||
|
||||
@@ -31,11 +31,12 @@ use prometheus_endpoint::{
|
||||
CounterVec, HistogramOpts, HistogramVec, Opts, Registry, U64
|
||||
};
|
||||
use sc_client_api::CloneableSpawn;
|
||||
use crate::config::TaskType;
|
||||
|
||||
mod prometheus_future;
|
||||
|
||||
/// Type alias for service task executor (usually runtime).
|
||||
pub type ServiceTaskExecutor = Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>;
|
||||
pub type ServiceTaskExecutor = Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>, TaskType) + Send + Sync>;
|
||||
|
||||
/// An handle for spawning tasks in the service.
|
||||
#[derive(Clone)]
|
||||
@@ -55,6 +56,16 @@ impl SpawnTaskHandle {
|
||||
/// In other words, it would be a bad idea for someone to do for example
|
||||
/// `spawn(format!("{:?}", some_public_key))`.
|
||||
pub fn spawn(&self, name: &'static str, task: impl Future<Output = ()> + Send + 'static) {
|
||||
self.spawn_inner(name, task, TaskType::Async)
|
||||
}
|
||||
|
||||
/// Spawns the blocking task with the given name. See also `spawn`.
|
||||
pub fn spawn_blocking(&self, name: &'static str, task: impl Future<Output = ()> + Send + 'static) {
|
||||
self.spawn_inner(name, task, TaskType::Blocking)
|
||||
}
|
||||
|
||||
/// Helper function that implements the spawning logic. See `spawn` and `spawn_blocking`.
|
||||
fn spawn_inner(&self, name: &'static str, task: impl Future<Output = ()> + Send + 'static, task_type: TaskType) {
|
||||
let on_exit = self.on_exit.clone();
|
||||
let metrics = self.metrics.clone();
|
||||
|
||||
@@ -80,7 +91,7 @@ impl SpawnTaskHandle {
|
||||
}
|
||||
};
|
||||
|
||||
(self.executor)(Box::pin(future));
|
||||
(self.executor)(Box::pin(future), task_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user