mod admit;
mod offload;
use std::time::Duration;
pub use admit::{Admit, Admitted, InFlightCap, Shed};
pub(crate) use offload::JobService;
pub use offload::{Offload, OffloadJob, OffloadPool};
use crate::Finished;
use crate::engine::{Family, Service};
use crate::envelope::Envelope;
use crate::error::EndReason;
use crate::net::{AllowAll, ConnectionId, ControlLine, EventSink, Gate, NoControl, NoopSink};
use crate::reply::Reply;
use crate::service::Outcome;
pub trait Dispatch: Send + Sync + 'static {
fn run<F: Family, S: Service<F>>(
&self,
service: &S,
request: &F::Request<'_>,
env: &Envelope,
reply: &mut Reply<F>,
) -> Outcome;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Inline;
impl Dispatch for Inline {
#[inline]
fn run<F: Family, S: Service<F>>(
&self,
service: &S,
request: &F::Request<'_>,
env: &Envelope,
reply: &mut Reply<F>,
) -> Outcome {
service.call(request, env, reply)
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CheckpointAt {
Admitted,
BeforeDispatch,
BeforeReply,
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Verdict {
Pass,
Deny {
status: u16,
},
Kill,
}
pub trait Checkpoint: Send + Sync + 'static {
fn check(&self, env: &Envelope, at: CheckpointAt) -> Verdict;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct NoCheckpoint;
impl Checkpoint for NoCheckpoint {
#[inline(always)]
fn check(&self, _env: &Envelope, _at: CheckpointAt) -> Verdict {
Verdict::Pass
}
}
#[allow(unused_variables)]
pub trait Observer: Send + Sync + 'static {
fn request_head(&self, env: &Envelope) {}
fn request_admitted(&self, env: &Envelope) {}
fn request_shed(&self, env: &Envelope, shed: &Shed) {}
fn request_finished(&self, env: &Envelope, finished: &Finished) {}
fn connection_ended(&self, connection: ConnectionId, end: EndReason, requests: u32) {}
fn capacity_refused(&self, listener: &str, profile: crate::config::ProfileId) {}
fn drain_started(&self, open_connections: u32) {}
fn drain_finished(&self, report: &crate::running::DrainReport) {}
fn reloaded(&self, summary: &crate::reload::ReloadSummary) {}
fn reload_refused(&self, errors: &crate::error::ConfigErrors) {}
fn notify_failed(&self, error: &std::io::Error) {}
fn public_bind(&self, listener: &str, reason: &'static str) {}
fn service_misdeclared(&self, env: &Envelope, took: Duration) {}
fn service_error(&self, env: &Envelope, what: &'static str) {}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct NoObserver;
impl Observer for NoObserver {}
pub trait Hooks: Send + Sync + 'static {
type Admit: Admit;
type Dispatch: Dispatch;
type Checkpoint: Checkpoint;
type Observer: Observer;
type Gate: Gate;
type Events: EventSink;
type Control: ControlLine;
type Tls: net_io::TlsAcceptor;
}
pub struct HookSet<A, D, K, O, G, E, C, T> {
pub(crate) admit: A,
pub(crate) dispatch: D,
pub(crate) checkpoint: K,
pub(crate) observer: O,
pub(crate) gate: G,
pub(crate) events: E,
pub(crate) control: std::sync::Arc<C>,
pub(crate) tls: T,
}
impl<A, D, K, O, G, E, C, T> Hooks for HookSet<A, D, K, O, G, E, C, T>
where
A: Admit,
D: Dispatch,
K: Checkpoint,
O: Observer,
G: Gate,
E: EventSink,
C: ControlLine,
T: net_io::TlsAcceptor,
{
type Admit = A;
type Dispatch = D;
type Checkpoint = K;
type Observer = O;
type Gate = G;
type Events = E;
type Control = C;
type Tls = T;
}
pub type DefaultHooks = HookSet<
InFlightCap,
Inline,
NoCheckpoint,
NoObserver,
AllowAll,
NoopSink,
NoControl,
net_io::NoTls,
>;
impl Default for DefaultHooks {
fn default() -> Self {
HookSet {
admit: InFlightCap::new(),
dispatch: Inline,
checkpoint: NoCheckpoint,
observer: NoObserver,
gate: AllowAll,
events: NoopSink,
control: std::sync::Arc::new(NoControl),
tls: net_io::NoTls,
}
}
}
impl<A, D, K, O, G, E, C, T> core::fmt::Debug for HookSet<A, D, K, O, G, E, C, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("HookSet")
}
}