Create a more rigid overseer builder pattern that fails at compile time (#4753)

Introduces `Missing<Field>` and `Init<Field>` states, that are used in place of builder generics, and make this possible.
This commit is contained in:
Vsevolod Stakhov
2022-02-09 16:01:16 +00:00
committed by GitHub
parent 227e39bff6
commit 84f55cc8d5
20 changed files with 891 additions and 267 deletions
@@ -33,7 +33,7 @@ use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig;
use polkadot_node_core_provisioner::ProvisionerConfig;
use polkadot_node_network_protocol::request_response::{v1 as request_v1, IncomingRequestReceiver};
use polkadot_overseer::{
metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, OverseerBuilder,
metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, InitializedOverseerBuilder,
OverseerConnector, OverseerHandle,
};
use polkadot_primitives::v1::ParachainHost;
@@ -139,7 +139,7 @@ pub fn prepared_overseer_builder<Spawner, RuntimeClient>(
disputes_enabled,
}: OverseerGenArgs<'_, Spawner, RuntimeClient>,
) -> Result<
OverseerBuilder<
InitializedOverseerBuilder<
Spawner,
Arc<RuntimeClient>,
CandidateValidationSubsystem,
@@ -0,0 +1,78 @@
# overseer pattern
The overseer pattern is a partial actor pattern
## proc-macro
The proc macro provides a convenience generator with a builder pattern,
where at it's core it creates and spawns a set of subsystems, which are purely
declarative.
```rust
#[overlord(signal=SigSigSig, event=Event, gen=AllMessages, error=OverseerError)]
pub struct Overseer {
#[subsystem(MsgA)]
sub_a: AwesomeSubSysA,
#[subsystem(MsgB)]
sub_b: AwesomeSubSysB,
}
```
* Each subsystem is annotated with `#[subsystem(_)]` where `MsgA` respectively `MsgB` are the messages
being consumed by that particular subsystem. Each of those subsystems is required to implement the subsystem
trait.
* `error=` tells the overseer to use the user provided
error type, if not provided a builtin one is used. Note that this is the one error type used throughout all calls, so make sure it does impl `From<E>` for all other error types `E` that are relevant to your application.
* `event=` declares an external event type, that injects certain events
into the overseer, without participating in the subsystem pattern.
* `signal=` defines a signal type to be used for the overseer. This is a shared "clock" for all subsystems.
* `gen=` defines a wrapping `enum` type that is used to wrap all messages that can be consumed by _any_ subsystem.
```rust
/// Execution context, always requred.
pub struct DummyCtx;
/// Task spawner, always required.
pub struct DummySpawner;
fn main() {
let _overseer = Overseer::builder()
.sub_a(AwesomeSubSysA::default())
.sub_b(AwesomeSubSysB::default())
.spawner(DummySpawner)
.build();
}
```
In the shown `main`, the overseer is created by means of a generated, compile time erroring
builder pattern.
The builder requires all subsystems, baggage fields (additional struct data) and spawner to be
set via the according setter method before `build` method could even be called. Failure to do
such an initialization will lead to a compile error. This is implemented by encoding each
builder field in a set of so called `state generics`, meaning that each field can be either
`Init<T>` or `Missing<T>`, so each setter translates a state from `Missing` to `Init` state
for the specific struct field. Therefore, if you see a compile time error that blames about
`Missing` where `Init` is expected it usually means that some subsystems or baggage fields were
not set prior to the `build` call.
To exclude subsystems from such a check, one can set `wip` attribute on some subsystem that
is not ready to be included in the Overseer:
```rust
#[overlord(signal=SigSigSig, event=Event, gen=AllMessages, error=OverseerError)]
pub struct Overseer {
#[subsystem(MsgA)]
sub_a: AwesomeSubSysA,
#[subsystem(MsgB), wip]
sub_b: AwesomeSubSysB, // This subsystem will not be required nor allowed to be set
}
```
Baggage fields can be initialized more than one time, however, it is not true for subsystems:
subsystems must be initialized only once (another compile time check) or be _replaced_ by
a special setter like method `replace_<subsystem>`.
A task spawner and subsystem context are required to be defined with `SpawnNamed` and respectively `SubsystemContext` implemented.
@@ -2,6 +2,7 @@
use polkadot_node_network_protocol::WrongVariant;
use polkadot_overseer_gen::*;
use std::collections::HashMap;
/// Concrete subsystem implementation for `MsgStrukt` msg type.
#[derive(Default)]
@@ -88,7 +89,7 @@ impl NetworkMsg {
}
#[overlord(signal=SigSigSig, event=EvX, error=Yikes, network=NetworkMsg, gen=AllMessages)]
struct Xxx {
struct Xxx<T> {
#[subsystem(MsgStrukt)]
sub0: AwesomeSubSys,
@@ -96,6 +97,8 @@ struct Xxx {
plinkos: GoblinTower,
i_like_pi: f64,
i_like_generic: T,
i_like_hash: HashMap<f64, f64>,
}
#[derive(Debug, Clone)]
@@ -125,12 +128,16 @@ impl SpawnNamed for DummySpawner {
struct DummyCtx;
fn main() {
let (overseer, _handle): (Xxx<_>, _) = Xxx::builder()
let (overseer, _handle): (Xxx<_, f64>, _) = Xxx::builder()
.sub0(AwesomeSubSys::default())
.plinkos(GoblinTower::default())
.i_like_pi(::std::f64::consts::PI)
.i_like_generic(42.0)
.i_like_hash(HashMap::new())
.spawner(DummySpawner)
.build()
.unwrap();
assert_eq!(overseer.i_like_pi.floor() as i8, 3);
assert_eq!(overseer.i_like_generic.floor() as i8, 42);
assert_eq!(overseer.i_like_hash.len() as i8, 0);
}
@@ -15,41 +15,15 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use quote::{format_ident, quote};
use syn::Ident;
use syn::{parse_quote, Path, PathSegment};
use super::*;
/// Returns all combinations for a single replacement:
/// 1. generic args with `NEW` in place
/// 2. subsystem type to be replaced
/// 3. the subsystem name to be replaced by a new type and value
/// 4. all other subsystems that are supposed to be kept
fn derive_replacable_generic_lists(
info: &OverseerInfo,
) -> Vec<(TokenStream, Ident, Ident, Vec<Ident>)> {
// subsystem generic types
let builder_generic_ty = info.builder_generic_types();
let to_be_replaced_name = info.subsystem_names_without_wip();
let baggage_generic_ty = &info.baggage_generic_types();
builder_generic_ty
.iter()
.enumerate()
.map(|(idx, to_be_replaced_ty)| {
let mut to_keep_name = to_be_replaced_name.clone();
let to_be_replaced_name: Ident = to_keep_name.remove(idx);
let mut builder_generic_ty = builder_generic_ty.clone();
builder_generic_ty[idx] = format_ident!("NEW");
let generics_ts = quote! {
<S, #( #baggage_generic_ty, )* #( #builder_generic_ty, )* >
};
(generics_ts, to_be_replaced_ty.clone(), to_be_replaced_name, to_keep_name)
})
.collect::<Vec<(_, _, _, _)>>()
fn recollect_without_idx<T: Clone>(x: &[T], idx: usize) -> Vec<T> {
let mut v = Vec::<T>::with_capacity(x.len().saturating_sub(1));
v.extend(x.iter().take(idx).cloned());
v.extend(x.iter().skip(idx + 1).cloned());
v
}
/// Implement a builder pattern for the `Overseer`-type,
@@ -58,24 +32,15 @@ fn derive_replacable_generic_lists(
/// Elements tagged with `wip` are not covered here.
pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
let overseer_name = info.overseer_name.clone();
let builder = Ident::new(&(overseer_name.to_string() + "Builder"), overseer_name.span());
let handle = Ident::new(&(overseer_name.to_string() + "Handle"), overseer_name.span());
let connector = Ident::new(&(overseer_name.to_string() + "Connector"), overseer_name.span());
let builder = format_ident!("{}Builder", overseer_name);
let handle = format_ident!("{}Handle", overseer_name);
let connector = format_ident!("{}Connector", overseer_name);
let subsystem_ctx_name = format_ident!("{}SubsystemContext", overseer_name);
let subsystem_name = &info.subsystem_names_without_wip();
let subsystem_name_init_with = &info
.subsystem_names_without_wip()
.iter()
.map(|subsystem_name| format_ident!("{}_with", subsystem_name))
.collect::<Vec<_>>();
let subsystem_name_replace_with = &info
.subsystem_names_without_wip()
.iter()
.map(|subsystem_name| format_ident!("replace_{}", subsystem_name))
.collect::<Vec<_>>();
let builder_generic_ty = &info.builder_generic_types();
let subsystem_generics = &info.subsystem_generic_types();
let consumes = &info.consumes_without_wip();
let channel_name = &info.channel_names_without_wip("");
let channel_name_unbounded = &info.channel_names_without_wip("_unbounded");
@@ -85,11 +50,20 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
let channel_name_rx = &info.channel_names_without_wip("_rx");
let channel_name_unbounded_rx = &info.channel_names_without_wip("_unbounded_rx");
let baggage_generic_ty = &info.baggage_generic_types();
let baggage_name = &info.baggage_names();
let baggage_ty = &info.baggage_types();
let baggage_generic_ty = &info.baggage_generic_types();
let subsystem_ctx_name = format_ident!("{}SubsystemContext", overseer_name);
// State generics that are used to encode each field's status (Init/Missing)
let baggage_passthrough_state_generics = baggage_name
.iter()
.enumerate()
.map(|(idx, _)| format_ident!("InitStateBaggage{}", idx))
.collect::<Vec<_>>();
let subsystem_passthrough_state_generics = subsystem_name
.iter()
.enumerate()
.map(|(idx, _)| format_ident!("InitStateSubsystem{}", idx))
.collect::<Vec<_>>();
let error_ty = &info.extern_error_ty;
@@ -107,49 +81,256 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
})
.collect::<Vec<_>>();
let generics = quote! {
< S, #( #baggage_generic_ty, )* >
};
let where_clause = quote! {
where
S: #support_crate ::SpawnNamed,
// Helpers to use within quote! macros
let spawner_where_clause: syn::TypeParam = parse_quote! {
S: #support_crate ::SpawnNamed + Send
};
let builder_generics = quote! {
<S, #( #baggage_generic_ty, )* #( #builder_generic_ty, )* >
};
// Field names and real types
let field_name = subsystem_name.iter().chain(baggage_name.iter()).collect::<Vec<_>>();
let field_type = subsystem_generics
.iter()
.map(|ident| Path::from(PathSegment::from(ident.clone())))
.chain(info.baggage().iter().map(|bag| bag.field_ty.clone()))
.collect::<Vec<_>>();
// all subsystems must have the same context
// even if the overseer does not impose such a limit.
let builder_additional_generics = quote! {
<#( #builder_generic_ty, )* >
};
// Setters logic
let consumes = &info.consumes();
// For each setter we need to leave the remaining fields untouched and
// remove the field that we are fixing in this setter
// For subsystems `*_with` and `replace_*` setters are needed.
let subsystem_specific_setters =
info.subsystems().iter().filter(|ssf| !ssf.wip).enumerate().map(|(idx, ssf)| {
let field_name = &ssf.name;
let field_type = &ssf.generic;
let subsystem_consumes = &ssf.consumes;
// Remove state generic for the item to be replaced. It sufficient to know `field_type` for
// that since we always move from `Init<#field_type>` to `Init<NEW>`.
let impl_subsystem_state_generics = recollect_without_idx(&subsystem_passthrough_state_generics[..], idx);
let subsyste_ctx_name =
Ident::new(&(overseer_name.to_string() + "SubsystemContext"), overseer_name.span());
let field_name_with = format_ident!("{}_with", field_name);
let field_name_replace = format_ident!("replace_{}", field_name);
let builder_where_clause = quote! {
where
S: #support_crate ::SpawnNamed,
#(
#builder_generic_ty : Subsystem<#subsyste_ctx_name< #consumes >, #error_ty>,
)*
};
// In a setter we replace `Uninit<T>` with `Init<T>` leaving all other
// types as they are, as such they will be free generics.
let mut current_state_generics = subsystem_passthrough_state_generics
.iter()
.map(|subsystem_state_generic_ty| parse_quote!(#subsystem_state_generic_ty))
.collect::<Vec<syn::GenericArgument>>();
current_state_generics[idx] = parse_quote! { Missing<#field_type> };
// Generics that will be present after initializing a specific `Missing<_>` field.
let mut post_setter_state_generics = current_state_generics.clone();
post_setter_state_generics[idx] = parse_quote! { Init<#field_type> };
let mut post_replace_state_generics = current_state_generics.clone();
post_replace_state_generics[idx] = parse_quote! { Init<NEW> };
// All fields except the one we update with the new argument
// see the loop below.
let to_keep_subsystem_name = recollect_without_idx(&subsystem_name[..], idx);
// Create the field init `fn`
quote! {
impl <InitStateSpawner, #field_type, #( #impl_subsystem_state_generics, )* #( #baggage_passthrough_state_generics, )*>
#builder <InitStateSpawner, #( #current_state_generics, )* #( #baggage_passthrough_state_generics, )*>
where
#field_type : Subsystem<#subsystem_ctx_name<#subsystem_consumes>, #error_ty>,
{
/// Specify the subsystem in the builder directly
pub fn #field_name (self, var: #field_type ) ->
#builder <InitStateSpawner, #( #post_setter_state_generics, )* #( #baggage_passthrough_state_generics, )*>
{
#builder {
#field_name: Init::<#field_type>::Value(var),
#(
#to_keep_subsystem_name: self. #to_keep_subsystem_name,
)*
#(
#baggage_name: self. #baggage_name,
)*
spawner: self.spawner,
}
}
/// Specify the the initialization function for a subsystem
pub fn #field_name_with<'a, F>(self, subsystem_init_fn: F ) ->
#builder <InitStateSpawner, #( #post_setter_state_generics, )* #( #baggage_passthrough_state_generics, )*>
where
F: 'static + FnOnce(#handle) ->
::std::result::Result<#field_type, #error_ty>,
{
let boxed_func = Init::<#field_type>::Fn(
Box::new(subsystem_init_fn) as SubsystemInitFn<#field_type>
);
#builder {
#field_name: boxed_func,
#(
#to_keep_subsystem_name: self. #to_keep_subsystem_name,
)*
#(
#baggage_name: self. #baggage_name,
)*
spawner: self.spawner,
}
}
}
impl <InitStateSpawner, #field_type, #( #impl_subsystem_state_generics, )* #( #baggage_passthrough_state_generics, )*>
#builder <InitStateSpawner, #( #post_setter_state_generics, )* #( #baggage_passthrough_state_generics, )*>
where
#field_type : Subsystem<#subsystem_ctx_name<#subsystem_consumes>, #error_ty>,
{
/// Replace a subsystem by another implementation for the
/// consumable message type.
pub fn #field_name_replace<NEW, F>(self, gen_replacement_fn: F)
-> #builder <InitStateSpawner, #( #post_replace_state_generics, )* #( #baggage_passthrough_state_generics, )*>
where
#field_type: 'static,
F: 'static + FnOnce(#field_type) -> NEW,
NEW: #support_crate ::Subsystem<#subsystem_ctx_name< #subsystem_consumes >, #error_ty>,
{
let replacement: Init<NEW> = match self.#field_name {
Init::Fn(fx) =>
Init::<NEW>::Fn(Box::new(move |handle: #handle| {
let orig = fx(handle)?;
Ok(gen_replacement_fn(orig))
})),
Init::Value(val) =>
Init::Value(gen_replacement_fn(val)),
};
#builder {
#field_name: replacement,
#(
#to_keep_subsystem_name: self. #to_keep_subsystem_name,
)*
#(
#baggage_name: self. #baggage_name,
)*
spawner: self.spawner,
}
}
}
}
});
// Produce setters for all baggage fields as well
let baggage_specific_setters = info.baggage().iter().enumerate().map(|(idx, bag_field)| {
// Baggage fields follow subsystems
let fname = &bag_field.field_name;
let field_type = &bag_field.field_ty;
let impl_baggage_state_generics = recollect_without_idx(&baggage_passthrough_state_generics[..], idx);
let to_keep_baggage_name = recollect_without_idx(&baggage_name[..], idx);
let mut pre_setter_generics = baggage_passthrough_state_generics
.iter()
.map(|gen_ty| parse_quote!(#gen_ty))
.collect::<Vec<syn::GenericArgument>>();
pre_setter_generics[idx] = parse_quote! { Missing<#field_type> };
let mut post_setter_generics = pre_setter_generics.clone();
post_setter_generics[idx] = parse_quote! { Init<#field_type> };
// Baggage can also be generic, so we need to include that to a signature
let preserved_baggage_generic = if bag_field.generic {
quote! {#field_type,}
} else {
TokenStream::new()
};
quote! {
impl <InitStateSpawner, #preserved_baggage_generic #( #subsystem_passthrough_state_generics, )* #( #impl_baggage_state_generics, )* >
#builder <InitStateSpawner, #( #subsystem_passthrough_state_generics, )* #( #pre_setter_generics, )* >
{
/// Specify the baggage in the builder when it was not initialized before
pub fn #fname (self, var: #field_type ) ->
#builder <InitStateSpawner, #( #subsystem_passthrough_state_generics, )* #( #post_setter_generics, )* >
{
#builder {
#fname: Init::<#field_type>::Value(var),
#(
#subsystem_name: self. #subsystem_name,
)*
#(
#to_keep_baggage_name: self. #to_keep_baggage_name,
)*
spawner: self.spawner,
}
}
}
impl <InitStateSpawner, #preserved_baggage_generic #( #subsystem_passthrough_state_generics, )* #( #impl_baggage_state_generics, )* >
#builder <InitStateSpawner, #( #subsystem_passthrough_state_generics, )* #( #post_setter_generics, )* > {
/// Specify the baggage in the builder when it has been previously initialized
pub fn #fname (self, var: #field_type ) ->
#builder <InitStateSpawner, #( #subsystem_passthrough_state_generics, )* #( #post_setter_generics, )* >
{
#builder {
#fname: Init::<#field_type>::Value(var),
#(
#subsystem_name: self. #subsystem_name,
)*
#(
#to_keep_baggage_name: self. #to_keep_baggage_name,
)*
spawner: self.spawner,
}
}
}
}
});
let event = &info.extern_event_ty;
let initialized_builder = format_ident!("Initialized{}", builder);
// The direct generics as expected by the `Overseer<_,_,..>`, without states
let initialized_builder_generics = quote! {
S, #( #baggage_generic_ty, )* #( #subsystem_generics, )*
};
let mut ts = quote! {
impl #generics #overseer_name #generics #where_clause {
/// Create a new overseer utilizing the builder.
pub fn builder #builder_additional_generics () -> #builder #builder_generics
#builder_where_clause
{
#builder :: default()
/// Convenience alias.
type SubsystemInitFn<T> = Box<dyn FnOnce(#handle) -> ::std::result::Result<T, #error_ty> >;
/// Type for the initialized field of the overseer builder
pub enum Init<T> {
/// Defer initialization to a point where the `handle` is available.
Fn(SubsystemInitFn<T>),
/// Directly initialize the subsystem with the given subsystem type `T`.
/// Also used for baggage fields
Value(T),
}
/// Type marker for the uninitialized field of the overseer builder.
/// `PhantomData` is used for type hinting when creating uninitialized
/// builder, e.g. to avoid specifying the generics when instantiating
/// the `FooBuilder` when calling `Foo::builder()`
#[derive(Debug)]
pub struct Missing<T>(::core::marker::PhantomData<T>);
/// Trait used to mark fields status in a builder
trait OverseerFieldState<T> {}
impl<T> OverseerFieldState<T> for Init<T> {}
impl<T> OverseerFieldState<T> for Missing<T> {}
impl<T> ::std::default::Default for Missing<T> {
fn default() -> Self {
Missing::<T>(::core::marker::PhantomData::<T>::default())
}
}
impl<S, #( #baggage_generic_ty, )*> #overseer_name <S, #( #baggage_generic_ty, )*> where #spawner_where_clause {
/// Create a new overseer utilizing the builder.
pub fn builder< #( #subsystem_generics),* >() ->
#builder<Missing<S> #(, Missing<#field_type> )* >
where
#(
#subsystem_generics : Subsystem<#subsystem_ctx_name< #consumes >, #error_ty>,
)*
{
#builder :: new()
}
}
};
ts.extend(quote! {
/// Handle for an overseer.
pub type #handle = #support_crate ::metered::MeteredSender< #event >;
@@ -192,39 +373,26 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
}
}
}
});
/// Convenience alias.
type SubsystemInitFn<T> = Box<dyn FnOnce(#handle) -> ::std::result::Result<T, #error_ty> >;
/// Initialization type to be used for a field of the overseer.
enum FieldInitMethod<T> {
/// Defer initialization to a point where the `handle` is available.
Fn(SubsystemInitFn<T>),
/// Directly initialize the subsystem with the given subsystem type `T`.
Value(T),
/// Subsystem field does not have a value just yet.
Uninitialized
}
impl<T> ::std::default::Default for FieldInitMethod<T> {
fn default() -> Self {
Self::Uninitialized
}
}
#[allow(missing_docs)]
pub struct #builder #builder_generics {
ts.extend(quote!{
/// Builder pattern to create compile time safe construction path.
pub struct #builder <InitStateSpawner, #( #subsystem_passthrough_state_generics, )* #( #baggage_passthrough_state_generics, )*> {
#(
#subsystem_name : FieldInitMethod< #builder_generic_ty >,
#subsystem_name: #subsystem_passthrough_state_generics,
)*
#(
#baggage_name : ::std::option::Option< #baggage_ty >,
#baggage_name: #baggage_passthrough_state_generics,
)*
spawner: ::std::option::Option< S >,
spawner: InitStateSpawner,
}
});
impl #builder_generics Default for #builder #builder_generics {
fn default() -> Self {
ts.extend(quote! {
impl<#initialized_builder_generics> #builder<Missing<S>, #( Missing<#field_type>, )*>
{
/// Create a new builder pattern, with all fields being uninitialized.
fn new() -> Self {
// explicitly assure the required traits are implemented
fn trait_from_must_be_implemented<E>()
where
@@ -234,62 +402,57 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
trait_from_must_be_implemented::< #error_ty >();
Self {
#(
#subsystem_name: Default::default(),
)*
#(
#baggage_name: None,
)*
spawner: None,
#(
#field_name: Missing::<#field_type>::default(),
)*
spawner: Missing::<S>::default(),
}
}
}
});
impl #builder_generics #builder #builder_generics #builder_where_clause {
/// The spawner to use for spawning tasks.
pub fn spawner(mut self, spawner: S) -> Self
where
S: #support_crate ::SpawnNamed + Send
// Spawner setter
ts.extend(quote!{
impl<S, #( #subsystem_passthrough_state_generics, )* #( #baggage_passthrough_state_generics, )*>
#builder<Missing<S>, #( #subsystem_passthrough_state_generics, )* #( #baggage_passthrough_state_generics, )*>
where
#spawner_where_clause
{
/// The `spawner` to use for spawning tasks.
pub fn spawner(self, spawner: S) -> #builder<Init<S>, #( #subsystem_passthrough_state_generics, )* #( #baggage_passthrough_state_generics, )*>
{
self.spawner = Some(spawner);
self
#builder {
#(
#field_name: self. #field_name,
)*
spawner: Init::<S>::Value(spawner),
}
}
}
});
ts.extend(quote! {
/// Type used to represent a builder where all fields are initialized and the overseer could be constructed.
pub type #initialized_builder<#initialized_builder_generics> = #builder<Init<S>, #( Init<#field_type>, )*>;
// A builder specialization where all fields are set
impl<#initialized_builder_generics> #initialized_builder<#initialized_builder_generics>
where
#spawner_where_clause,
#(
/// Specify the particular subsystem implementation.
pub fn #subsystem_name (mut self, subsystem: #builder_generic_ty ) -> Self {
self. #subsystem_name = FieldInitMethod::Value( subsystem );
self
}
/// Specify the particular subsystem by giving a init function.
pub fn #subsystem_name_init_with <'a, F> (mut self, subsystem_init_fn: F ) -> Self
where
F: 'static + FnOnce(#handle) -> ::std::result::Result<#builder_generic_ty, #error_ty>,
{
self. #subsystem_name = FieldInitMethod::Fn(
Box::new(subsystem_init_fn) as SubsystemInitFn<#builder_generic_ty>
);
self
}
#subsystem_generics : Subsystem<#subsystem_ctx_name< #consumes >, #error_ty>,
)*
#(
/// Attach the user defined addendum type.
pub fn #baggage_name (mut self, baggage: #baggage_ty ) -> Self {
self. #baggage_name = Some( baggage );
self
}
)*
{
/// Complete the construction and create the overseer type.
pub fn build(self) -> ::std::result::Result<(#overseer_name #generics, #handle), #error_ty> {
pub fn build(self)
-> ::std::result::Result<(#overseer_name<S, #( #baggage_generic_ty, )*>, #handle), #error_ty> {
let connector = #connector ::default();
self.build_with_connector(connector)
}
/// Complete the construction and create the overseer type based on an existing `connector`.
pub fn build_with_connector(self, connector: #connector) -> ::std::result::Result<(#overseer_name #generics, #handle), #error_ty>
pub fn build_with_connector(self, connector: #connector)
-> ::std::result::Result<(#overseer_name<S, #( #baggage_generic_ty, )*>, #handle), #error_ty>
{
let #connector {
handle: events_tx,
@@ -327,20 +490,19 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
)*
};
let mut spawner = self.spawner.expect("Spawner is set. qed");
let mut spawner = match self.spawner {
Init::Value(value) => value,
_ => unreachable!("Only ever init spawner as value. qed"),
};
let mut running_subsystems = #support_crate ::FuturesUnordered::<
BoxFuture<'static, ::std::result::Result<(), #error_ty > >
>::new();
#(
// TODO generate a builder pattern that ensures this
// TODO https://github.com/paritytech/polkadot/issues/3427
let #subsystem_name = match self. #subsystem_name {
FieldInitMethod::Fn(func) => func(handle.clone())?,
FieldInitMethod::Value(val) => val,
FieldInitMethod::Uninitialized =>
panic!("All subsystems must exist with the builder pattern."),
Init::Fn(func) => func(handle.clone())?,
Init::Value(val) => val,
};
let unbounded_meter = #channel_name_unbounded_rx.meter().clone();
@@ -351,11 +513,11 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
let (signal_tx, signal_rx) = #support_crate ::metered::channel(SIGNAL_CHANNEL_CAPACITY);
// Generate subsystem name based on overseer field name.
let mut subsystem_string = String::from(stringify!(#subsystem_name));
let subsystem_string = String::from(stringify!(#subsystem_name));
// Convert owned `snake case` string to a `kebab case` static str.
let subsystem_static_str = Box::leak(subsystem_string.replace("_", "-").into_boxed_str());
let ctx = #subsyste_ctx_name::< #consumes >::new(
let ctx = #subsystem_ctx_name::< #consumes >::new(
signal_rx,
message_rx,
channels_out.clone(),
@@ -376,15 +538,6 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
)?;
)*
#(
let #baggage_name = self. #baggage_name .expect(
&format!("Baggage variable `{0}` of `{1}` must be set by the user!",
stringify!(#baggage_name),
stringify!(#overseer_name)
)
);
)*
use #support_crate ::StreamExt;
let to_overseer_rx = to_overseer_rx.fuse();
@@ -394,7 +547,10 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
)*
#(
#baggage_name,
#baggage_name: match self. #baggage_name {
Init::Value(val) => val,
_ => panic!("unexpected baggage initialization, must be value"),
},
)*
spawner,
@@ -406,84 +562,10 @@ pub(crate) fn impl_builder(info: &OverseerInfo) -> proc_macro2::TokenStream {
Ok((overseer, handle))
}
}
};
let mut acc = TokenStream::new();
for (
(
(
ref modified_generics,
ref to_be_replaced_ty,
ref to_be_replaced_name,
ref to_keep_name,
),
subsystem_name_replace_with,
),
consumes,
) in derive_replacable_generic_lists(info)
.into_iter()
.zip(subsystem_name_replace_with.iter())
.zip(consumes.iter())
{
let replace1 = quote! {
/// Replace a subsystem by another implementation for the
/// consumable message type.
pub fn #subsystem_name_replace_with < NEW, F >
(self, gen_replacement_fn: F) -> #builder #modified_generics
where
#to_be_replaced_ty: 'static,
F: 'static + FnOnce(#to_be_replaced_ty) -> NEW,
NEW: #support_crate ::Subsystem<#subsystem_ctx_name< #consumes >, #error_ty>,
{
let Self {
#to_be_replaced_name,
#(
#to_keep_name,
)*
#(
#baggage_name,
)*
spawner,
} = self;
// Some cases require that parts of the original are copied
// over, since they include a one time initialization.
let replacement: FieldInitMethod<NEW> = match #to_be_replaced_name {
FieldInitMethod::Fn(fx) => FieldInitMethod::Fn(
Box::new(move |handle: #handle| {
let orig = fx(handle)?;
Ok(gen_replacement_fn(orig))
})
),
FieldInitMethod::Value(val) => FieldInitMethod::Value(gen_replacement_fn(val)),
FieldInitMethod::Uninitialized => panic!("Must have a value before it can be replaced. qed"),
};
#builder :: #modified_generics {
#to_be_replaced_name: replacement,
#(
#to_keep_name,
)*
#(
#baggage_name,
)*
spawner,
}
}
};
acc.extend(replace1);
}
ts.extend(quote! {
impl #builder_generics #builder #builder_generics
#builder_where_clause
{
#acc
}
});
ts.extend(baggage_specific_setters);
ts.extend(subsystem_specific_setters);
ts.extend(impl_task_kind(info));
ts
}
@@ -264,12 +264,21 @@ impl OverseerInfo {
.collect::<Vec<_>>()
}
pub(crate) fn subsystem_generic_types(&self) -> Vec<Ident> {
self.subsystems
.iter()
.filter(|ssf| !ssf.wip)
.map(|sff| sff.generic.clone())
.collect::<Vec<_>>()
}
pub(crate) fn baggage(&self) -> &[BaggageField] {
self.baggage.as_slice()
}
pub(crate) fn baggage_names(&self) -> Vec<Ident> {
self.baggage.iter().map(|bag| bag.field_name.clone()).collect::<Vec<_>>()
}
pub(crate) fn baggage_types(&self) -> Vec<Path> {
self.baggage.iter().map(|bag| bag.field_ty.clone()).collect::<Vec<_>>()
}
pub(crate) fn baggage_decl(&self) -> Vec<TokenStream> {
self.baggage
.iter()
@@ -280,15 +289,6 @@ impl OverseerInfo {
.collect::<Vec<TokenStream>>()
}
/// Generic types per subsystem, as defined by the user.
pub(crate) fn builder_generic_types(&self) -> Vec<Ident> {
self.subsystems
.iter()
.filter(|ssf| !ssf.wip)
.map(|sff| sff.generic.clone())
.collect::<Vec<_>>()
}
pub(crate) fn baggage_generic_types(&self) -> Vec<Ident> {
self.baggage
.iter()
@@ -7,3 +7,9 @@ fn ui_compile_fail() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/err-*.rs");
}
#[test]
fn ui_pass() {
let t = trybuild::TestCases::new();
t.pass("tests/ui/ok-*.rs");
}
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `std::convert::From<MsgStrukt>` for type `AllMessages`
--> $DIR/err-01-duplicate-consumer.rs:19:1
--> tests/ui/err-01-duplicate-consumer.rs:19:1
|
19 | #[overlord(signal=SigSigSig, event=Event, gen=AllMessages, error=OverseerError)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -10,7 +10,7 @@ error[E0119]: conflicting implementations of trait `std::convert::From<MsgStrukt
= note: this error originates in the attribute macro `overlord` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0119]: conflicting implementations of trait `polkadot_overseer_gen::SubsystemSender<MsgStrukt>` for type `OverseerSubsystemSender`
--> $DIR/err-01-duplicate-consumer.rs:19:1
--> tests/ui/err-01-duplicate-consumer.rs:19:1
|
19 | #[overlord(signal=SigSigSig, event=Event, gen=AllMessages, error=OverseerError)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -0,0 +1,61 @@
#![allow(dead_code)]
use polkadot_overseer_gen::*;
#[derive(Default)]
struct AwesomeSubSys;
impl ::polkadot_overseer_gen::Subsystem<OverseerSubsystemContext<MsgStrukt>, OverseerError> for AwesomeSubSys {
fn start(self, _ctx: OverseerSubsystemContext<MsgStrukt>) -> SpawnedSubsystem<OverseerError> {
unimplemented!("starting yay!")
}
}
#[derive(Clone, Debug)]
pub struct SigSigSig;
pub struct Event;
#[derive(Clone, Debug)]
pub struct MsgStrukt(u8);
#[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
struct Overseer {
#[subsystem(no_dispatch, MsgStrukt)]
sub0: AwesomeSubSys,
i_like_pie: f64,
}
#[derive(Debug, Clone)]
pub struct DummySpawner;
impl SpawnNamed for DummySpawner {
fn spawn_blocking(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn blocking {} {}", task_name, subsystem_name.unwrap_or("default"))
}
fn spawn(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn {} {}", task_name, subsystem_name.unwrap_or("default"))
}
}
struct DummyCtx;
fn main() {
let _ = Overseer::builder()
.sub0(AwesomeSubSys::default())
//.i_like_pie(std::f64::consts::PI) // The filed is not initialised
.spawner(DummySpawner)
.build()
.unwrap();
}
@@ -0,0 +1,15 @@
error[E0599]: no method named `build` found for struct `OverseerBuilder<Init<DummySpawner>, Init<AwesomeSubSys>, Missing<f64>>` in the current scope
--> tests/ui/err-05-missing-field.rs:59:4
|
22 | #[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
| -------------------------------------------------------------------------------- method `build` not found for this
...
59 | .build()
| ^^^^^ method not found in `OverseerBuilder<Init<DummySpawner>, Init<AwesomeSubSys>, Missing<f64>>`
|
= note: the method was found for
- `OverseerBuilder<Init<S>, Init<AwesomeSubSys>, Init<f64>>`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `build`, perhaps you need to implement one of them:
candidate #1: `frame_support::traits::hooks::GenesisBuild`
candidate #2: `prometheus::vec::MetricVecBuilder`
@@ -0,0 +1,61 @@
#![allow(dead_code)]
use polkadot_overseer_gen::*;
#[derive(Default)]
struct AwesomeSubSys;
impl ::polkadot_overseer_gen::Subsystem<OverseerSubsystemContext<MsgStrukt>, OverseerError> for AwesomeSubSys {
fn start(self, _ctx: OverseerSubsystemContext<MsgStrukt>) -> SpawnedSubsystem<OverseerError> {
unimplemented!("starting yay!")
}
}
#[derive(Clone, Debug)]
pub struct SigSigSig;
pub struct Event;
#[derive(Clone, Debug)]
pub struct MsgStrukt(u8);
#[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
struct Overseer {
#[subsystem(no_dispatch, MsgStrukt)]
sub0: AwesomeSubSys,
i_like_pie: f64,
}
#[derive(Debug, Clone)]
pub struct DummySpawner;
impl SpawnNamed for DummySpawner {
fn spawn_blocking(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn blocking {} {}", task_name, subsystem_name.unwrap_or("default"))
}
fn spawn(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn {} {}", task_name, subsystem_name.unwrap_or("default"))
}
}
struct DummyCtx;
fn main() {
let _ = Overseer::builder()
//.sub0(AwesomeSubSys::default()) // Subsystem is uninitialized
.i_like_pie(std::f64::consts::PI)
.spawner(DummySpawner)
.build()
.unwrap();
}
@@ -0,0 +1,15 @@
error[E0599]: no method named `build` found for struct `OverseerBuilder<Init<DummySpawner>, Missing<_>, Init<f64>>` in the current scope
--> tests/ui/err-06-missing-subsystem.rs:59:4
|
22 | #[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
| -------------------------------------------------------------------------------- method `build` not found for this
...
59 | .build()
| ^^^^^ method not found in `OverseerBuilder<Init<DummySpawner>, Missing<_>, Init<f64>>`
|
= note: the method was found for
- `OverseerBuilder<Init<S>, Init<AwesomeSubSys>, Init<f64>>`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `build`, perhaps you need to implement one of them:
candidate #1: `frame_support::traits::hooks::GenesisBuild`
candidate #2: `prometheus::vec::MetricVecBuilder`
@@ -0,0 +1,61 @@
#![allow(dead_code)]
use polkadot_overseer_gen::*;
#[derive(Default)]
struct AwesomeSubSys;
impl ::polkadot_overseer_gen::Subsystem<OverseerSubsystemContext<MsgStrukt>, OverseerError> for AwesomeSubSys {
fn start(self, _ctx: OverseerSubsystemContext<MsgStrukt>) -> SpawnedSubsystem<OverseerError> {
unimplemented!("starting yay!")
}
}
#[derive(Clone, Debug)]
pub struct SigSigSig;
pub struct Event;
#[derive(Clone, Debug)]
pub struct MsgStrukt(u8);
#[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
struct Overseer {
#[subsystem(no_dispatch, MsgStrukt)]
sub0: AwesomeSubSys,
i_like_pie: f64,
}
#[derive(Debug, Clone)]
pub struct DummySpawner;
impl SpawnNamed for DummySpawner {
fn spawn_blocking(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn blocking {} {}", task_name, subsystem_name.unwrap_or("default"))
}
fn spawn(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn {} {}", task_name, subsystem_name.unwrap_or("default"))
}
}
struct DummyCtx;
fn main() {
let _ = Overseer::builder()
.sub0(AwesomeSubSys::default())
.i_like_pie(std::f64::consts::PI)
//.spawner(DummySpawner) // Spawner is missing
.build()
.unwrap();
}
@@ -0,0 +1,15 @@
error[E0599]: no method named `build` found for struct `OverseerBuilder<Missing<_>, Init<AwesomeSubSys>, Init<f64>>` in the current scope
--> tests/ui/err-07-missing-spawner.rs:59:4
|
22 | #[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
| -------------------------------------------------------------------------------- method `build` not found for this
...
59 | .build()
| ^^^^^ method not found in `OverseerBuilder<Missing<_>, Init<AwesomeSubSys>, Init<f64>>`
|
= note: the method was found for
- `OverseerBuilder<Init<S>, Init<AwesomeSubSys>, Init<f64>>`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `build`, perhaps you need to implement one of them:
candidate #1: `frame_support::traits::hooks::GenesisBuild`
candidate #2: `prometheus::vec::MetricVecBuilder`
@@ -0,0 +1,62 @@
#![allow(dead_code)]
use polkadot_overseer_gen::*;
#[derive(Default)]
struct AwesomeSubSys;
impl ::polkadot_overseer_gen::Subsystem<OverseerSubsystemContext<MsgStrukt>, OverseerError> for AwesomeSubSys {
fn start(self, _ctx: OverseerSubsystemContext<MsgStrukt>) -> SpawnedSubsystem<OverseerError> {
unimplemented!("starting yay!")
}
}
#[derive(Clone, Debug)]
pub struct SigSigSig;
pub struct Event;
#[derive(Clone, Debug)]
pub struct MsgStrukt(u8);
#[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
struct Overseer {
#[subsystem(no_dispatch, MsgStrukt)]
sub0: AwesomeSubSys,
i_like_pie: f64,
}
#[derive(Debug, Clone)]
pub struct DummySpawner;
impl SpawnNamed for DummySpawner {
fn spawn_blocking(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn blocking {} {}", task_name, subsystem_name.unwrap_or("default"))
}
fn spawn(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn {} {}", task_name, subsystem_name.unwrap_or("default"))
}
}
struct DummyCtx;
fn main() {
let _ = Overseer::builder()
.sub0(AwesomeSubSys::default())
.sub0(AwesomeSubSys::default()) // Duplicate subsystem
.i_like_pie(std::f64::consts::PI)
.spawner(DummySpawner)
.build()
.unwrap();
}
@@ -0,0 +1,10 @@
error[E0599]: no method named `sub0` found for struct `OverseerBuilder<Missing<_>, Init<AwesomeSubSys>, Missing<f64>>` in the current scope
--> tests/ui/err-08-duplicate-subsystem.rs:57:4
|
22 | #[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
| -------------------------------------------------------------------------------- method `sub0` not found for this
...
57 | .sub0(AwesomeSubSys::default()) // Duplicate subsystem
| ^^^^-------------------------- help: remove the arguments
| |
| field, not a method
@@ -0,0 +1,61 @@
#![allow(dead_code)]
use polkadot_overseer_gen::*;
#[derive(Default)]
struct AwesomeSubSys;
impl ::polkadot_overseer_gen::Subsystem<OverseerSubsystemContext<MsgStrukt>, OverseerError> for AwesomeSubSys {
fn start(self, _ctx: OverseerSubsystemContext<MsgStrukt>) -> SpawnedSubsystem<OverseerError> {
unimplemented!("starting yay!")
}
}
#[derive(Clone, Debug)]
pub struct SigSigSig;
pub struct Event;
#[derive(Clone, Debug)]
pub struct MsgStrukt(u8);
#[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
struct Overseer<T> {
#[subsystem(no_dispatch, MsgStrukt)]
sub0: AwesomeSubSys,
i_like_pie: T,
}
#[derive(Debug, Clone)]
pub struct DummySpawner;
impl SpawnNamed for DummySpawner {
fn spawn_blocking(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn blocking {} {}", task_name, subsystem_name.unwrap_or("default"))
}
fn spawn(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
unimplemented!("spawn {} {}", task_name, subsystem_name.unwrap_or("default"))
}
}
struct DummyCtx;
fn main() {
let (_, _): (Overseer<_, f64>, _) = Overseer::builder()
.sub0(AwesomeSubSys::default())
//.i_like_pie(std::f64::consts::PI) // The filed is not initialised
.spawner(DummySpawner)
.build()
.unwrap();
}
@@ -0,0 +1,15 @@
error[E0599]: no method named `build` found for struct `OverseerBuilder<Init<DummySpawner>, Init<AwesomeSubSys>, Missing<_>>` in the current scope
--> tests/ui/err-09-uninit_generic_baggage.rs:59:4
|
22 | #[overlord(signal=SigSigSig, error=OverseerError, event=Event, gen=AllMessages)]
| -------------------------------------------------------------------------------- method `build` not found for this
...
59 | .build()
| ^^^^^ method not found in `OverseerBuilder<Init<DummySpawner>, Init<AwesomeSubSys>, Missing<_>>`
|
= note: the method was found for
- `OverseerBuilder<Init<S>, Init<AwesomeSubSys>, Init<T>>`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `build`, perhaps you need to implement one of them:
candidate #1: `frame_support::traits::hooks::GenesisBuild`
candidate #2: `prometheus::vec::MetricVecBuilder`
@@ -0,0 +1,75 @@
#![allow(dead_code)]
use polkadot_overseer_gen::*;
#[derive(Default)]
struct AwesomeSubSysA;
impl ::polkadot_overseer_gen::Subsystem<OverseerSubsystemContext<MsgA>, OverseerError> for AwesomeSubSysA {
fn start(self, _ctx: OverseerSubsystemContext<MsgA>) -> SpawnedSubsystem<OverseerError> {
SpawnedSubsystem { name: "sub A", future: Box::pin(async move { Ok(()) }) }
}
}
impl ::polkadot_overseer_gen::Subsystem<OverseerSubsystemContext<MsgB>, OverseerError> for AwesomeSubSysB {
fn start(self, _ctx: OverseerSubsystemContext<MsgB>) -> SpawnedSubsystem<OverseerError> {
SpawnedSubsystem { name: "sub B", future: Box::pin(async move { Ok(()) }) }
}
}
#[derive(Debug, Clone)]
pub struct DummySpawner;
impl SpawnNamed for DummySpawner {
fn spawn_blocking(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
println!("spawn blocking {} {}", task_name, subsystem_name.unwrap_or("default"))
}
fn spawn(
&self,
task_name: &'static str,
subsystem_name: Option<&'static str>,
_future: futures::future::BoxFuture<'static, ()>,
) {
println!("spawn {} {}", task_name, subsystem_name.unwrap_or("default"))
}
}
#[derive(Default)]
struct AwesomeSubSysB;
#[derive(Clone, Debug)]
pub struct SigSigSig;
pub struct Event;
#[derive(Clone, Debug)]
pub struct MsgA(u8);
#[derive(Clone, Debug)]
pub struct MsgB(u8);
#[overlord(signal=SigSigSig, event=Event, gen=AllMessages, error=OverseerError)]
pub struct Overseer {
#[subsystem(MsgA)]
sub_a: AwesomeSubSysA,
#[subsystem(wip, MsgB)]
sub_b: AwesomeSubSysB,
}
pub struct DummyCtx;
fn main() {
let _overseer_builder = Overseer::builder()
.sub_a(AwesomeSubSysA::default())
// b is tagged as `wip`
// .sub_b(AwesomeSubSysB::default())
.spawner(DummySpawner)
.build();
}
+4 -4
View File
@@ -15,8 +15,8 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use crate::{
prometheus::Registry, AllMessages, HeadSupportsParachains, MetricsTrait, Overseer,
OverseerBuilder, OverseerMetrics, OverseerSignal, OverseerSubsystemContext, SpawnNamed,
prometheus::Registry, AllMessages, HeadSupportsParachains, InitializedOverseerBuilder,
MetricsTrait, Overseer, OverseerMetrics, OverseerSignal, OverseerSubsystemContext, SpawnNamed,
KNOWN_LEAVES_CACHE_SIZE,
};
use lru::LruCache;
@@ -66,7 +66,7 @@ pub fn dummy_overseer_builder<'a, Spawner, SupportsParachains>(
supports_parachains: SupportsParachains,
registry: Option<&'a Registry>,
) -> Result<
OverseerBuilder<
InitializedOverseerBuilder<
Spawner,
SupportsParachains,
DummySubsystem,
@@ -107,7 +107,7 @@ pub fn one_for_all_overseer_builder<'a, Spawner, SupportsParachains, Sub>(
subsystem: Sub,
registry: Option<&'a Registry>,
) -> Result<
OverseerBuilder<
InitializedOverseerBuilder<
Spawner,
SupportsParachains,
Sub,
+3 -3
View File
@@ -30,8 +30,8 @@ pub use polkadot_overseer::{
HeadSupportsParachains,
};
use polkadot_overseer::{
metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, OverseerBuilder,
OverseerConnector, OverseerHandle,
metrics::Metrics as OverseerMetrics, BlockInfo, InitializedOverseerBuilder, MetricsTrait,
Overseer, OverseerConnector, OverseerHandle,
};
use polkadot_primitives::v2::ParachainHost;
@@ -142,7 +142,7 @@ pub fn prepared_overseer_builder<'a, Spawner, RuntimeClient>(
pvf_checker_enabled,
}: OverseerGenArgs<'a, Spawner, RuntimeClient>,
) -> Result<
OverseerBuilder<
InitializedOverseerBuilder<
Spawner,
Arc<RuntimeClient>,
CandidateValidationSubsystem,