Simplify subsystem jobs (#2037)

* Simplify subsystem jobs

This pr simplifies the subsystem jobs interface. Instead of requiring an
extra message that is used to signal that a job should be ended, a job
now ends when the receiver returns `None`. Besides that it changes the
interface to enforce that messages to a job provide a relay parent.

* Drop ToJobTrait

* Remove FromJob

We always convert this message to FromJobCommand anyway.
This commit is contained in:
Bastian Köcher
2020-11-30 17:01:26 +01:00
committed by GitHub
parent 2d4aa3a42e
commit 536dceb4f6
9 changed files with 246 additions and 686 deletions
+39 -93
View File
@@ -25,16 +25,15 @@ use sp_keystore::{Error as KeystoreError, SyncCryptoStorePtr};
use polkadot_node_subsystem::{
messages::{
AllMessages, AvailabilityStoreMessage, BitfieldDistributionMessage,
BitfieldSigningMessage, CandidateBackingMessage, RuntimeApiMessage, RuntimeApiRequest,
BitfieldSigningMessage, RuntimeApiMessage, RuntimeApiRequest,
},
errors::RuntimeApiError,
};
use polkadot_node_subsystem_util::{
self as util, JobManager, JobTrait, ToJobTrait, Validator, FromJobCommand,
metrics::{self, prometheus},
self as util, JobManager, JobTrait, Validator, FromJobCommand, metrics::{self, prometheus},
};
use polkadot_primitives::v1::{AvailabilityBitfield, CoreState, Hash, ValidatorIndex};
use std::{convert::TryFrom, pin::Pin, time::Duration, iter::FromIterator};
use std::{pin::Pin, time::Duration, iter::FromIterator};
use wasm_timer::{Delay, Instant};
use thiserror::Error;
@@ -45,76 +44,6 @@ const LOG_TARGET: &str = "bitfield_signing";
/// Each `BitfieldSigningJob` prepares a signed bitfield for a single relay parent.
pub struct BitfieldSigningJob;
/// Messages which a `BitfieldSigningJob` is prepared to receive.
#[allow(missing_docs)]
pub enum ToJob {
BitfieldSigning(BitfieldSigningMessage),
Stop,
}
impl ToJobTrait for ToJob {
const STOP: Self = ToJob::Stop;
fn relay_parent(&self) -> Option<Hash> {
match self {
Self::BitfieldSigning(bsm) => bsm.relay_parent(),
Self::Stop => None,
}
}
}
impl TryFrom<AllMessages> for ToJob {
type Error = ();
fn try_from(msg: AllMessages) -> Result<Self, Self::Error> {
match msg {
AllMessages::BitfieldSigning(bsm) => Ok(ToJob::BitfieldSigning(bsm)),
_ => Err(()),
}
}
}
impl From<BitfieldSigningMessage> for ToJob {
fn from(bsm: BitfieldSigningMessage) -> ToJob {
ToJob::BitfieldSigning(bsm)
}
}
/// Messages which may be sent from a `BitfieldSigningJob`.
#[allow(missing_docs)]
#[derive(Debug, derive_more::From)]
pub enum FromJob {
AvailabilityStore(AvailabilityStoreMessage),
BitfieldDistribution(BitfieldDistributionMessage),
CandidateBacking(CandidateBackingMessage),
RuntimeApi(RuntimeApiMessage),
}
impl From<FromJob> for FromJobCommand {
fn from(from_job: FromJob) -> FromJobCommand {
FromJobCommand::SendMessage(match from_job {
FromJob::AvailabilityStore(asm) => AllMessages::AvailabilityStore(asm),
FromJob::BitfieldDistribution(bdm) => AllMessages::BitfieldDistribution(bdm),
FromJob::CandidateBacking(cbm) => AllMessages::CandidateBacking(cbm),
FromJob::RuntimeApi(ram) => AllMessages::RuntimeApi(ram),
})
}
}
impl TryFrom<AllMessages> for FromJob {
type Error = ();
fn try_from(msg: AllMessages) -> Result<Self, Self::Error> {
match msg {
AllMessages::AvailabilityStore(asm) => Ok(Self::AvailabilityStore(asm)),
AllMessages::BitfieldDistribution(bdm) => Ok(Self::BitfieldDistribution(bdm)),
AllMessages::CandidateBacking(cbm) => Ok(Self::CandidateBacking(cbm)),
AllMessages::RuntimeApi(ram) => Ok(Self::RuntimeApi(ram)),
_ => Err(()),
}
}
}
/// Errors we may encounter in the course of executing the `BitfieldSigningSubsystem`.
#[derive(Debug, Error)]
pub enum Error {
@@ -145,7 +74,7 @@ async fn get_core_availability(
relay_parent: Hash,
core: CoreState,
validator_idx: ValidatorIndex,
sender: &Mutex<&mut mpsc::Sender<FromJob>>,
sender: &Mutex<&mut mpsc::Sender<FromJobCommand>>,
) -> Result<bool, Error> {
if let CoreState::Occupied(core) = core {
let (tx, rx) = oneshot::channel();
@@ -153,10 +82,10 @@ async fn get_core_availability(
.lock()
.await
.send(
RuntimeApiMessage::Request(
AllMessages::from(RuntimeApiMessage::Request(
relay_parent,
RuntimeApiRequest::CandidatePendingAvailability(core.para_id, tx),
).into(),
)).into(),
)
.await?;
@@ -174,11 +103,11 @@ async fn get_core_availability(
.lock()
.await
.send(
AvailabilityStoreMessage::QueryChunkAvailability(
AllMessages::from(AvailabilityStoreMessage::QueryChunkAvailability(
committed_candidate_receipt.hash(),
validator_idx,
tx,
).into(),
)).into(),
)
.await?;
return rx.await.map_err(Into::into);
@@ -188,9 +117,14 @@ async fn get_core_availability(
}
/// delegates to the v1 runtime API
async fn get_availability_cores(relay_parent: Hash, sender: &mut mpsc::Sender<FromJob>) -> Result<Vec<CoreState>, Error> {
async fn get_availability_cores(
relay_parent: Hash,
sender: &mut mpsc::Sender<FromJobCommand>,
) -> Result<Vec<CoreState>, Error> {
let (tx, rx) = oneshot::channel();
sender.send(RuntimeApiMessage::Request(relay_parent, RuntimeApiRequest::AvailabilityCores(tx)).into()).await?;
sender
.send(AllMessages::from(RuntimeApiMessage::Request(relay_parent, RuntimeApiRequest::AvailabilityCores(tx))).into())
.await?;
match rx.await {
Ok(Ok(out)) => Ok(out),
Ok(Err(runtime_err)) => Err(runtime_err.into()),
@@ -206,7 +140,7 @@ async fn get_availability_cores(relay_parent: Hash, sender: &mut mpsc::Sender<Fr
async fn construct_availability_bitfield(
relay_parent: Hash,
validator_idx: ValidatorIndex,
sender: &mut mpsc::Sender<FromJob>,
sender: &mut mpsc::Sender<FromJobCommand>,
) -> Result<AvailabilityBitfield, Error> {
// get the set of availability cores from the runtime
let availability_cores = get_availability_cores(relay_parent, sender).await?;
@@ -275,8 +209,7 @@ impl metrics::Metrics for Metrics {
}
impl JobTrait for BitfieldSigningJob {
type ToJob = ToJob;
type FromJob = FromJob;
type ToJob = BitfieldSigningMessage;
type Error = Error;
type RunArgs = SyncCryptoStorePtr;
type Metrics = Metrics;
@@ -289,8 +222,8 @@ impl JobTrait for BitfieldSigningJob {
relay_parent: Hash,
keystore: Self::RunArgs,
metrics: Self::Metrics,
_receiver: mpsc::Receiver<ToJob>,
mut sender: mpsc::Sender<FromJob>,
_receiver: mpsc::Receiver<BitfieldSigningMessage>,
mut sender: mpsc::Sender<FromJobCommand>,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send>> {
let metrics = metrics.clone();
async move {
@@ -330,7 +263,11 @@ impl JobTrait for BitfieldSigningJob {
metrics.on_bitfield_signed();
sender
.send(BitfieldDistributionMessage::DistributeBitfield(relay_parent, signed_bitfield).into())
.send(
AllMessages::from(
BitfieldDistributionMessage::DistributeBitfield(relay_parent, signed_bitfield),
).into(),
)
.await
.map_err(Into::into)
}
@@ -345,8 +282,7 @@ pub type BitfieldSigningSubsystem<Spawner, Context> = JobManager<Spawner, Contex
mod tests {
use super::*;
use futures::{pin_mut, executor::block_on};
use polkadot_primitives::v1::{OccupiedCore};
use FromJob::*;
use polkadot_primitives::v1::OccupiedCore;
fn occupied_core(para_id: u32) -> CoreState {
CoreState::Occupied(OccupiedCore {
@@ -373,12 +309,18 @@ mod tests {
loop {
futures::select! {
m = receiver.next() => match m.unwrap() {
RuntimeApi(RuntimeApiMessage::Request(rp, RuntimeApiRequest::AvailabilityCores(tx))) => {
FromJobCommand::SendMessage(
AllMessages::RuntimeApi(
RuntimeApiMessage::Request(rp, RuntimeApiRequest::AvailabilityCores(tx)),
),
) => {
assert_eq!(relay_parent, rp);
tx.send(Ok(vec![CoreState::Free, occupied_core(1), occupied_core(2)])).unwrap();
},
RuntimeApi(
RuntimeApiMessage::Request(rp, RuntimeApiRequest::CandidatePendingAvailability(para_id, tx))
FromJobCommand::SendMessage(
AllMessages::RuntimeApi(
RuntimeApiMessage::Request(rp, RuntimeApiRequest::CandidatePendingAvailability(para_id, tx)),
),
) => {
assert_eq!(relay_parent, rp);
@@ -388,7 +330,11 @@ mod tests {
tx.send(Ok(None)).unwrap();
}
},
AvailabilityStore(AvailabilityStoreMessage::QueryChunkAvailability(_, vidx, tx)) => {
FromJobCommand::SendMessage(
AllMessages::AvailabilityStore(
AvailabilityStoreMessage::QueryChunkAvailability(_, vidx, tx),
),
) => {
assert_eq!(validator_index, vidx);
tx.send(true).unwrap();