use {
super::{
super::{
FunctionId,
Functions,
derived_function_id,
effective_function_id,
status::HandlerConditions,
},
Caller,
worker::CallerWorker,
},
crate::{discovery::PeerInfo, primitives::Datum, tickets::TicketValidator},
core::{marker::PhantomData, time::Duration},
std::sync::Arc,
};
pub struct CallerConfig {
pub function_id: FunctionId,
pub require: Box<dyn Fn(&PeerInfo) -> bool + Send + Sync>,
pub handler_auth: Vec<Arc<dyn TicketValidator>>,
pub caller_auth: Vec<Arc<dyn TicketValidator>>,
pub call_timeout: Duration,
pub online_when:
Box<dyn Fn(HandlerConditions) -> HandlerConditions + Send + Sync>,
}
pub struct Builder<'f, Req: Datum, Res: Datum, E: Datum = ()> {
function_id: Option<FunctionId>,
require: Box<dyn Fn(&PeerInfo) -> bool + Send + Sync>,
handler_auth: Vec<Arc<dyn TicketValidator>>,
caller_auth: Vec<Arc<dyn TicketValidator>>,
call_timeout: Duration,
online_when:
Box<dyn Fn(HandlerConditions) -> HandlerConditions + Send + Sync>,
functions: &'f Functions,
_marker: PhantomData<fn(&Req, &Res, &E)>,
}
impl<Req: Datum, Res: Datum, E: Datum> Builder<'_, Req, Res, E> {
#[must_use]
pub fn with_function_id(
mut self,
function_id: impl Into<FunctionId>,
) -> Self {
self.function_id = Some(function_id.into());
self
}
#[must_use]
pub fn require<F>(mut self, pred: F) -> Self
where
F: Fn(&PeerInfo) -> bool + Send + Sync + 'static,
{
let prev = self.require;
self.require = Box::new(move |peer| prev(peer) && pred(peer));
self
}
#[must_use]
pub fn require_ticket(self, validator: impl TicketValidator) -> Self {
self.require_handler_ticket(validator)
}
#[must_use]
pub fn require_handler_ticket(
mut self,
validator: impl TicketValidator,
) -> Self {
self.handler_auth.push(Arc::new(validator));
self
}
#[must_use]
pub fn require_caller_ticket(
mut self,
validator: impl TicketValidator,
) -> Self {
self.caller_auth.push(Arc::new(validator));
self
}
#[must_use]
pub const fn with_call_timeout(mut self, timeout: Duration) -> Self {
self.call_timeout = timeout;
self
}
#[must_use]
pub fn online_when<F>(mut self, f: F) -> Self
where
F: Fn(HandlerConditions) -> HandlerConditions + Send + Sync + 'static,
{
self.online_when = Box::new(f);
self
}
pub fn build(self) -> Caller<Req, Res, E> {
let base = self
.function_id
.unwrap_or_else(derived_function_id::<Req, Res>);
let function_id =
effective_function_id(base, &self.caller_auth, &self.handler_auth);
let config = CallerConfig {
function_id,
require: self.require,
handler_auth: self.handler_auth,
caller_auth: self.caller_auth,
call_timeout: self.call_timeout,
online_when: self.online_when,
};
CallerWorker::spawn(config, self.functions)
}
}
impl<'f, Req: Datum, Res: Datum, E: Datum> Builder<'f, Req, Res, E> {
pub(in crate::functions) fn new(functions: &'f Functions) -> Self {
Self {
functions,
function_id: None,
require: Box::new(|_| true),
handler_auth: Vec::new(),
caller_auth: Vec::new(),
call_timeout: functions.config.call_timeout,
online_when: Box::new(|c| c.minimum_of(1)),
_marker: PhantomData,
}
}
}