mod app_trait;
mod health;
mod include;
mod run;
mod scope;
mod service;
pub use app_trait::App;
pub use health::{HealthProbe, HealthState};
pub use include::{
IncludeBatchOut, IncludeBatchPublishing, IncludeBatchPublishingOut, IncludeDef, IncludeOut,
IncludePublishing, IncludePublishingOut, IncludeWith, IncludeWithOut, forms,
};
pub use run::RunningApp;
pub use scope::BrokerScope;
#[cfg(feature = "testing")]
pub(crate) use service::{RegisteredBroker, TestParts};
pub use service::{RustStream, Setup, Wired};
use std::sync::Arc;
use thiserror::Error;
use tokio::task::JoinHandle;
use tokio_util::sync::CancellationToken;
use crate::runtime::failure::ErrorShutdown;
use crate::runtime::lifecycle::{BoxError, BoxFuture};
pub(crate) type Starter<St> = Box<
dyn FnOnce(
Arc<St>,
ErrorShutdown,
CancellationToken,
) -> BoxFuture<'static, Result<JoinHandle<()>, BoxError>>
+ Send,
>;
pub(crate) type StateInit<St> =
Box<dyn FnOnce() -> BoxFuture<'static, Result<St, BoxError>> + Send>;
pub(crate) type LifecycleHook<St> =
Box<dyn FnOnce(Arc<St>) -> BoxFuture<'static, Result<(), BoxError>> + Send>;
#[derive(Clone, Copy)]
enum LifecyclePhase {
AfterStartup,
OnShutdown,
AfterShutdown,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct AppInfo {
pub title: String,
pub version: String,
pub description: Option<String>,
}
impl AppInfo {
#[must_use]
pub fn new(title: impl Into<String>, version: impl Into<String>) -> Self {
Self {
title: title.into(),
version: version.into(),
description: None,
}
}
#[must_use]
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum RustStreamError {
#[error("broker connect failed: {0}")]
Connect(#[source] BoxError),
#[error("startup hook failed: {0}")]
Startup(#[source] BoxError),
#[error("subscription failed: {0}")]
Subscribe(#[source] BoxError),
#[error("broker shutdown failed: {0}")]
Shutdown(#[source] BoxError),
#[error("dispatch task failed: {0}")]
Join(#[source] tokio::task::JoinError),
#[error("dispatch failed: {0}")]
Dispatch(String),
}
pub(super) mod lifecycle_hooks {
use std::{error::Error as StdError, future::Future, sync::Arc};
use crate::runtime::lifecycle::{BoxError, ConnectedSlot};
use crate::runtime::publish_source::pair_bound;
use crate::{Broker, Connected, PublishPolicy};
use super::LifecycleHook;
pub(crate) fn box_startup_publish<B, State, Source, Hook, Fut, E>(
slot: ConnectedSlot<B>,
source: Source,
hook: Hook,
) -> LifecycleHook<State>
where
B: Broker + 'static,
Source: PublishPolicy<Connected<B>> + Send + 'static,
Source::Live: Send,
Hook: FnOnce(Source::Live) -> Fut + Send + 'static,
Fut: Future<Output = Result<(), E>> + Send + 'static,
E: StdError + Send + Sync + 'static,
{
Box::new(move |_state: Arc<State>| {
Box::pin(async move {
let live = pair_bound::<B, Source>(&slot, source)
.await
.map_err(|e| Box::new(e) as BoxError)?;
hook(live).await.map_err(|e| Box::new(e) as BoxError)
})
})
}
}