remove AllSubsystems and AllSubsystemsGen types (#3874)

* introduce the OverseerConnector, use it

* introduce is_relay_chain to RelayChainSelection

* Update node/service/src/lib.rs

Co-authored-by: Andronik Ordian <write@reusable.software>

* avoid the deferred setting of `is_relay_chain` in `RelayChainSelection`

* positive assertion is not mandated, only the negative one, to avoid a stall

* cleanup: overseer residue

* spellcheck

* fixin

* groundwork to obsolete Overseer::new and AllSubsystemsGen proc-macro

* Now all malus & tests can be ported to the builder pattern.

Obsoletes `Overseer::new`, `AllSubsystemsGen` derive macro, `AllSubsystems`.

* spellcheck

* adjust tests, minor fixes

* remove derive macro AllSubsystemsGen

* add forgotten file dummy.rs

* remove residue

* good news everyone!

* spellcheck

* address review comments

* fixup imports

* make it conditional

* fixup docs

* reduce import

* chore: fmt

* chore: fmt

* chore: spellcheck / nlprules

* fixup malus variant-a

* fmt

* fix

* fixins

* pfmt

* fixins

* chore: fmt

* remove expanded overseer generation

* tracing version

* Update node/network/statement-distribution/src/lib.rs

Co-authored-by: Robert Habermeier <rphmeier@gmail.com>

* use future::ready instead

* silence warning

* chore: fmt

Co-authored-by: Andronik Ordian <write@reusable.software>
Co-authored-by: Robert Habermeier <rphmeier@gmail.com>
This commit is contained in:
Bernhard Schuster
2021-09-29 16:24:56 +02:00
committed by GitHub
parent f9de0040c9
commit c57a1e7934
42 changed files with 600 additions and 1389 deletions
+144 -2
View File
@@ -14,8 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use crate::{AllMessages, OverseerSignal};
use polkadot_node_subsystem_types::errors::SubsystemError;
use crate::{
prometheus::Registry, AllMessages, HeadSupportsParachains, MetricsTrait, Overseer,
OverseerBuilder, OverseerMetrics, OverseerSignal, OverseerSubsystemContext, SpawnNamed,
KNOWN_LEAVES_CACHE_SIZE,
};
use lru::LruCache;
use polkadot_node_subsystem_types::{errors::SubsystemError, messages::*};
use polkadot_overseer_gen::{FromOverseer, SpawnedSubsystem, Subsystem, SubsystemContext};
/// A dummy subsystem that implements [`Subsystem`] for all
@@ -52,3 +57,140 @@ where
SpawnedSubsystem { name: "dummy-subsystem", future }
}
}
/// Create an overseer with all subsystem being `Sub`.
///
/// Preferred way of initializing a dummy overseer for subsystem tests.
pub fn dummy_overseer_builder<'a, Spawner, SupportsParachains>(
spawner: Spawner,
supports_parachains: SupportsParachains,
registry: Option<&'a Registry>,
) -> Result<
OverseerBuilder<
Spawner,
SupportsParachains,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
>,
SubsystemError,
>
where
Spawner: SpawnNamed + Send + Sync + 'static,
SupportsParachains: HeadSupportsParachains,
{
one_for_all_overseer_builder(spawner, supports_parachains, DummySubsystem, registry)
}
/// Create an overseer with all subsystem being `Sub`.
pub fn one_for_all_overseer_builder<'a, Spawner, SupportsParachains, Sub>(
spawner: Spawner,
supports_parachains: SupportsParachains,
subsystem: Sub,
registry: Option<&'a Registry>,
) -> Result<
OverseerBuilder<
Spawner,
SupportsParachains,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
Sub,
>,
SubsystemError,
>
where
Spawner: SpawnNamed + Send + Sync + 'static,
SupportsParachains: HeadSupportsParachains,
Sub: Clone
+ Subsystem<OverseerSubsystemContext<AvailabilityDistributionMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<AvailabilityRecoveryMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<AvailabilityStoreMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<BitfieldDistributionMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<BitfieldSigningMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<CandidateBackingMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<CandidateValidationMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<ChainApiMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<CollationGenerationMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<CollatorProtocolMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<NetworkBridgeMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<ProvisionerMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<RuntimeApiMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<StatementDistributionMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<ApprovalDistributionMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<ApprovalVotingMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<GossipSupportMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<DisputeCoordinatorMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<DisputeParticipationMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<DisputeDistributionMessage>, SubsystemError>
+ Subsystem<OverseerSubsystemContext<ChainSelectionMessage>, SubsystemError>,
{
let metrics = <OverseerMetrics as MetricsTrait>::register(registry)?;
let builder = Overseer::builder()
.availability_distribution(subsystem.clone())
.availability_recovery(subsystem.clone())
.availability_store(subsystem.clone())
.bitfield_distribution(subsystem.clone())
.bitfield_signing(subsystem.clone())
.candidate_backing(subsystem.clone())
.candidate_validation(subsystem.clone())
.chain_api(subsystem.clone())
.collation_generation(subsystem.clone())
.collator_protocol(subsystem.clone())
.network_bridge(subsystem.clone())
.provisioner(subsystem.clone())
.runtime_api(subsystem.clone())
.statement_distribution(subsystem.clone())
.approval_distribution(subsystem.clone())
.approval_voting(subsystem.clone())
.gossip_support(subsystem.clone())
.dispute_coordinator(subsystem.clone())
.dispute_participation(subsystem.clone())
.dispute_distribution(subsystem.clone())
.chain_selection(subsystem)
.activation_external_listeners(Default::default())
.span_per_active_leaf(Default::default())
.active_leaves(Default::default())
.known_leaves(LruCache::new(KNOWN_LEAVES_CACHE_SIZE))
.leaves(Default::default())
.spawner(spawner)
.metrics(metrics)
.supports_parachains(supports_parachains);
Ok(builder)
}
+174 -318
View File
@@ -62,7 +62,6 @@
use std::{
collections::{hash_map, HashMap},
fmt::{self, Debug},
iter::FromIterator,
pin::Pin,
sync::Arc,
time::Duration,
@@ -90,17 +89,13 @@ pub use polkadot_node_subsystem_types::{
jaeger, ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, OverseerSignal,
};
/// Test helper supplements.
pub mod metrics;
pub use self::metrics::Metrics as OverseerMetrics;
/// A dummy subsystem, mostly useful for placeholders and tests.
pub mod dummy;
pub use self::dummy::DummySubsystem;
// TODO legacy, to be deleted, left for easier integration
// TODO https://github.com/paritytech/polkadot/issues/3427
mod subsystems;
pub use self::subsystems::AllSubsystems;
pub mod metrics;
pub use polkadot_node_metrics::{
metrics::{prometheus, Metrics as MetricsTrait},
Metronome,
@@ -292,7 +287,119 @@ pub async fn forward_events<P: BlockchainEvents<Block>>(client: Arc<P>, mut hand
}
}
/// The `Overseer` itself.
/// Create a new instance of the [`Overseer`] with a fixed set of [`Subsystem`]s.
///
/// This returns the overseer along with an [`OverseerHandle`] which can
/// be used to send messages from external parts of the codebase.
///
/// The [`OverseerHandle`] returned from this function is connected to
/// the returned [`Overseer`].
///
/// ```text
/// +------------------------------------+
/// | Overseer |
/// +------------------------------------+
/// / | | \
/// ................. subsystems...................................
/// . +-----------+ +-----------+ +----------+ +---------+ .
/// . | | | | | | | | .
/// . +-----------+ +-----------+ +----------+ +---------+ .
/// ...............................................................
/// |
/// probably `spawn`
/// a `job`
/// |
/// V
/// +-----------+
/// | |
/// +-----------+
///
/// ```
///
/// [`Subsystem`]: trait.Subsystem.html
///
/// # Example
///
/// The [`Subsystems`] may be any type as long as they implement an expected interface.
/// Here, we create a mock validation subsystem and a few dummy ones and start the `Overseer` with them.
/// For the sake of simplicity the termination of the example is done with a timeout.
/// ```
/// # use std::time::Duration;
/// # use futures::{executor, pin_mut, select, FutureExt};
/// # use futures_timer::Delay;
/// # use polkadot_primitives::v1::Hash;
/// # use polkadot_overseer::{
/// # self as overseer,
/// # OverseerSignal,
/// # SubsystemSender as _,
/// # AllMessages,
/// # HeadSupportsParachains,
/// # Overseer,
/// # SubsystemError,
/// # gen::{
/// # SubsystemContext,
/// # FromOverseer,
/// # SpawnedSubsystem,
/// # },
/// # };
/// # use polkadot_node_subsystem_types::messages::{
/// # CandidateValidationMessage, CandidateBackingMessage,
/// # NetworkBridgeMessage,
/// # };
///
/// struct ValidationSubsystem;
///
/// impl<Ctx> overseer::Subsystem<Ctx, SubsystemError> for ValidationSubsystem
/// where
/// Ctx: overseer::SubsystemContext<
/// Message=CandidateValidationMessage,
/// AllMessages=AllMessages,
/// Signal=OverseerSignal,
/// Error=SubsystemError,
/// >,
/// {
/// fn start(
/// self,
/// mut ctx: Ctx,
/// ) -> SpawnedSubsystem<SubsystemError> {
/// SpawnedSubsystem {
/// name: "validation-subsystem",
/// future: Box::pin(async move {
/// loop {
/// Delay::new(Duration::from_secs(1)).await;
/// }
/// }),
/// }
/// }
/// }
///
/// # fn main() { executor::block_on(async move {
///
/// struct AlwaysSupportsParachains;
/// impl HeadSupportsParachains for AlwaysSupportsParachains {
/// fn head_supports_parachains(&self, _head: &Hash) -> bool { true }
/// }
/// let spawner = sp_core::testing::TaskExecutor::new();
/// let (overseer, _handle) = dummy_overseer_builder(spawner, AlwaysSupportsParachains, None)
/// .unwrap()
/// .replace_candidate_validation(|_| ValidationSubsystem)
/// .build()
/// .unwrap();
///
/// let timer = Delay::new(Duration::from_millis(50)).fuse();
///
/// let overseer_fut = overseer.run().fuse();
/// pin_mut!(timer);
/// pin_mut!(overseer_fut);
///
/// select! {
/// _ = overseer_fut => (),
/// _ = timer => (),
/// }
/// #
/// # });
/// # }
/// ```
#[overlord(
gen=AllMessages,
event=Event,
@@ -385,7 +492,60 @@ pub struct Overseer<SupportsParachains> {
pub known_leaves: LruCache<Hash, ()>,
/// Various Prometheus metrics.
pub metrics: crate::metrics::Metrics,
pub metrics: OverseerMetrics,
}
/// Spawn the metrics metronome task.
pub fn spawn_metronome_metrics<S, SupportsParachains>(
overseer: &mut Overseer<S, SupportsParachains>,
metronome_metrics: OverseerMetrics,
) -> Result<(), SubsystemError>
where
S: SpawnNamed,
SupportsParachains: HeadSupportsParachains,
{
struct ExtractNameAndMeters;
impl<'a, T: 'a> MapSubsystem<&'a OverseenSubsystem<T>> for ExtractNameAndMeters {
type Output = Option<(&'static str, SubsystemMeters)>;
fn map_subsystem(&self, subsystem: &'a OverseenSubsystem<T>) -> Self::Output {
subsystem
.instance
.as_ref()
.map(|instance| (instance.name, instance.meters.clone()))
}
}
let subsystem_meters = overseer.map_subsystems(ExtractNameAndMeters);
let memory_stats =
MemoryAllocationTracker::new().expect("Jemalloc is the default allocator. qed");
let metronome = Metronome::new(std::time::Duration::from_millis(950)).for_each(move |_| {
match memory_stats.snapshot() {
Ok(memory_stats_snapshot) => {
tracing::trace!(target: LOG_TARGET, "memory_stats: {:?}", &memory_stats_snapshot);
metronome_metrics.memory_stats_snapshot(memory_stats_snapshot);
},
Err(e) => tracing::debug!(target: LOG_TARGET, "Failed to obtain memory stats: {:?}", e),
}
// We combine the amount of messages from subsystems to the overseer
// as well as the amount of messages from external sources to the overseer
// into one `to_overseer` value.
metronome_metrics.channel_fill_level_snapshot(
subsystem_meters
.iter()
.cloned()
.filter_map(|x| x)
.map(|(name, ref meters)| (name, meters.read())),
);
futures::future::ready(())
});
overseer.spawner().spawn("metrics_metronome", Box::pin(metronome));
Ok(())
}
impl<S, SupportsParachains> Overseer<S, SupportsParachains>
@@ -393,313 +553,6 @@ where
SupportsParachains: HeadSupportsParachains,
S: SpawnNamed,
{
/// Create a new instance of the [`Overseer`] with a fixed set of [`Subsystem`]s.
///
/// This returns the overseer along with an [`OverseerHandle`] which can
/// be used to send messages from external parts of the codebase.
///
/// The [`OverseerHandle`] returned from this function is connected to
/// the returned [`Overseer`].
///
/// ```text
/// +------------------------------------+
/// | Overseer |
/// +------------------------------------+
/// / | | \
/// ................. subsystems...................................
/// . +-----------+ +-----------+ +----------+ +---------+ .
/// . | | | | | | | | .
/// . +-----------+ +-----------+ +----------+ +---------+ .
/// ...............................................................
/// |
/// probably `spawn`
/// a `job`
/// |
/// V
/// +-----------+
/// | |
/// +-----------+
///
/// ```
///
/// [`Subsystem`]: trait.Subsystem.html
///
/// # Example
///
/// The [`Subsystems`] may be any type as long as they implement an expected interface.
/// Here, we create a mock validation subsystem and a few dummy ones and start the `Overseer` with them.
/// For the sake of simplicity the termination of the example is done with a timeout.
/// ```
/// # use std::time::Duration;
/// # use futures::{executor, pin_mut, select, FutureExt};
/// # use futures_timer::Delay;
/// # use polkadot_primitives::v1::Hash;
/// # use polkadot_overseer::{
/// # self as overseer,
/// # Overseer,
/// # OverseerSignal,
/// # OverseerConnector,
/// # SubsystemSender as _,
/// # AllMessages,
/// # AllSubsystems,
/// # HeadSupportsParachains,
/// # SubsystemError,
/// # gen::{
/// # SubsystemContext,
/// # FromOverseer,
/// # SpawnedSubsystem,
/// # },
/// # };
/// # use polkadot_node_subsystem_types::messages::{
/// # CandidateValidationMessage, CandidateBackingMessage,
/// # NetworkBridgeMessage,
/// # };
///
/// struct ValidationSubsystem;
///
/// impl<Ctx> overseer::Subsystem<Ctx, SubsystemError> for ValidationSubsystem
/// where
/// Ctx: overseer::SubsystemContext<
/// Message=CandidateValidationMessage,
/// AllMessages=AllMessages,
/// Signal=OverseerSignal,
/// Error=SubsystemError,
/// >,
/// {
/// fn start(
/// self,
/// mut ctx: Ctx,
/// ) -> SpawnedSubsystem<SubsystemError> {
/// SpawnedSubsystem {
/// name: "validation-subsystem",
/// future: Box::pin(async move {
/// loop {
/// Delay::new(Duration::from_secs(1)).await;
/// }
/// }),
/// }
/// }
/// }
///
/// # fn main() { executor::block_on(async move {
///
/// struct AlwaysSupportsParachains;
/// impl HeadSupportsParachains for AlwaysSupportsParachains {
/// fn head_supports_parachains(&self, _head: &Hash) -> bool { true }
/// }
/// let spawner = sp_core::testing::TaskExecutor::new();
/// let all_subsystems = AllSubsystems::<()>::dummy()
/// .replace_candidate_validation(|_| ValidationSubsystem);
/// let (overseer, _handle) = Overseer::new(
/// vec![],
/// all_subsystems,
/// None,
/// AlwaysSupportsParachains,
/// spawner,
/// OverseerConnector::default(),
/// ).unwrap();
///
/// let timer = Delay::new(Duration::from_millis(50)).fuse();
///
/// let overseer_fut = overseer.run().fuse();
/// pin_mut!(timer);
/// pin_mut!(overseer_fut);
///
/// select! {
/// _ = overseer_fut => (),
/// _ = timer => (),
/// }
/// #
/// # });
/// # }
/// ```
pub fn new<
CV,
CB,
SD,
AD,
AR,
BS,
BD,
P,
RA,
AS,
NB,
CA,
CG,
CP,
ApD,
ApV,
GS,
DC,
DP,
DD,
CS,
>(
leaves: impl IntoIterator<Item = BlockInfo>,
all_subsystems: AllSubsystems<
CV,
CB,
SD,
AD,
AR,
BS,
BD,
P,
RA,
AS,
NB,
CA,
CG,
CP,
ApD,
ApV,
GS,
DC,
DP,
DD,
CS,
>,
prometheus_registry: Option<&prometheus::Registry>,
supports_parachains: SupportsParachains,
s: S,
connector: OverseerConnector,
) -> SubsystemResult<(Self, OverseerHandle)>
where
CV: Subsystem<OverseerSubsystemContext<CandidateValidationMessage>, SubsystemError> + Send,
CB: Subsystem<OverseerSubsystemContext<CandidateBackingMessage>, SubsystemError> + Send,
SD: Subsystem<OverseerSubsystemContext<StatementDistributionMessage>, SubsystemError>
+ Send,
AD: Subsystem<OverseerSubsystemContext<AvailabilityDistributionMessage>, SubsystemError>
+ Send,
AR: Subsystem<OverseerSubsystemContext<AvailabilityRecoveryMessage>, SubsystemError> + Send,
BS: Subsystem<OverseerSubsystemContext<BitfieldSigningMessage>, SubsystemError> + Send,
BD: Subsystem<OverseerSubsystemContext<BitfieldDistributionMessage>, SubsystemError> + Send,
P: Subsystem<OverseerSubsystemContext<ProvisionerMessage>, SubsystemError> + Send,
RA: Subsystem<OverseerSubsystemContext<RuntimeApiMessage>, SubsystemError> + Send,
AS: Subsystem<OverseerSubsystemContext<AvailabilityStoreMessage>, SubsystemError> + Send,
NB: Subsystem<OverseerSubsystemContext<NetworkBridgeMessage>, SubsystemError> + Send,
CA: Subsystem<OverseerSubsystemContext<ChainApiMessage>, SubsystemError> + Send,
CG: Subsystem<OverseerSubsystemContext<CollationGenerationMessage>, SubsystemError> + Send,
CP: Subsystem<OverseerSubsystemContext<CollatorProtocolMessage>, SubsystemError> + Send,
ApD:
Subsystem<OverseerSubsystemContext<ApprovalDistributionMessage>, SubsystemError> + Send,
ApV: Subsystem<OverseerSubsystemContext<ApprovalVotingMessage>, SubsystemError> + Send,
GS: Subsystem<OverseerSubsystemContext<GossipSupportMessage>, SubsystemError> + Send,
DC: Subsystem<OverseerSubsystemContext<DisputeCoordinatorMessage>, SubsystemError> + Send,
DP: Subsystem<OverseerSubsystemContext<DisputeParticipationMessage>, SubsystemError> + Send,
DD: Subsystem<OverseerSubsystemContext<DisputeDistributionMessage>, SubsystemError> + Send,
CS: Subsystem<OverseerSubsystemContext<ChainSelectionMessage>, SubsystemError> + Send,
S: SpawnNamed,
{
let metrics = <crate::metrics::Metrics as MetricsTrait>::register(prometheus_registry)?;
let (mut overseer, handle) = Self::builder()
.candidate_validation(all_subsystems.candidate_validation)
.candidate_backing(all_subsystems.candidate_backing)
.statement_distribution(all_subsystems.statement_distribution)
.availability_distribution(all_subsystems.availability_distribution)
.availability_recovery(all_subsystems.availability_recovery)
.bitfield_signing(all_subsystems.bitfield_signing)
.bitfield_distribution(all_subsystems.bitfield_distribution)
.provisioner(all_subsystems.provisioner)
.runtime_api(all_subsystems.runtime_api)
.availability_store(all_subsystems.availability_store)
.network_bridge(all_subsystems.network_bridge)
.chain_api(all_subsystems.chain_api)
.collation_generation(all_subsystems.collation_generation)
.collator_protocol(all_subsystems.collator_protocol)
.approval_distribution(all_subsystems.approval_distribution)
.approval_voting(all_subsystems.approval_voting)
.gossip_support(all_subsystems.gossip_support)
.dispute_coordinator(all_subsystems.dispute_coordinator)
.dispute_participation(all_subsystems.dispute_participation)
.dispute_distribution(all_subsystems.dispute_distribution)
.chain_selection(all_subsystems.chain_selection)
.leaves(Vec::from_iter(
leaves
.into_iter()
.map(|BlockInfo { hash, parent_hash: _, number }| (hash, number)),
))
.known_leaves(LruCache::new(KNOWN_LEAVES_CACHE_SIZE))
.active_leaves(Default::default())
.span_per_active_leaf(Default::default())
.activation_external_listeners(Default::default())
.supports_parachains(supports_parachains)
.metrics(metrics.clone())
.spawner(s)
.build_with_connector(connector)?;
// spawn the metrics metronome task
{
struct ExtractNameAndMeters;
impl<'a, T: 'a> MapSubsystem<&'a OverseenSubsystem<T>> for ExtractNameAndMeters {
type Output = Option<(&'static str, SubsystemMeters)>;
fn map_subsystem(&self, subsystem: &'a OverseenSubsystem<T>) -> Self::Output {
subsystem
.instance
.as_ref()
.map(|instance| (instance.name, instance.meters.clone()))
}
}
let subsystem_meters = overseer.map_subsystems(ExtractNameAndMeters);
let memory_stats = match MemoryAllocationTracker::new() {
Ok(memory_stats) => Some(memory_stats),
Err(error) => {
tracing::debug!(
target: LOG_TARGET,
"Failed to initialize memory allocation tracker: {:?}",
error
);
None
},
};
let metronome_metrics = metrics.clone();
let metronome =
Metronome::new(std::time::Duration::from_millis(950)).for_each(move |_| {
if let Some(ref memory_stats) = memory_stats {
match memory_stats.snapshot() {
Ok(memory_stats_snapshot) => {
tracing::trace!(
target: LOG_TARGET,
"memory_stats: {:?}",
&memory_stats_snapshot
);
metronome_metrics.memory_stats_snapshot(memory_stats_snapshot);
},
Err(e) => tracing::debug!(
target: LOG_TARGET,
"Failed to obtain memory stats: {:?}",
e
),
}
}
// We combine the amount of messages from subsystems to the overseer
// as well as the amount of messages from external sources to the overseer
// into one `to_overseer` value.
metronome_metrics.channel_fill_level_snapshot(
subsystem_meters
.iter()
.cloned()
.filter_map(|x| x)
.map(|(name, ref meters)| (name, meters.read())),
);
async move { () }
});
overseer.spawner().spawn("metrics_metronome", Box::pin(metronome));
}
Ok((overseer, handle))
}
/// Stop the overseer.
async fn stop(mut self) {
let _ = self.wait_terminate(OverseerSignal::Conclude, Duration::from_secs(1_u64)).await;
@@ -707,6 +560,9 @@ where
/// Run the `Overseer`.
pub async fn run(mut self) -> SubsystemResult<()> {
let metrics = self.metrics.clone();
spawn_metronome_metrics(&mut self, metrics)?;
// Notify about active leaves on startup before starting the loop
for (hash, number) in std::mem::take(&mut self.leaves) {
let _ = self.active_leaves.insert(hash, number);
-344
View File
@@ -1,344 +0,0 @@
// Copyright 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 <http://www.gnu.org/licenses/>.
//! Legacy way of defining subsystems.
//!
//! In the future, everything should be set up using the generated
//! overseer builder pattern instead.
use crate::dummy::DummySubsystem;
use polkadot_overseer_all_subsystems_gen::AllSubsystemsGen;
use polkadot_overseer_gen::MapSubsystem;
/// This struct is passed as an argument to create a new instance of an [`Overseer`].
///
/// As any entity that satisfies the interface may act as a [`Subsystem`] this allows
/// mocking in the test code:
///
/// Each [`Subsystem`] is supposed to implement some interface that is generic over
/// message type that is specific to this [`Subsystem`]. At the moment not all
/// subsystems are implemented and the rest can be mocked with the [`DummySubsystem`].
#[derive(Debug, Clone, AllSubsystemsGen)]
pub struct AllSubsystems<
CV = (),
CB = (),
SD = (),
AD = (),
AR = (),
BS = (),
BD = (),
P = (),
RA = (),
AS = (),
NB = (),
CA = (),
CG = (),
CP = (),
ApD = (),
ApV = (),
GS = (),
DC = (),
DP = (),
DD = (),
CS = (),
> {
/// A candidate validation subsystem.
pub candidate_validation: CV,
/// A candidate backing subsystem.
pub candidate_backing: CB,
/// A statement distribution subsystem.
pub statement_distribution: SD,
/// An availability distribution subsystem.
pub availability_distribution: AD,
/// An availability recovery subsystem.
pub availability_recovery: AR,
/// A bitfield signing subsystem.
pub bitfield_signing: BS,
/// A bitfield distribution subsystem.
pub bitfield_distribution: BD,
/// A provisioner subsystem.
pub provisioner: P,
/// A runtime API subsystem.
pub runtime_api: RA,
/// An availability store subsystem.
pub availability_store: AS,
/// A network bridge subsystem.
pub network_bridge: NB,
/// A Chain API subsystem.
pub chain_api: CA,
/// A Collation Generation subsystem.
pub collation_generation: CG,
/// A Collator Protocol subsystem.
pub collator_protocol: CP,
/// An Approval Distribution subsystem.
pub approval_distribution: ApD,
/// An Approval Voting subsystem.
pub approval_voting: ApV,
/// A Connection Request Issuer subsystem.
pub gossip_support: GS,
/// A Dispute Coordinator subsystem.
pub dispute_coordinator: DC,
/// A Dispute Participation subsystem.
pub dispute_participation: DP,
/// A Dispute Distribution subsystem.
pub dispute_distribution: DD,
/// A Chain Selection subsystem.
pub chain_selection: CS,
}
impl<CV, CB, SD, AD, AR, BS, BD, P, RA, AS, NB, CA, CG, CP, ApD, ApV, GS, DC, DP, DD, CS>
AllSubsystems<CV, CB, SD, AD, AR, BS, BD, P, RA, AS, NB, CA, CG, CP, ApD, ApV, GS, DC, DP, DD, CS>
{
/// Create a new instance of [`AllSubsystems`].
///
/// Each subsystem is set to [`DummySystem`].
///
///# Note
///
/// Because of a bug in rustc it is required that when calling this function,
/// you provide a "random" type for the first generic parameter:
///
/// ```
/// polkadot_overseer::AllSubsystems::<()>::dummy();
/// ```
pub fn dummy() -> AllSubsystems<
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
DummySubsystem,
> {
AllSubsystems {
candidate_validation: DummySubsystem,
candidate_backing: DummySubsystem,
statement_distribution: DummySubsystem,
availability_distribution: DummySubsystem,
availability_recovery: DummySubsystem,
bitfield_signing: DummySubsystem,
bitfield_distribution: DummySubsystem,
provisioner: DummySubsystem,
runtime_api: DummySubsystem,
availability_store: DummySubsystem,
network_bridge: DummySubsystem,
chain_api: DummySubsystem,
collation_generation: DummySubsystem,
collator_protocol: DummySubsystem,
approval_distribution: DummySubsystem,
approval_voting: DummySubsystem,
gossip_support: DummySubsystem,
dispute_coordinator: DummySubsystem,
dispute_participation: DummySubsystem,
dispute_distribution: DummySubsystem,
chain_selection: DummySubsystem,
}
}
/// Reference every individual subsystem.
pub fn as_ref(
&self,
) -> AllSubsystems<
&'_ CV,
&'_ CB,
&'_ SD,
&'_ AD,
&'_ AR,
&'_ BS,
&'_ BD,
&'_ P,
&'_ RA,
&'_ AS,
&'_ NB,
&'_ CA,
&'_ CG,
&'_ CP,
&'_ ApD,
&'_ ApV,
&'_ GS,
&'_ DC,
&'_ DP,
&'_ DD,
&'_ CS,
> {
AllSubsystems {
candidate_validation: &self.candidate_validation,
candidate_backing: &self.candidate_backing,
statement_distribution: &self.statement_distribution,
availability_distribution: &self.availability_distribution,
availability_recovery: &self.availability_recovery,
bitfield_signing: &self.bitfield_signing,
bitfield_distribution: &self.bitfield_distribution,
provisioner: &self.provisioner,
runtime_api: &self.runtime_api,
availability_store: &self.availability_store,
network_bridge: &self.network_bridge,
chain_api: &self.chain_api,
collation_generation: &self.collation_generation,
collator_protocol: &self.collator_protocol,
approval_distribution: &self.approval_distribution,
approval_voting: &self.approval_voting,
gossip_support: &self.gossip_support,
dispute_coordinator: &self.dispute_coordinator,
dispute_participation: &self.dispute_participation,
dispute_distribution: &self.dispute_distribution,
chain_selection: &self.chain_selection,
}
}
/// Map each subsystem.
pub fn map_subsystems<Mapper>(
self,
mapper: Mapper,
) -> AllSubsystems<
<Mapper as MapSubsystem<CV>>::Output,
<Mapper as MapSubsystem<CB>>::Output,
<Mapper as MapSubsystem<SD>>::Output,
<Mapper as MapSubsystem<AD>>::Output,
<Mapper as MapSubsystem<AR>>::Output,
<Mapper as MapSubsystem<BS>>::Output,
<Mapper as MapSubsystem<BD>>::Output,
<Mapper as MapSubsystem<P>>::Output,
<Mapper as MapSubsystem<RA>>::Output,
<Mapper as MapSubsystem<AS>>::Output,
<Mapper as MapSubsystem<NB>>::Output,
<Mapper as MapSubsystem<CA>>::Output,
<Mapper as MapSubsystem<CG>>::Output,
<Mapper as MapSubsystem<CP>>::Output,
<Mapper as MapSubsystem<ApD>>::Output,
<Mapper as MapSubsystem<ApV>>::Output,
<Mapper as MapSubsystem<GS>>::Output,
<Mapper as MapSubsystem<DC>>::Output,
<Mapper as MapSubsystem<DP>>::Output,
<Mapper as MapSubsystem<DD>>::Output,
<Mapper as MapSubsystem<CS>>::Output,
>
where
Mapper: MapSubsystem<CV>,
Mapper: MapSubsystem<CB>,
Mapper: MapSubsystem<SD>,
Mapper: MapSubsystem<AD>,
Mapper: MapSubsystem<AR>,
Mapper: MapSubsystem<BS>,
Mapper: MapSubsystem<BD>,
Mapper: MapSubsystem<P>,
Mapper: MapSubsystem<RA>,
Mapper: MapSubsystem<AS>,
Mapper: MapSubsystem<NB>,
Mapper: MapSubsystem<CA>,
Mapper: MapSubsystem<CG>,
Mapper: MapSubsystem<CP>,
Mapper: MapSubsystem<ApD>,
Mapper: MapSubsystem<ApV>,
Mapper: MapSubsystem<GS>,
Mapper: MapSubsystem<DC>,
Mapper: MapSubsystem<DP>,
Mapper: MapSubsystem<DD>,
Mapper: MapSubsystem<CS>,
{
AllSubsystems {
candidate_validation: <Mapper as MapSubsystem<CV>>::map_subsystem(
&mapper,
self.candidate_validation,
),
candidate_backing: <Mapper as MapSubsystem<CB>>::map_subsystem(
&mapper,
self.candidate_backing,
),
statement_distribution: <Mapper as MapSubsystem<SD>>::map_subsystem(
&mapper,
self.statement_distribution,
),
availability_distribution: <Mapper as MapSubsystem<AD>>::map_subsystem(
&mapper,
self.availability_distribution,
),
availability_recovery: <Mapper as MapSubsystem<AR>>::map_subsystem(
&mapper,
self.availability_recovery,
),
bitfield_signing: <Mapper as MapSubsystem<BS>>::map_subsystem(
&mapper,
self.bitfield_signing,
),
bitfield_distribution: <Mapper as MapSubsystem<BD>>::map_subsystem(
&mapper,
self.bitfield_distribution,
),
provisioner: <Mapper as MapSubsystem<P>>::map_subsystem(&mapper, self.provisioner),
runtime_api: <Mapper as MapSubsystem<RA>>::map_subsystem(&mapper, self.runtime_api),
availability_store: <Mapper as MapSubsystem<AS>>::map_subsystem(
&mapper,
self.availability_store,
),
network_bridge: <Mapper as MapSubsystem<NB>>::map_subsystem(
&mapper,
self.network_bridge,
),
chain_api: <Mapper as MapSubsystem<CA>>::map_subsystem(&mapper, self.chain_api),
collation_generation: <Mapper as MapSubsystem<CG>>::map_subsystem(
&mapper,
self.collation_generation,
),
collator_protocol: <Mapper as MapSubsystem<CP>>::map_subsystem(
&mapper,
self.collator_protocol,
),
approval_distribution: <Mapper as MapSubsystem<ApD>>::map_subsystem(
&mapper,
self.approval_distribution,
),
approval_voting: <Mapper as MapSubsystem<ApV>>::map_subsystem(
&mapper,
self.approval_voting,
),
gossip_support: <Mapper as MapSubsystem<GS>>::map_subsystem(
&mapper,
self.gossip_support,
),
dispute_coordinator: <Mapper as MapSubsystem<DC>>::map_subsystem(
&mapper,
self.dispute_coordinator,
),
dispute_participation: <Mapper as MapSubsystem<DP>>::map_subsystem(
&mapper,
self.dispute_participation,
),
dispute_distribution: <Mapper as MapSubsystem<DD>>::map_subsystem(
&mapper,
self.dispute_distribution,
),
chain_selection: <Mapper as MapSubsystem<CS>>::map_subsystem(
&mapper,
self.chain_selection,
),
}
}
}
+71 -109
View File
@@ -32,7 +32,12 @@ use polkadot_primitives::v1::{
ValidatorIndex,
};
use crate::{self as overseer, gen::Delay, HeadSupportsParachains, Overseer, OverseerConnector};
use crate::{
self as overseer,
dummy::{dummy_overseer_builder, one_for_all_overseer_builder},
gen::Delay,
HeadSupportsParachains,
};
use metered_channel as metered;
use assert_matches::assert_matches;
@@ -40,6 +45,15 @@ use sp_core::crypto::Pair as _;
use super::*;
fn block_info_to_pair(blocks: impl IntoIterator<Item = BlockInfo>) -> Vec<(Hash, BlockNumber)> {
use std::iter::FromIterator;
Vec::from_iter(
blocks
.into_iter()
.map(|BlockInfo { hash, parent_hash: _, number }| (hash, number)),
)
}
type SpawnedSubsystem = crate::gen::SpawnedSubsystem<SubsystemError>;
struct TestSubsystem1(metered::MeteredSender<usize>);
@@ -159,20 +173,12 @@ fn overseer_works() {
let mut s1_rx = s1_rx.fuse();
let mut s2_rx = s2_rx.fuse();
let all_subsystems = AllSubsystems::<()>::dummy()
let (overseer, handle) = dummy_overseer_builder(spawner, MockSupportsParachains, None)
.unwrap()
.replace_candidate_validation(move |_| TestSubsystem1(s1_tx))
.replace_candidate_backing(move |_| TestSubsystem2(s2_tx));
let (overseer, handle) = Overseer::new(
vec![],
all_subsystems,
None,
MockSupportsParachains,
spawner,
OverseerConnector::default(),
)
.unwrap();
.replace_candidate_backing(move |_| TestSubsystem2(s2_tx))
.build()
.unwrap();
let mut handle = Handle::new(handle);
let overseer_fut = overseer.run().fuse();
@@ -226,17 +232,14 @@ fn overseer_metrics_work() {
let third_block =
BlockInfo { hash: third_block_hash, parent_hash: second_block_hash, number: 3 };
let all_subsystems = AllSubsystems::<()>::dummy();
let registry = prometheus::Registry::new();
let (overseer, handle) = Overseer::new(
vec![first_block],
all_subsystems,
Some(&registry),
MockSupportsParachains,
spawner,
OverseerConnector::default(),
)
.unwrap();
let (overseer, handle) =
dummy_overseer_builder(spawner, MockSupportsParachains, Some(&registry))
.unwrap()
.leaves(block_info_to_pair(vec![first_block]))
.build()
.unwrap();
let mut handle = Handle::new(handle);
let overseer_fut = overseer.run().fuse();
@@ -264,13 +267,20 @@ fn overseer_metrics_work() {
fn extract_metrics(registry: &prometheus::Registry) -> HashMap<&'static str, u64> {
let gather = registry.gather();
let gather = &gather[2..];
assert_eq!(gather[0].get_name(), "parachain_activated_heads_total");
assert_eq!(gather[1].get_name(), "parachain_deactivated_heads_total");
assert_eq!(gather[2].get_name(), "parachain_messages_relayed_total");
let activated = gather[0].get_metric()[0].get_counter().get_value() as u64;
let deactivated = gather[1].get_metric()[0].get_counter().get_value() as u64;
let relayed = gather[2].get_metric()[0].get_counter().get_value() as u64;
assert!(!gather.is_empty(), "Gathered metrics are not empty. qed");
let extract = |name: &str| -> u64 {
gather
.iter()
.find(|&mf| dbg!(mf.get_name()) == dbg!(name))
.expect(&format!("Must contain `{}` metric", name))
.get_metric()[0]
.get_counter()
.get_value() as u64
};
let activated = extract("parachain_activated_heads_total");
let deactivated = extract("parachain_deactivated_heads_total");
let relayed = extract("parachain_messages_relayed_total");
let mut result = HashMap::new();
result.insert("activated", activated);
result.insert("deactivated", deactivated);
@@ -286,17 +296,11 @@ fn overseer_ends_on_subsystem_exit() {
let spawner = sp_core::testing::TaskExecutor::new();
executor::block_on(async move {
let all_subsystems =
AllSubsystems::<()>::dummy().replace_candidate_backing(|_| ReturnOnStart);
let (overseer, _handle) = Overseer::new(
vec![],
all_subsystems,
None,
MockSupportsParachains,
spawner,
OverseerConnector::default(),
)
.unwrap();
let (overseer, _handle) = dummy_overseer_builder(spawner, MockSupportsParachains, None)
.unwrap()
.replace_candidate_backing(|_| ReturnOnStart)
.build()
.unwrap();
overseer.run().await.unwrap();
})
@@ -394,18 +398,14 @@ fn overseer_start_stop_works() {
let (tx_5, mut rx_5) = metered::channel(64);
let (tx_6, mut rx_6) = metered::channel(64);
let all_subsystems = AllSubsystems::<()>::dummy()
let (overseer, handle) = dummy_overseer_builder(spawner, MockSupportsParachains, None)
.unwrap()
.replace_candidate_validation(move |_| TestSubsystem5(tx_5))
.replace_candidate_backing(move |_| TestSubsystem6(tx_6));
let (overseer, handle) = Overseer::new(
vec![first_block],
all_subsystems,
None,
MockSupportsParachains,
spawner,
OverseerConnector::default(),
)
.unwrap();
.replace_candidate_backing(move |_| TestSubsystem6(tx_6))
.leaves(block_info_to_pair(vec![first_block]))
.build()
.unwrap();
let mut handle = Handle::new(handle);
let overseer_fut = overseer.run().fuse();
@@ -496,20 +496,15 @@ fn overseer_finalize_works() {
let (tx_5, mut rx_5) = metered::channel(64);
let (tx_6, mut rx_6) = metered::channel(64);
let all_subsystems = AllSubsystems::<()>::dummy()
.replace_candidate_validation(move |_| TestSubsystem5(tx_5))
.replace_candidate_backing(move |_| TestSubsystem6(tx_6));
// start with two forks of different height.
let (overseer, handle) = Overseer::new(
vec![first_block, second_block],
all_subsystems,
None,
MockSupportsParachains,
spawner,
OverseerConnector::default(),
)
.unwrap();
let (overseer, handle) = dummy_overseer_builder(spawner, MockSupportsParachains, None)
.unwrap()
.replace_candidate_validation(move |_| TestSubsystem5(tx_5))
.replace_candidate_backing(move |_| TestSubsystem6(tx_6))
.leaves(block_info_to_pair(vec![first_block, second_block]))
.build()
.unwrap();
let mut handle = Handle::new(handle);
let overseer_fut = overseer.run().fuse();
@@ -592,18 +587,12 @@ fn do_not_send_empty_leaves_update_on_block_finalization() {
let (tx_5, mut rx_5) = metered::channel(64);
let all_subsystems =
AllSubsystems::<()>::dummy().replace_candidate_backing(move |_| TestSubsystem6(tx_5));
let (overseer, handle) = dummy_overseer_builder(spawner, MockSupportsParachains, None)
.unwrap()
.replace_candidate_backing(move |_| TestSubsystem6(tx_5))
.build()
.unwrap();
let (overseer, handle) = Overseer::new(
Vec::new(),
all_subsystems,
None,
MockSupportsParachains,
spawner,
OverseerConnector::default(),
)
.unwrap();
let mut handle = Handle::new(handle);
let overseer_fut = overseer.run().fuse();
@@ -854,39 +843,12 @@ fn overseer_all_subsystems_receive_signals_and_messages() {
msgs_received.clone(),
);
let all_subsystems = AllSubsystems {
candidate_validation: subsystem.clone(),
candidate_backing: subsystem.clone(),
collation_generation: subsystem.clone(),
collator_protocol: subsystem.clone(),
statement_distribution: subsystem.clone(),
availability_distribution: subsystem.clone(),
availability_recovery: subsystem.clone(),
bitfield_signing: subsystem.clone(),
bitfield_distribution: subsystem.clone(),
provisioner: subsystem.clone(),
runtime_api: subsystem.clone(),
availability_store: subsystem.clone(),
network_bridge: subsystem.clone(),
chain_api: subsystem.clone(),
approval_distribution: subsystem.clone(),
approval_voting: subsystem.clone(),
gossip_support: subsystem.clone(),
dispute_coordinator: subsystem.clone(),
dispute_participation: subsystem.clone(),
dispute_distribution: subsystem.clone(),
chain_selection: subsystem.clone(),
};
let (overseer, handle) =
one_for_all_overseer_builder(spawner, MockSupportsParachains, subsystem, None)
.unwrap()
.build()
.unwrap();
let (overseer, handle) = Overseer::new(
vec![],
all_subsystems,
None,
MockSupportsParachains,
spawner,
OverseerConnector::default(),
)
.unwrap();
let mut handle = Handle::new(handle);
let overseer_fut = overseer.run().fuse();