// Copyright 2017-2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see .
//! Utility module for subsystems
//!
//! Many subsystems have common interests such as canceling a bunch of spawned jobs,
//! or determining what their validator ID is. These common interests are factored into
//! this module.
use crate::messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest, SchedulerRoster};
use futures::{
channel::{mpsc, oneshot},
future::AbortHandle,
prelude::*,
task::SpawnError,
};
use polkadot_primitives::{
parachain::{
GlobalValidationSchedule, HeadData, Id as ParaId, LocalValidationData, SigningContext,
ValidatorId,
},
Hash,
};
use std::{
collections::HashMap,
ops::{Deref, DerefMut},
};
/// JobCanceler aborts all contained abort handles on drop
#[derive(Debug, Default)]
pub struct JobCanceler(HashMap);
impl Drop for JobCanceler {
fn drop(&mut self) {
for abort_handle in self.0.values() {
abort_handle.abort();
}
}
}
// JobCanceler is a smart pointer wrapping the contained hashmap;
// it only cares about the wrapped data insofar as it's necessary
// to implement proper Drop behavior. Therefore, it's appropriate
// to impl Deref and DerefMut.
impl Deref for JobCanceler {
type Target = HashMap;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for JobCanceler {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug, derive_more::From)]
pub enum Error {
#[from]
Oneshot(oneshot::Canceled),
#[from]
Mpsc(mpsc::SendError),
#[from]
Spawn(SpawnError),
}
/// Request some data from the `RuntimeApi`.
pub async fn request_from_runtime(
parent: Hash,
sender: &mut mpsc::Sender,
request_builder: RequestBuilder,
) -> Result, Error>
where
RequestBuilder: FnOnce(oneshot::Sender) -> RuntimeApiRequest,
{
let (tx, rx) = oneshot::channel();
sender
.send(AllMessages::RuntimeApi(RuntimeApiMessage::Request(
parent,
request_builder(tx),
)))
.await?;
Ok(rx)
}
/// Request a `GlobalValidationSchedule` from `RuntimeApi`.
pub async fn request_global_validation_schedule(
parent: Hash,
s: &mut mpsc::Sender,
) -> Result, Error> {
request_from_runtime(parent, s, |tx| {
RuntimeApiRequest::GlobalValidationSchedule(tx)
})
.await
}
/// Request a `LocalValidationData` from `RuntimeApi`.
pub async fn request_local_validation_data(
parent: Hash,
para_id: ParaId,
s: &mut mpsc::Sender,
) -> Result>, Error> {
request_from_runtime(parent, s, |tx| {
RuntimeApiRequest::LocalValidationData(para_id, tx)
})
.await
}
/// Request a validator set from the `RuntimeApi`.
pub async fn request_validators(
parent: Hash,
s: &mut mpsc::Sender,
) -> Result>, Error> {
request_from_runtime(parent, s, |tx| RuntimeApiRequest::Validators(tx)).await
}
/// Request the scheduler roster from `RuntimeApi`.
pub async fn request_validator_groups(
parent: Hash,
s: &mut mpsc::Sender,
) -> Result, Error> {
request_from_runtime(parent, s, |tx| RuntimeApiRequest::ValidatorGroups(tx)).await
}
/// Request a `SigningContext` from the `RuntimeApi`.
pub async fn request_signing_context(
parent: Hash,
s: &mut mpsc::Sender,
) -> Result, Error> {
request_from_runtime(parent, s, |tx| RuntimeApiRequest::SigningContext(tx)).await
}
/// Request `HeadData` for some `ParaId` from `RuntimeApi`.
pub async fn request_head_data(
parent: Hash,
s: &mut mpsc::Sender,
id: ParaId,
) -> Result, Error> {
request_from_runtime(parent, s, |tx| RuntimeApiRequest::HeadData(id, tx)).await
}