#[macro_export]
macro_rules! __tightbeam_servlet_common_methods {
($protocol:path) => {
#[allow(dead_code)]
pub fn addr(&self) -> <$protocol as $crate::transport::Protocol>::Address {
self.addr
}
#[allow(dead_code)]
pub fn set_trace(&self, trace: ::std::sync::Arc<$crate::trace::TraceCollector>) {
if let Ok(mut guard) = self.trace_handle.lock() {
*guard = trace;
}
}
#[allow(dead_code)]
pub fn stop(mut self) {
if let Some(handle) = self.server_handle.take() {
$crate::colony::servlet::servlet_runtime::rt::abort(&handle);
}
}
#[allow(dead_code)]
#[cfg(feature = "tokio")]
pub async fn join(
mut self,
) -> ::core::result::Result<(), $crate::colony::servlet::servlet_runtime::rt::JoinError> {
if let Some(handle) = self.server_handle.take() {
$crate::colony::servlet::servlet_runtime::rt::join(handle).await
} else {
Ok(())
}
}
#[allow(dead_code)]
#[cfg(all(not(feature = "tokio"), feature = "std"))]
pub fn join(mut self) -> Result<(), $crate::colony::servlet::servlet_runtime::rt::JoinError> {
if let Some(handle) = self.server_handle.take() {
$crate::colony::servlet::servlet_runtime::rt::join(handle)
} else {
Ok(())
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __servlet_structs {
($vis:vis, $servlet_name:ident, $protocol:path, $env_config:ty) => {
$crate::paste::paste! {
$vis struct $servlet_name {
server_handle: Option<$crate::colony::servlet::servlet_runtime::rt::JoinHandle>,
server_pool_handles: Vec<$crate::colony::servlet::servlet_runtime::rt::JoinHandle>,
addr: <$protocol as $crate::transport::Protocol>::Address,
trace_handle: ::std::sync::Arc<::std::sync::Mutex<::std::sync::Arc<$crate::trace::TraceCollector>>>,
_phantom: ::core::marker::PhantomData<$env_config>,
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __servlet_create_server {
(
$protocol:path,
$listener:ident,
$collector_gates:ident,
$servlet_context:ident,
$trace_handle:ident,
$frame:ident,
$ctx:ident,
$handler_body:block
) => {
if $collector_gates.is_empty() {
$crate::server! {
protocol $protocol: $listener,
handle: move |frame_in| {
let ctx_clone = ::std::sync::Arc::clone(&$servlet_context);
async move {
let $frame = frame_in;
let $ctx = &*ctx_clone;
$handler_body
}
}
}
} else {
use $crate::transport::policy::PolicyConf;
$crate::colony::servlet::servlet_runtime::rt::spawn({
use $crate::transport::MessageCollector;
async move {
loop {
match $listener.accept().await {
Ok((mut transport, _addr)) => {
for gate in &$collector_gates {
transport = transport.with_collector_gate(::std::sync::Arc::clone(gate));
}
let ctx_clone = ::std::sync::Arc::clone(&$servlet_context);
$crate::colony::servlet::servlet_runtime::rt::spawn(async move {
let mut transport = transport;
loop {
let (frame_arc, status) = match transport.collect_message().await {
Ok(result) => result,
Err(_err) => break,
};
let frame_owned = ::std::sync::Arc::try_unwrap(frame_arc)
.unwrap_or_else(|arc| arc.as_ref().clone());
let response = if status == $crate::policy::TransitStatus::Accepted {
let ctx_for_handler = ::std::sync::Arc::clone(&ctx_clone);
let result: Result<Option<$crate::Frame>, $crate::TightBeamError> =
async move {
let $frame = frame_owned;
let $ctx = &*ctx_for_handler;
$handler_body
}
.await;
match result {
Ok(opt) => opt,
Err(_) => None,
}
} else {
None
};
match transport.send_response(status, response).await {
Ok(()) => continue,
Err(_err) => break,
}
}
});
}
Err(_err) => break,
}
}
}
})
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __servlet_start_impl {
(
$servlet_name:ident,
$protocol:path,
$input:ty,
$env_config:ty,
$frame:ident,
$ctx:ident,
$handler_body:block
) => {
$crate::paste::paste! {
async fn start_impl(
trace: ::std::sync::Arc<$crate::trace::TraceCollector>,
servlet_conf: $crate::colony::servlet::ServletConf<$protocol, $input>,
) -> Result<Self, $crate::TightBeamError> {
let bind_addr = <$protocol as $crate::transport::Protocol>::default_bind_address()?;
#[cfg(feature = "x509")]
let (listener, addr) = if let Some(x509_cfg) = servlet_conf.to_encryption_config_ref() {
<$protocol as $crate::transport::EncryptedProtocol>::bind_with(
bind_addr,
x509_cfg.clone()
).await?
} else {
<$protocol as $crate::transport::Protocol>::bind(bind_addr).await?
};
#[cfg(not(feature = "x509"))]
let (listener, addr) = <$protocol as $crate::transport::Protocol>::bind(bind_addr).await?;
let env_config = ::std::sync::Arc::clone(
servlet_conf.to_servlet_conf_ref()
.ok_or($crate::TightBeamError::MissingConfiguration)?
);
let trace_handle = ::std::sync::Arc::new(::std::sync::Mutex::new(::std::sync::Arc::clone(&trace)));
let collector_gates = servlet_conf.collector_gates_ref().to_vec();
let hive_context = servlet_conf.hive_context().cloned();
let message_decryptor = servlet_conf.to_message_decryptor();
let message_inflator = servlet_conf.to_message_inflator();
let workers_map = servlet_conf.to_workers();
let mut started_workers = ::std::collections::HashMap::new();
for (name, worker_box) in workers_map {
let started = worker_box.start_boxed(::std::sync::Arc::clone(&trace)).await?;
started_workers.insert(name, started);
}
let servlet_context = ::std::sync::Arc::new(
$crate::colony::servlet::ServletContext::new(
::std::sync::Arc::clone(&trace),
env_config,
started_workers,
hive_context,
)
.with_message_decryptor(message_decryptor)
.with_message_inflator(message_inflator)
);
let server_handle = $crate::__servlet_create_server!(
$protocol,
listener,
collector_gates,
servlet_context,
trace_handle,
$frame,
$ctx,
$handler_body
);
Ok(Self {
server_handle: Some(server_handle),
server_pool_handles: Vec::new(),
addr,
trace_handle,
_phantom: ::core::marker::PhantomData,
})
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __servlet_impl_methods {
($vis:vis, $servlet_name:ident, $protocol:path, $input:ty) => {
impl $servlet_name {
#[allow(dead_code)]
$vis async fn start(
trace: ::std::sync::Arc<$crate::trace::TraceCollector>,
config: Option<$crate::colony::servlet::ServletConf<$protocol, $input>>,
) -> Result<Self, $crate::TightBeamError> {
<Self as $crate::colony::servlet::Servlet<$input>>::start(trace, config).await
}
$crate::__tightbeam_servlet_common_methods!($protocol);
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __servlet_trait_impl {
($servlet_name:ident, $protocol:path, $input:ty) => {
impl $crate::colony::servlet::Servlet<$input> for $servlet_name {
type Conf = $crate::colony::servlet::ServletConf<$protocol, $input>;
type Address = <$protocol as $crate::transport::Protocol>::Address;
async fn start(
trace: ::std::sync::Arc<$crate::trace::TraceCollector>,
config: Option<Self::Conf>,
) -> Result<Self, $crate::TightBeamError> {
let servlet_conf = config.unwrap_or_default();
Self::start_impl(trace, servlet_conf).await
}
fn addr(&self) -> Self::Address {
self.addr
}
fn stop(self) {
self.stop()
}
async fn join(self) -> Result<(), $crate::colony::servlet::servlet_runtime::rt::JoinError> {
self.join().await
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __servlet_drop_impl {
($servlet_name:ident) => {
impl Drop for $servlet_name {
fn drop(&mut self) {
if let Some(handle) = self.server_handle.take() {
$crate::colony::servlet::servlet_runtime::rt::abort(&handle);
}
for handle in self.server_pool_handles.drain(..) {
$crate::colony::servlet::servlet_runtime::rt::abort(&handle);
}
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __servlet_box_impl {
($servlet_name:ident, $protocol:path) => {
impl $crate::colony::hive::ServletBox for $servlet_name {
fn addr_bytes(&self) -> Vec<u8> {
let addr = self.addr();
let addr_string: String = addr.to_string();
addr_string.into_bytes()
}
fn stop_boxed(self: Box<Self>) {
(*self).stop()
}
fn utilization(&self) -> Option<$crate::utils::BasisPoints> {
use $crate::colony::servlet::Servlet;
<Self as Servlet<_>>::utilization(self)
}
}
};
}
#[macro_export]
macro_rules! servlet {
(
$(#[$meta:meta])*
pub $servlet_name:ident<$input:ty, EnvConfig = $env_config:ty>,
protocol: $protocol:path,
handle: |$msg:ident, $frame:ident, $ctx:ident| async move $handler_body:block
) => {
$crate::servlet! {
$(#[$meta])*
pub $servlet_name<$input, EnvConfig = $env_config>,
protocol: $protocol,
handle: raw |$frame, $ctx| async move {
let mut $frame = $frame;
$crate::colony::servlet::prepare_typed_frame(&mut $frame, $ctx)?;
let $msg: $input = $crate::decode(&$frame.message)?;
$handler_body
}
}
};
(
$(#[$meta:meta])*
$servlet_name:ident<$input:ty, EnvConfig = $env_config:ty>,
protocol: $protocol:path,
handle: |$msg:ident, $frame:ident, $ctx:ident| async move $handler_body:block
) => {
$crate::servlet! {
$(#[$meta])*
$servlet_name<$input, EnvConfig = $env_config>,
protocol: $protocol,
handle: raw |$frame, $ctx| async move {
let mut $frame = $frame;
$crate::colony::servlet::prepare_typed_frame(&mut $frame, $ctx)?;
let $msg: $input = $crate::decode(&$frame.message)?;
$handler_body
}
}
};
(
$(#[$meta:meta])*
pub $servlet_name:ident<$input:ty, EnvConfig = $env_config:ty>,
protocol: $protocol:path,
handle: raw |$frame:ident, $ctx:ident| async move $handler_body:block
) => {
$crate::paste::paste! {
$(#[$meta])*
$crate::__servlet_structs!(pub, $servlet_name, $protocol, $env_config);
impl $servlet_name {
$crate::__servlet_start_impl!(
$servlet_name, $protocol, $input, $env_config,
$frame, $ctx,
$handler_body
);
}
$crate::__servlet_impl_methods!(pub, $servlet_name, $protocol, $input);
$crate::__servlet_trait_impl!($servlet_name, $protocol, $input);
$crate::__servlet_drop_impl!($servlet_name);
$crate::__servlet_box_impl!($servlet_name, $protocol);
}
};
(
$(#[$meta:meta])*
$servlet_name:ident<$input:ty, EnvConfig = $env_config:ty>,
protocol: $protocol:path,
handle: raw |$frame:ident, $ctx:ident| async move $handler_body:block
) => {
$crate::paste::paste! {
$(#[$meta])*
$crate::__servlet_structs!(, $servlet_name, $protocol, $env_config);
impl $servlet_name {
$crate::__servlet_start_impl!(
$servlet_name, $protocol, $input, $env_config,
$frame, $ctx,
$handler_body
);
}
$crate::__servlet_impl_methods!(pub, $servlet_name, $protocol, $input);
$crate::__servlet_trait_impl!($servlet_name, $protocol, $input);
$crate::__servlet_drop_impl!($servlet_name);
$crate::__servlet_box_impl!($servlet_name, $protocol);
}
};
}