use std::fmt;
use std::marker::PhantomData;
use std::borrow::Cow;
use std::num::NonZeroU32;
use crate::{
BatchSubscriber, Broker, Connected, PublishPolicy, Publisher, RetryDeclaration, Subscriber,
SubscriptionSource,
};
use crate::runtime::batch::{BatchDef, DeserializedBatch, TypedBatch, batch_metadata};
use crate::runtime::batch_inject::{BatchInjectDef, batch_inject_metadata};
use crate::runtime::batch_publishing::{BatchPublishingDef, batch_publishing_metadata};
use crate::runtime::dispatch::Workers;
use crate::runtime::failure::FailurePolicies;
use crate::runtime::handler::Handler;
use crate::runtime::inject::{InjectDef, inject_metadata};
use crate::runtime::input::{DecodeWith, Provided};
use crate::runtime::metadata::{HandlerMetadata, OutgoingKind, PublishDescription};
use crate::runtime::middleware::{BlanketLayer, Identity, Layer, Stack};
use crate::runtime::publish::{
FitsOffer, ForReply, NamesDestination, NarrowToUse, OutPipeline, PublishIdentity,
PublishPipeline, PublishTransform, Reads,
};
use crate::runtime::publishing::{PublishingDef, publishing_metadata};
use crate::runtime::redelivery::{PublishesCopiesHere, RetryPairing, RetrySetup};
use crate::runtime::retry::{
Absent, DeclareCap, DeclareDeadLetter, DeclareMount, Present, Retry, RetryOffer, RetryOpen,
RetryStackUse, RouteDeclaring, RoutePosition, SettlesDestination,
};
use crate::runtime::settings::BatchSized;
use crate::runtime::slot::{NoReply, OutAttachment, SlotCodec};
use crate::runtime::subscriber_def::{SubscriberDef, subscriber_metadata};
use crate::runtime::typed::Typed;
use super::builders::RouterWith;
use super::routes::{
BatchRoute, DeclaredRoute, HandleRoute, MountRoute, RetriedRoute, RetryDestinationsDeclared,
RouteMeta, RouteMetadata, RouteSubscription, RouterDef, RouterHandlers, SubscribeRoute,
};
use super::routes_inject::{BatchInjectRoute, InjectRoute};
use super::routes_publish::{BatchPublishingRoute, PublishingRoute, RawReplyRoute};
use super::sink::RouterSink;
use super::{
BatchInjectedRouter, BatchPublishingRouter, IncludedBatchRouter, IncludedRawBatchRouter,
IncludedRouter, InjectedRouter, MergedRouter, PublishingRouter, RawReplyRouter,
};
pub struct Router<B, Routes = (), C = (), Layers = Identity, Pipe = PublishIdentity> {
pub(super) routes: Routes,
pub(super) codec: C,
pub(super) layers: Layers,
pub(super) pipeline: Pipe,
pub(super) _broker: PhantomData<fn() -> B>,
}
impl<B: Broker + 'static> Default for Router<B> {
fn default() -> Self {
Self {
routes: (),
codec: (),
layers: Identity,
pipeline: PublishIdentity,
_broker: PhantomData,
}
}
}
impl<B, Routes, C, Layers, Pipe> fmt::Debug for Router<B, Routes, C, Layers, Pipe> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Router").finish_non_exhaustive()
}
}
impl<B: Broker + 'static> Router<B, ()> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
}
impl<B: Broker + 'static, RouteCodec, RouteLayers, RoutePipe>
Router<B, (), RouteCodec, RouteLayers, RoutePipe>
{
#[must_use]
pub fn layer<N>(self, layer: N) -> Router<B, (), RouteCodec, Stack<N, RouteLayers>, RoutePipe> {
Router {
routes: self.routes,
codec: self.codec,
layers: Stack::new(layer, self.layers),
pipeline: self.pipeline,
_broker: PhantomData,
}
}
}
impl<B: Broker + 'static, RouteCodec, RoutePipe> Router<B, (), RouteCodec, Identity, RoutePipe> {
pub(crate) fn for_scope(codec: RouteCodec, pipeline: RoutePipe) -> Self {
Self {
routes: (),
codec,
layers: Identity,
pipeline,
_broker: PhantomData,
}
}
}
impl<B: Broker + 'static, Routes, RouteCodec, RouteLayers, RoutePipe>
Router<B, Routes, RouteCodec, RouteLayers, RoutePipe>
{
#[must_use]
pub fn with_codec<C>(self, codec: C) -> Router<B, Routes, C, RouteLayers, RoutePipe> {
Router {
routes: self.routes,
codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
#[must_use]
pub fn merge<R2, C2, L2, P2>(
self,
other: Router<B, R2, C2, L2, P2>,
) -> MergedRouter<B, R2, C2, L2, P2, RouteCodec, RouteLayers, RoutePipe, Routes>
where
L2: BlanketLayer,
{
Router {
routes: (other, self.routes),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
#[allow(clippy::type_complexity)] pub fn handle<S, H>(
self,
subscriber: S,
handler: H,
meta: HandlerMetadata,
) -> Router<B, (HandleRoute<S, H>, Routes), RouteCodec, RouteLayers, RoutePipe>
where
S: Subscriber + Send + 'static,
H: Handler<S::Message> + 'static,
{
Router {
routes: (
HandleRoute {
subscriber,
handler,
meta,
policies: FailurePolicies::default(),
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
pub(crate) fn mount_subscriber<Source, Def, DecodeCodec>(
self,
source: Source,
def: Def,
codec: DecodeCodec,
) -> IncludedRouter<B, Source, Def, DecodeCodec, RouteCodec, RouteLayers, RoutePipe, Routes>
where
Source: SubscriptionSource<Connected<B>> + Send + 'static,
Source::Subscriber: Send + 'static,
Def: SubscriberDef,
Def::Input: DecodeWith<DecodeCodec>,
Def::Handler: 'static,
DecodeCodec: Send + Sync + 'static,
{
let meta = subscriber_metadata(source.name().to_owned(), &def)
.decoded_with::<Def::Input, DecodeCodec>()
.describing::<Connected<B>, _>(&source);
let policies = def.failure_policies();
let workers = def.workers();
let handler = Typed::over(codec, def.into_handler()).on_decode_failure(policies.decode);
Router {
routes: (
SubscribeRoute {
source,
handler,
meta,
policies,
workers,
_context: PhantomData,
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
pub(crate) fn mount_batch<Source, Def, DecodeCodec>(
self,
source: Source,
def: Def,
codec: DecodeCodec,
) -> IncludedBatchRouter<B, Source, Def, DecodeCodec, RouteCodec, RouteLayers, RoutePipe, Routes>
where
Source: SubscriptionSource<Connected<B>> + Send + 'static,
Source::Subscriber: BatchSubscriber + Send + 'static,
Def: BatchDef + BatchSized,
Def::Input: DecodeWith<DecodeCodec>,
Def::Handler: 'static,
DecodeCodec: Send + Sync + 'static,
{
let meta = batch_metadata(source.name().to_owned(), &def)
.decoded_with::<Def::Input, DecodeCodec>()
.describing::<Connected<B>, _>(&source);
let policies = def.failure_policies();
let workers = def.workers();
let batch_size = def.batch_size();
let handler = TypedBatch::<_, Def::Input, _, _>::over(codec, def.into_handler())
.with_decode(policies.decode);
Router {
routes: (
BatchRoute {
source,
handler,
meta,
policies,
workers,
batch_size,
_context: PhantomData,
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
pub(super) fn mount_raw_batch<Source, Def, F>(
self,
source: Source,
def: Def,
) -> IncludedRawBatchRouter<B, Source, Def, F, RouteCodec, RouteLayers, RoutePipe, Routes>
where
Source: SubscriptionSource<Connected<B>> + Send + 'static,
Source::Subscriber: BatchSubscriber + Send + 'static,
Def: BatchDef<Input = Provided<F>> + BatchSized,
Def::Handler: 'static,
{
let meta =
batch_metadata(source.name().to_owned(), &def).describing::<Connected<B>, _>(&source);
let policies = def.failure_policies();
let workers = def.workers();
let batch_size = def.batch_size();
let handler =
DeserializedBatch::<_, F, _>::over(def.into_handler()).with_decode(policies.decode);
Router {
routes: (
BatchRoute {
source,
handler,
meta,
policies,
workers,
batch_size,
_context: PhantomData,
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
pub(super) fn mount_inject<Source, Def, DecodeCodec, Extra>(
self,
source: Source,
def: Def,
codec: DecodeCodec,
extra: Extra,
) -> InjectedRouter<
B,
Source,
Def,
DecodeCodec,
Extra,
RouteCodec,
RouteLayers,
RoutePipe,
Routes,
>
where
Source: SubscriptionSource<Connected<B>> + Send + 'static,
Source::Subscriber: Send + 'static,
Def: InjectDef + 'static,
Def::Input: DecodeWith<DecodeCodec>,
DecodeCodec: Send + Sync + 'static,
{
let meta = inject_metadata(source.name().to_owned(), &def)
.decoded_with::<Def::Input, DecodeCodec>()
.describing::<Connected<B>, _>(&source);
let policies = def.failure_policies();
let workers = def.workers();
Router {
routes: (
InjectRoute {
source,
def,
codec,
extra,
meta,
policies,
workers,
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
pub(super) fn mount_batch_inject<Source, Def, DecodeCodec, Extra>(
self,
source: Source,
def: Def,
codec: DecodeCodec,
extra: Extra,
) -> BatchInjectedRouter<
B,
Source,
Def,
DecodeCodec,
Extra,
RouteCodec,
RouteLayers,
RoutePipe,
Routes,
>
where
Source: SubscriptionSource<Connected<B>> + Send + 'static,
Source::Subscriber: BatchSubscriber + Send + 'static,
Def: BatchInjectDef + BatchSized + 'static,
Def::Input: DecodeWith<DecodeCodec>,
DecodeCodec: Send + Sync + 'static,
{
let meta = batch_inject_metadata(source.name().to_owned(), &def)
.decoded_with::<Def::Input, DecodeCodec>()
.describing::<Connected<B>, _>(&source);
let policies = def.failure_policies();
let workers = def.workers();
let batch_size = def.batch_size();
Router {
routes: (
BatchInjectRoute {
source,
def,
codec,
extra,
meta,
policies,
workers,
batch_size,
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
pub(super) fn mount_batch_publishing_source<Source, Def, DecodeCodec, ReplySource, Extra>(
self,
source: Source,
def: Def,
codec: DecodeCodec,
publisher: ReplySource,
extra: Extra,
) -> BatchPublishingRouter<
B,
Source,
Def,
DecodeCodec,
ReplySource,
Extra,
RouteCodec,
RouteLayers,
RoutePipe,
Routes,
>
where
Source: SubscriptionSource<Connected<B>> + Send + 'static,
Source::Subscriber: BatchSubscriber + Send + 'static,
Def: BatchPublishingDef + BatchSized + 'static,
Def::Input: DecodeWith<DecodeCodec>,
DecodeCodec: Send + Sync + 'static,
ReplySource: 'static,
{
let meta = batch_publishing_metadata(source.name().to_owned(), &def)
.decoded_with::<Def::Input, DecodeCodec>()
.describing::<Connected<B>, _>(&source);
let policies = def.failure_policies();
let workers = def.workers();
let batch_size = def.batch_size();
Router {
routes: (
BatchPublishingRoute {
source,
def,
codec,
publisher,
extra,
meta,
policies,
workers,
batch_size,
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
pub(super) fn mount_publishing_source<Source, Def, DecodeCodec, ReplySource, Extra>(
self,
source: Source,
def: Def,
codec: DecodeCodec,
publisher: ReplySource,
extra: Extra,
) -> PublishingRouter<
B,
Source,
Def,
DecodeCodec,
ReplySource,
Extra,
RouteCodec,
RouteLayers,
RoutePipe,
Routes,
>
where
Source: SubscriptionSource<Connected<B>> + Send + 'static,
Source::Subscriber: Send + 'static,
Def: PublishingDef + 'static,
Def::Input: DecodeWith<DecodeCodec>,
DecodeCodec: 'static,
ReplySource: 'static,
{
let meta = publishing_metadata(source.name().to_owned(), &def)
.decoded_with::<Def::Input, DecodeCodec>()
.describing::<Connected<B>, _>(&source);
let policies = def.failure_policies();
let workers = def.workers();
Router {
routes: (
PublishingRoute {
source,
def,
codec,
publisher,
extra,
meta,
policies,
workers,
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
pub(super) fn mount_raw_reply_source<Source, Def, DecodeCodec, ReplySource, Extra>(
self,
source: Source,
def: Def,
codec: DecodeCodec,
publisher: ReplySource,
extra: Extra,
) -> RawReplyRouter<
B,
Source,
Def,
DecodeCodec,
ReplySource,
Extra,
RouteCodec,
RouteLayers,
RoutePipe,
Routes,
>
where
Source: SubscriptionSource<Connected<B>> + Send + 'static,
Source::Subscriber: Send + 'static,
Def: PublishingDef + 'static,
Def::Input: DecodeWith<DecodeCodec>,
DecodeCodec: 'static,
ReplySource: 'static,
{
let meta = publishing_metadata(source.name().to_owned(), &def)
.decoded_with::<Def::Input, DecodeCodec>()
.describing::<Connected<B>, _>(&source);
let policies = def.failure_policies();
let workers = def.workers();
Router {
routes: (
RawReplyRoute {
source,
def,
codec,
publisher,
extra,
meta,
policies,
workers,
},
self.routes,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
}
impl<B, S, H, Cx, Routes, RouteCodec, RouteLayers, RoutePipe>
Router<B, (SubscribeRoute<S, H, Cx>, Routes), RouteCodec, RouteLayers, RoutePipe>
{
#[must_use]
pub fn workers(mut self, workers: Workers) -> Self {
self.routes.0.workers = workers;
self
}
#[must_use]
#[allow(clippy::needless_pass_by_value, clippy::type_complexity)]
pub fn layer<N>(
self,
layer: N,
) -> Router<B, (SubscribeRoute<S, N::Handler, Cx>, Routes), RouteCodec, RouteLayers, RoutePipe>
where
N: Layer<H>,
{
let SubscribeRoute {
source,
handler,
meta,
policies,
workers,
_context: context,
} = self.routes.0;
Router {
routes: (
SubscribeRoute {
source,
handler: layer.layer(handler),
meta,
policies,
workers,
_context: context,
},
self.routes.1,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
}
impl<B, S, H, Cx, Routes, RouteCodec, RouteLayers, RoutePipe>
Router<B, (BatchRoute<S, H, Cx>, Routes), RouteCodec, RouteLayers, RoutePipe>
{
#[must_use]
pub fn workers(mut self, workers: Workers) -> Self {
self.routes.0.workers = workers;
self
}
}
impl<B: Broker + 'static, Head, Tail, RouteCodec, RouteLayers, RoutePipe>
Router<B, (Head, Tail), RouteCodec, RouteLayers, RoutePipe>
{
#[allow(clippy::needless_pass_by_value)]
pub fn out<M, Policy>(
self,
marker: M,
policy: Policy,
) -> <M as RoutePosition<B, Self, Policy>>::Out
where
M: RoutePosition<B, Self, Policy>,
{
let _ = marker;
M::bind(self, policy)
}
pub fn out_retry<Policy>(self, policy: Policy) -> <Retry as RoutePosition<B, Self, Policy>>::Out
where
Retry: RoutePosition<B, Self, Policy>,
{
self.out(Retry, policy)
}
#[allow(clippy::type_complexity)] pub fn max_attempts(
self,
attempts: NonZeroU32,
) -> RouterWith<DeclareMount, Self, (), RouteDeclaring<Present, Absent>>
where
Head: RetryOpen,
{
RouterWith::new((), (NoReply, ()).declare_cap(attempts), self)
}
#[allow(clippy::type_complexity)] pub fn dead_letter(
self,
destination: impl Into<Cow<'static, str>>,
) -> RouterWith<DeclareMount, Self, (), RouteDeclaring<Absent, Present>>
where
Head: RetryOpen,
{
RouterWith::new(
(),
(NoReply, ()).declare_dead_letter(destination.into()),
self,
)
}
}
impl<B: Broker + 'static, Routes: RouterHandlers, C, Layers, Pipe>
Router<B, Routes, C, Layers, Pipe>
{
#[must_use]
pub fn handlers(&self) -> Vec<HandlerMetadata> {
let mut out = Vec::new();
self.routes.collect_handlers(&mut out);
out
}
}
#[doc(hidden)]
pub trait RouterBroker {
type Broker: Broker + 'static;
}
impl<B: Broker + 'static, Routes, C, Layers, Pipe> RouterBroker
for Router<B, Routes, C, Layers, Pipe>
{
type Broker = B;
}
type RetryLive<Policy, B> = <Policy as PublishPolicy<Connected<B>>>::Live;
type RetryCx<Head, B> = <Head as RouteSubscription<B>>::Context;
type RetryOfferOf<Head, B, Dest> =
<<Head as RouteSubscription<B>>::Copies as RetryOffer<Dest>>::Offer;
type RetryUse<Transforms, Policy, B, Head> =
<Transforms as RetryStackUse<RetryLive<Policy, B>, RetryCx<Head, B>>>::Destination;
type RetryPolicy<Transforms, Policy, B, Head> =
<RetryUse<Transforms, Policy, B, Head> as NarrowToUse<Policy>>::Out;
type RetrySettled<Head, B, Dest, Transforms, Policy> =
<RetryOfferOf<Head, B, Dest> as SettlesDestination<RetryUse<Transforms, Policy, B, Head>>>::Settled;
type RetryWire<Transforms, Policy, B, Head> =
<RetryPolicy<Transforms, Policy, B, Head> as PublishPolicy<Connected<B>>>::Live;
#[doc(hidden)]
pub trait AttachRetry<Attachment, Dest>: Sized {
type Out;
fn attach_retry(self, slot: Attachment, destination: Option<Cow<'static, str>>) -> Self::Out;
}
impl<B, Head, Tail, C, Layers, Pipe, Policy, Transforms, Enc, Dest>
AttachRetry<OutAttachment<Retry, Policy, Transforms, Enc>, Dest>
for Router<B, (Head, Tail), C, Layers, Pipe>
where
B: Broker + 'static,
Head: RetryOpen + RouteMetadata + RouteSubscription<B, Context: Send + Sync + 'static>,
<Head as RouteSubscription<B>>::Copies:
PublishesCopiesHere<<Head as RouteSubscription<B>>::Source> + RetryOffer<Dest>,
RetryOfferOf<Head, B, Dest>: SettlesDestination<RetryUse<Transforms, Policy, B, Head>>,
C: Clone,
Pipe: Clone + OutPipeline<RetryWire<Transforms, Policy, B, Head>> + 'static,
Enc: SlotCodec<C>,
Policy: PublishPolicy<Connected<B>>,
Transforms: RetryStackUse<RetryLive<Policy, B>, RetryCx<Head, B>>
+ PublishTransform<
ForReply<RetryCx<Head, B>>,
<RetryWire<Transforms, Policy, B, Head> as Publisher>::Options,
> + Send
+ Sync
+ 'static,
RetryUse<Transforms, Policy, B, Head>: NarrowToUse<Policy>
+ NamesDestination
+ FitsOffer<RetryOfferOf<Head, B, Dest>, Reads, Retry>,
RetryPolicy<Transforms, Policy, B, Head>:
PublishPolicy<Connected<B>, Live: Publisher + Send + Sync + 'static> + Send + 'static,
{
type Out = Router<
B,
(
RetriedRoute<
Head,
B,
RetryCx<Head, B>,
RetrySettled<Head, B, Dest, Transforms, Policy>,
>,
Tail,
),
C,
Layers,
Pipe,
>;
fn attach_retry(
self,
slot: OutAttachment<Retry, Policy, Transforms, Enc>,
destination: Option<Cow<'static, str>>,
) -> Self::Out {
let (policy, transforms, _codec) = slot.into_parts();
let policy = <RetryUse<Transforms, Policy, B, Head> as NarrowToUse<Policy>>::narrow(policy);
let (mut head, tail) = self.routes;
if let Some(destination) = destination.clone() {
head.metadata_mut()
.declare_copy(destination, OutgoingKind::RetryCopy);
}
Router {
routes: (
RetriedRoute::new(
head,
RetryPairing::new(policy, transforms, self.pipeline.clone()),
destination,
<RetryUse<Transforms, Policy, B, Head> as NamesDestination>::NAMES,
),
tail,
),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
}
pub(super) type SlotDescription = Vec<(Cow<'static, str>, PublishDescription)>;
impl<B, Head, Tail, C, Layers, Pipe> Router<B, (Head, Tail), C, Layers, Pipe>
where
Head: RouteMetadata,
{
pub(super) fn describing_slots(mut self, slots: &[SlotDescription]) -> Self {
let meta = self.routes.0.metadata_mut();
for described in slots {
meta.describe_slot(described);
}
self
}
}
#[doc(hidden)]
pub trait AttachDeclaration: Sized {
type Out;
fn attach_declaration(self, declaration: RetryDeclaration) -> Self::Out;
}
impl<B, Head, Tail, C, Layers, Pipe> AttachDeclaration for Router<B, (Head, Tail), C, Layers, Pipe>
where
B: Broker + 'static,
Head: RetryOpen + RouteMetadata,
{
type Out = Router<B, (DeclaredRoute<Head>, Tail), C, Layers, Pipe>;
fn attach_declaration(self, declaration: RetryDeclaration) -> Self::Out {
let (mut head, tail) = self.routes;
if let Some(destination) = declaration.dead_letter() {
head.metadata_mut()
.declare_copy(destination.to_owned().into(), OutgoingKind::DeadLetter);
}
head.metadata_mut().retry = declaration.clone();
Router {
routes: (DeclaredRoute::new(head, declaration), tail),
codec: self.codec,
layers: self.layers,
pipeline: self.pipeline,
_broker: PhantomData,
}
}
}
impl<B: Broker, Routes: RetryDestinationsDeclared, C, Layers, Pipe> RetryDestinationsDeclared
for Router<B, Routes, C, Layers, Pipe>
{
}
#[derive(Clone)]
struct ComposedBlanket<Outer, Inner> {
outer: Outer,
inner: Inner,
}
impl<Outer: BlanketLayer, Inner: BlanketLayer> BlanketLayer for ComposedBlanket<Outer, Inner> {
fn apply<M, C, S, H>(&self, handler: H) -> impl Handler<M, C, S> + 'static
where
M: Send + Sync + 'static,
C: Send + 'static,
S: Send + Sync + 'static,
H: Handler<M, C, S> + 'static,
{
self.outer
.apply::<M, C, S, _>(self.inner.apply::<M, C, S, _>(handler))
}
}
impl<B, Routes, C, Layers, Pipe, State, RetryPipeline> RouterDef<B, State, RetryPipeline>
for Router<B, Routes, C, Layers, Pipe>
where
B: Broker + 'static,
Routes: RouterDef<B, State, Pipe>,
Layers: BlanketLayer + Clone + Send + Sync + 'static,
{
fn mount<G, PP>(
self,
global: &G,
pipeline: &PP,
_retry_pipeline: &RetryPipeline,
sink: &mut RouterSink<B, State>,
) where
G: BlanketLayer + Clone + Send + Sync + 'static,
PP: PublishPipeline + Clone + Send + 'static,
{
let composed = ComposedBlanket {
outer: global.clone(),
inner: self.layers,
};
self.routes.mount(&composed, pipeline, &self.pipeline, sink);
}
}
impl<B, Routes, C, Layers, Pipe> RouterHandlers for Router<B, Routes, C, Layers, Pipe>
where
Routes: RouterHandlers,
{
fn collect_handlers(&self, out: &mut Vec<HandlerMetadata>) {
self.routes.collect_handlers(out);
}
}
impl<B, Routes, C, Layers, Pipe, State, RetryPipeline> MountRoute<B, State, RetryPipeline>
for Router<B, Routes, C, Layers, Pipe>
where
B: Broker + 'static,
Routes: RouterDef<B, State, Pipe>,
Layers: BlanketLayer + Clone + Send + Sync + 'static,
{
type Context = ();
fn mount_one<G, PP>(
self,
global: &G,
pipeline: &PP,
retry_pipeline: &RetryPipeline,
sink: &mut RouterSink<B, State>,
_setup: RetrySetup<B, ()>,
) where
G: BlanketLayer + Clone + Send + Sync + 'static,
PP: PublishPipeline + Clone + Send + 'static,
{
RouterDef::<B, State, RetryPipeline>::mount(self, global, pipeline, retry_pipeline, sink);
}
}
impl<B, Routes, C, Layers, Pipe> RouteMeta for Router<B, Routes, C, Layers, Pipe>
where
Routes: RouterHandlers,
{
fn collect(&self, out: &mut Vec<HandlerMetadata>) {
self.routes.collect_handlers(out);
}
}