use std::sync::{
Arc, Mutex,
atomic::{AtomicBool, Ordering},
};
use aws_config::Region;
use aws_sdk_secretsmanager::config::Credentials;
use tokio::signal;
use tokio_util::sync::CancellationToken;
pub use git_version;
#[cfg(feature = "api")]
pub mod api;
#[macro_export]
macro_rules! version_info {
() => {
format!(
"{} {} ({})",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
option_env!("GIT_HASH")
.unwrap_or($crate::git_version::git_version!(fallback = "UNKNOWN"))
)
};
}
#[derive(Debug, Clone, Default)]
pub struct StartedServices {
external_service: Arc<Mutex<Vec<Arc<AtomicBool>>>>,
}
impl StartedServices {
pub fn new() -> Self {
Self::default()
}
pub fn new_service(&self) -> Arc<AtomicBool> {
let service = Arc::new(AtomicBool::default());
self.external_service
.lock()
.expect("Not poisoned")
.push(Arc::clone(&service));
service
}
pub fn all_started(&self) -> bool {
self.external_service
.lock()
.expect("Not poisoned")
.iter()
.all(|service| service.load(Ordering::Relaxed))
}
}
pub fn spawn_shutdown_task(
shutdown_signal: impl Future<Output = ()> + Send + 'static,
) -> (CancellationToken, Arc<AtomicBool>) {
let cancellation_token = CancellationToken::new();
let is_graceful = Arc::new(AtomicBool::new(false));
let task_token = cancellation_token.clone();
tokio::spawn({
let is_graceful = Arc::clone(&is_graceful);
async move {
let _drop_guard = task_token.drop_guard_ref();
tokio::select! {
_ = shutdown_signal => {
tracing::info!("received graceful shutdown");
is_graceful.store(true, Ordering::Relaxed);
task_token.cancel();
}
_ = task_token.cancelled() => {}
}
}
});
(cancellation_token, is_graceful)
}
pub async fn default_shutdown_signal() {
let ctrl_c = async {
signal::ctrl_c()
.await
.expect("failed to install Ctrl+C handler");
};
#[cfg(unix)]
let terminate = async {
signal::unix::signal(signal::unix::SignalKind::terminate())
.expect("failed to install signal handler")
.recv()
.await;
};
#[cfg(not(unix))]
let terminate = std::future::pending::<()>();
tokio::select! {
_ = ctrl_c => {},
_ = terminate => {},
}
}
pub async fn localstack_aws_config() -> aws_config::SdkConfig {
let region_provider = Region::new("us-east-1");
let credentials = Credentials::new("test", "test", None, None, "Static");
aws_config::from_env()
.region(region_provider)
.endpoint_url(
std::env::var("TEST_AWS_ENDPOINT_URL").unwrap_or("http://localhost:4566".to_string()),
)
.credentials_provider(credentials)
.load()
.await
}