mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-07 16:38:01 +00:00
dc0bf210fb
* ChainSpec trait * Apply suggestions from code review Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Added docs * Fixed build * Fixed build Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
142 lines
3.7 KiB
Rust
142 lines
3.7 KiB
Rust
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
|
// This file is part of Substrate.
|
|
|
|
// Substrate is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// Substrate is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
use std::sync::Arc;
|
|
|
|
use futures::{Future, future, future::FutureExt};
|
|
use futures::select;
|
|
use futures::pin_mut;
|
|
use sc_service::{AbstractService, Configuration};
|
|
use crate::error;
|
|
|
|
#[cfg(target_family = "unix")]
|
|
async fn main<F, E>(func: F) -> Result<(), Box<dyn std::error::Error>>
|
|
where
|
|
F: Future<Output = Result<(), E>> + future::FusedFuture,
|
|
E: 'static + std::error::Error,
|
|
{
|
|
use tokio::signal::unix::{signal, SignalKind};
|
|
|
|
let mut stream_int = signal(SignalKind::interrupt())?;
|
|
let mut stream_term = signal(SignalKind::terminate())?;
|
|
|
|
let t1 = stream_int.recv().fuse();
|
|
let t2 = stream_term.recv().fuse();
|
|
let t3 = func;
|
|
|
|
pin_mut!(t1, t2, t3);
|
|
|
|
select! {
|
|
_ = t1 => {},
|
|
_ = t2 => {},
|
|
res = t3 => res?,
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(not(unix))]
|
|
async fn main<F, E>(func: F) -> Result<(), Box<dyn std::error::Error>>
|
|
where
|
|
F: Future<Output = Result<(), E>> + future::FusedFuture,
|
|
E: 'static + std::error::Error,
|
|
{
|
|
use tokio::signal::ctrl_c;
|
|
|
|
let t1 = ctrl_c().fuse();
|
|
let t2 = func;
|
|
|
|
pin_mut!(t1, t2);
|
|
|
|
select! {
|
|
_ = t1 => {},
|
|
res = t2 => res?,
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn build_runtime() -> Result<tokio::runtime::Runtime, std::io::Error> {
|
|
tokio::runtime::Builder::new()
|
|
.thread_name("main-tokio-")
|
|
.threaded_scheduler()
|
|
.enable_all()
|
|
.build()
|
|
}
|
|
|
|
/// A helper function that runs a future with tokio and stops if the process receives the signal
|
|
/// SIGTERM or SIGINT
|
|
pub fn run_until_exit<FUT, ERR, F>(
|
|
mut config: Configuration,
|
|
future_builder: F,
|
|
) -> error::Result<()>
|
|
where
|
|
F: FnOnce(Configuration) -> error::Result<FUT>,
|
|
FUT: Future<Output = Result<(), ERR>> + future::Future,
|
|
ERR: 'static + std::error::Error,
|
|
{
|
|
let mut runtime = build_runtime()?;
|
|
|
|
config.task_executor = {
|
|
let runtime_handle = runtime.handle().clone();
|
|
Some(Arc::new(move |fut| { runtime_handle.spawn(fut); }))
|
|
};
|
|
|
|
let f = future_builder(config)?;
|
|
let f = f.fuse();
|
|
pin_mut!(f);
|
|
|
|
runtime.block_on(main(f)).map_err(|e| e.to_string())?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// A helper function that runs an `AbstractService` with tokio and stops if the process receives
|
|
/// the signal SIGTERM or SIGINT
|
|
pub fn run_service_until_exit<T, F>(
|
|
mut config: Configuration,
|
|
service_builder: F,
|
|
) -> error::Result<()>
|
|
where
|
|
F: FnOnce(Configuration) -> Result<T, sc_service::error::Error>,
|
|
T: AbstractService + Unpin,
|
|
{
|
|
let mut runtime = build_runtime()?;
|
|
|
|
config.task_executor = {
|
|
let runtime_handle = runtime.handle().clone();
|
|
Some(Arc::new(move |fut| { runtime_handle.spawn(fut); }))
|
|
};
|
|
|
|
let service = service_builder(config)?;
|
|
|
|
let informant_future = sc_informant::build(&service, sc_informant::OutputFormat::Coloured);
|
|
let _informant_handle = runtime.spawn(informant_future);
|
|
|
|
// we eagerly drop the service so that the internal exit future is fired,
|
|
// but we need to keep holding a reference to the global telemetry guard
|
|
// and drop the runtime first.
|
|
let _telemetry = service.telemetry();
|
|
|
|
let f = service.fuse();
|
|
pin_mut!(f);
|
|
|
|
runtime.block_on(main(f)).map_err(|e| e.to_string())?;
|
|
drop(runtime);
|
|
|
|
Ok(())
|
|
}
|