mod domain;
mod observability;
mod orders;
mod payments;
mod routes;
use std::time::Duration;
use ruststream::ServerSpec;
use ruststream::memory::MemoryBroker;
use ruststream::metrics::Metrics;
use ruststream::runtime::{AppInfo, Identity, RustStream, Stack};
use crate::domain::{Repository, ServiceError};
use crate::observability::Observe;
#[ruststream::app]
fn app() -> RustStream<Stack<Observe, Identity>> {
let metrics = Metrics::new().expect("create metrics registry");
let metrics_dump = metrics.clone();
RustStream::new(AppInfo::new("orders-service", "0.1.0"))
.server(
"production",
ServerSpec::new("nats://orders.internal:4222", "nats"),
)
.layer(Observe)
.publish_layer(metrics.publish_layer())
.on_startup(|mut state| async move {
let repo = Repository::open().await?;
state.insert(repo);
Ok::<_, ServiceError>(state)
})
.after_shutdown(move |state| async move {
if let Some(repo) = state.get::<Repository>() {
repo.close().await;
}
match metrics_dump.export() {
Ok(text) => tracing::info!("final metrics:\n{text}"),
Err(e) => tracing::warn!(error = %e, "could not export metrics"),
}
Ok::<(), ServiceError>(())
})
.shutdown_timeout(Duration::from_secs(10))
.with_broker(MemoryBroker::new(), |b| {
b.include_router(routes::orders(b.broker(), &metrics));
b.include_router(routes::payments(b.broker(), &metrics));
})
}