mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-08 06:37:23 +00:00
b0f89bbfbc
* SubsystemContext: add subsystem name str Signed-off-by: Andrei Sandu <sandu.andrei@gmail.com> * Overseer builder proc macro changes * initilize SubsystemContext name field. * Add subsystem name in TaskKind::launch_task() Signed-off-by: Andrei Sandu <sandu.andrei@gmail.com> * Update ToOverseer enum Signed-off-by: Andrei Sandu <sandu.andrei@gmail.com> * Assign subsystem names to orphan tasks Signed-off-by: Andrei Sandu <sandu.andrei@gmail.com> * cargo fmt Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * SubsystemContext: add subsystem name str Signed-off-by: Andrei Sandu <sandu.andrei@gmail.com> * Overseer builder proc macro changes * initilize SubsystemContext name field. * Add subsystem name in TaskKind::launch_task() Signed-off-by: Andrei Sandu <sandu.andrei@gmail.com> * Update ToOverseer enum Signed-off-by: Andrei Sandu <sandu.andrei@gmail.com> * Assign subsystem names to orphan tasks Signed-off-by: Andrei Sandu <sandu.andrei@gmail.com> * cargo fmt Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Rebase changes for new spawn() group param Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Add subsystem constat in JobTrait Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Add subsystem string Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Fix tests Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Fix spawn() calls Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * cargo fmt Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Fix Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Fix tests Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * fix Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Fix more tests Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Address PR review feedback #1 Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Address PR review round 2 Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * Fixes - remove JobTrait::Subsystem - fix tests Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> * update Cargo.lock Co-authored-by: Andronik Ordian <write@reusable.software>
260 lines
8.5 KiB
Rust
260 lines
8.5 KiB
Rust
// Copyright 2021 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/>.
|
|
|
|
use quote::quote;
|
|
use syn::Ident;
|
|
|
|
use super::*;
|
|
|
|
/// Implement a builder pattern for the `Overseer`-type,
|
|
/// which acts as the gateway to constructing the overseer.
|
|
pub(crate) fn impl_misc(info: &OverseerInfo) -> proc_macro2::TokenStream {
|
|
let overseer_name = info.overseer_name.clone();
|
|
let subsystem_sender_name =
|
|
Ident::new(&(overseer_name.to_string() + "SubsystemSender"), overseer_name.span());
|
|
let subsystem_ctx_name =
|
|
Ident::new(&(overseer_name.to_string() + "SubsystemContext"), overseer_name.span());
|
|
let consumes = &info.consumes();
|
|
let signal = &info.extern_signal_ty;
|
|
let wrapper_message = &info.message_wrapper;
|
|
let error_ty = &info.extern_error_ty;
|
|
let support_crate = info.support_crate_name();
|
|
|
|
let ts = quote! {
|
|
/// Connector to send messages towards all subsystems,
|
|
/// while tracking the which signals where already received.
|
|
#[derive(Debug, Clone)]
|
|
pub struct #subsystem_sender_name {
|
|
/// Collection of channels to all subsystems.
|
|
channels: ChannelsOut,
|
|
/// Systemwide tick for which signals were received by all subsystems.
|
|
signals_received: SignalsReceived,
|
|
}
|
|
|
|
/// implementation for wrapping message type...
|
|
#[#support_crate ::async_trait]
|
|
impl SubsystemSender< #wrapper_message > for #subsystem_sender_name {
|
|
async fn send_message(&mut self, msg: #wrapper_message) {
|
|
self.channels.send_and_log_error(self.signals_received.load(), msg).await;
|
|
}
|
|
|
|
async fn send_messages<T>(&mut self, msgs: T)
|
|
where
|
|
T: IntoIterator<Item = #wrapper_message> + Send,
|
|
T::IntoIter: Send,
|
|
{
|
|
// This can definitely be optimized if necessary.
|
|
for msg in msgs {
|
|
self.send_message(msg).await;
|
|
}
|
|
}
|
|
|
|
fn send_unbounded_message(&mut self, msg: #wrapper_message) {
|
|
self.channels.send_unbounded_and_log_error(self.signals_received.load(), msg);
|
|
}
|
|
}
|
|
|
|
// ... but also implement for all individual messages to avoid
|
|
// the necessity for manual wrapping, and do the conversion
|
|
// based on the generated `From::from` impl for the individual variants.
|
|
#(
|
|
#[#support_crate ::async_trait]
|
|
impl SubsystemSender< #consumes > for #subsystem_sender_name {
|
|
async fn send_message(&mut self, msg: #consumes) {
|
|
self.channels.send_and_log_error(self.signals_received.load(), #wrapper_message ::from ( msg )).await;
|
|
}
|
|
|
|
async fn send_messages<T>(&mut self, msgs: T)
|
|
where
|
|
T: IntoIterator<Item = #consumes> + Send,
|
|
T::IntoIter: Send,
|
|
{
|
|
// This can definitely be optimized if necessary.
|
|
for msg in msgs {
|
|
self.send_message(msg).await;
|
|
}
|
|
}
|
|
|
|
fn send_unbounded_message(&mut self, msg: #consumes) {
|
|
self.channels.send_unbounded_and_log_error(self.signals_received.load(), #wrapper_message ::from ( msg ));
|
|
}
|
|
}
|
|
)*
|
|
|
|
/// A context type that is given to the [`Subsystem`] upon spawning.
|
|
/// It can be used by [`Subsystem`] to communicate with other [`Subsystem`]s
|
|
/// or to spawn it's [`SubsystemJob`]s.
|
|
///
|
|
/// [`Overseer`]: struct.Overseer.html
|
|
/// [`Subsystem`]: trait.Subsystem.html
|
|
/// [`SubsystemJob`]: trait.SubsystemJob.html
|
|
#[derive(Debug)]
|
|
#[allow(missing_docs)]
|
|
pub struct #subsystem_ctx_name<M>{
|
|
signals: #support_crate ::metered::MeteredReceiver< #signal >,
|
|
messages: SubsystemIncomingMessages<M>,
|
|
to_subsystems: #subsystem_sender_name,
|
|
to_overseer: #support_crate ::metered::UnboundedMeteredSender<
|
|
#support_crate ::ToOverseer
|
|
>,
|
|
signals_received: SignalsReceived,
|
|
pending_incoming: Option<(usize, M)>,
|
|
name: &'static str
|
|
}
|
|
|
|
impl<M> #subsystem_ctx_name<M> {
|
|
/// Create a new context.
|
|
fn new(
|
|
signals: #support_crate ::metered::MeteredReceiver< #signal >,
|
|
messages: SubsystemIncomingMessages<M>,
|
|
to_subsystems: ChannelsOut,
|
|
to_overseer: #support_crate ::metered::UnboundedMeteredSender<#support_crate:: ToOverseer>,
|
|
name: &'static str
|
|
) -> Self {
|
|
let signals_received = SignalsReceived::default();
|
|
#subsystem_ctx_name {
|
|
signals,
|
|
messages,
|
|
to_subsystems: #subsystem_sender_name {
|
|
channels: to_subsystems,
|
|
signals_received: signals_received.clone(),
|
|
},
|
|
to_overseer,
|
|
signals_received,
|
|
pending_incoming: None,
|
|
name
|
|
}
|
|
}
|
|
|
|
fn name(&self) -> &'static str {
|
|
self.name
|
|
}
|
|
}
|
|
|
|
#[#support_crate ::async_trait]
|
|
impl<M: std::fmt::Debug + Send + 'static> #support_crate ::SubsystemContext for #subsystem_ctx_name<M>
|
|
where
|
|
#subsystem_sender_name: #support_crate ::SubsystemSender< #wrapper_message >,
|
|
#wrapper_message: From<M>,
|
|
{
|
|
type Message = M;
|
|
type Signal = #signal;
|
|
type Sender = #subsystem_sender_name;
|
|
type AllMessages = #wrapper_message;
|
|
type Error = #error_ty;
|
|
|
|
async fn try_recv(&mut self) -> ::std::result::Result<Option<FromOverseer<M, #signal>>, ()> {
|
|
match #support_crate ::poll!(self.recv()) {
|
|
#support_crate ::Poll::Ready(msg) => Ok(Some(msg.map_err(|_| ())?)),
|
|
#support_crate ::Poll::Pending => Ok(None),
|
|
}
|
|
}
|
|
|
|
async fn recv(&mut self) -> ::std::result::Result<FromOverseer<M, #signal>, #error_ty> {
|
|
loop {
|
|
// If we have a message pending an overseer signal, we only poll for signals
|
|
// in the meantime.
|
|
if let Some((needs_signals_received, msg)) = self.pending_incoming.take() {
|
|
if needs_signals_received <= self.signals_received.load() {
|
|
return Ok(#support_crate ::FromOverseer::Communication { msg });
|
|
} else {
|
|
self.pending_incoming = Some((needs_signals_received, msg));
|
|
|
|
// wait for next signal.
|
|
let signal = self.signals.next().await
|
|
.ok_or(#support_crate ::OverseerError::Context(
|
|
"Signal channel is terminated and empty."
|
|
.to_owned()
|
|
))?;
|
|
|
|
self.signals_received.inc();
|
|
return Ok(#support_crate ::FromOverseer::Signal(signal))
|
|
}
|
|
}
|
|
|
|
let mut await_message = self.messages.next().fuse();
|
|
let mut await_signal = self.signals.next().fuse();
|
|
let signals_received = self.signals_received.load();
|
|
let pending_incoming = &mut self.pending_incoming;
|
|
|
|
// Otherwise, wait for the next signal or incoming message.
|
|
let from_overseer = #support_crate ::futures::select_biased! {
|
|
signal = await_signal => {
|
|
let signal = signal
|
|
.ok_or(#support_crate ::OverseerError::Context(
|
|
"Signal channel is terminated and empty."
|
|
.to_owned()
|
|
))?;
|
|
|
|
#support_crate ::FromOverseer::Signal(signal)
|
|
}
|
|
msg = await_message => {
|
|
let packet = msg
|
|
.ok_or(#support_crate ::OverseerError::Context(
|
|
"Message channel is terminated and empty."
|
|
.to_owned()
|
|
))?;
|
|
|
|
if packet.signals_received > signals_received {
|
|
// wait until we've received enough signals to return this message.
|
|
*pending_incoming = Some((packet.signals_received, packet.message));
|
|
continue;
|
|
} else {
|
|
// we know enough to return this message.
|
|
#support_crate ::FromOverseer::Communication { msg: packet.message}
|
|
}
|
|
}
|
|
};
|
|
|
|
if let #support_crate ::FromOverseer::Signal(_) = from_overseer {
|
|
self.signals_received.inc();
|
|
}
|
|
|
|
return Ok(from_overseer);
|
|
}
|
|
}
|
|
|
|
fn sender(&mut self) -> &mut Self::Sender {
|
|
&mut self.to_subsystems
|
|
}
|
|
|
|
fn spawn(&mut self, name: &'static str, s: Pin<Box<dyn Future<Output = ()> + Send>>)
|
|
-> ::std::result::Result<(), #error_ty>
|
|
{
|
|
self.to_overseer.unbounded_send(#support_crate ::ToOverseer::SpawnJob {
|
|
name,
|
|
subsystem: Some(self.name()),
|
|
s,
|
|
}).map_err(|_| #support_crate ::OverseerError::TaskSpawn(name))?;
|
|
Ok(())
|
|
}
|
|
|
|
fn spawn_blocking(&mut self, name: &'static str, s: Pin<Box<dyn Future<Output = ()> + Send>>)
|
|
-> ::std::result::Result<(), #error_ty>
|
|
{
|
|
self.to_overseer.unbounded_send(#support_crate ::ToOverseer::SpawnBlockingJob {
|
|
name,
|
|
subsystem: Some(self.name()),
|
|
s,
|
|
}).map_err(|_| #support_crate ::OverseerError::TaskSpawn(name))?;
|
|
Ok(())
|
|
}
|
|
}
|
|
};
|
|
|
|
ts
|
|
}
|