2026-02-02 07:19:22 +01:00
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
|
|
|
|
use testing_framework_core::scenario::HttpReadinessRequirement;
|
|
|
|
|
use tracing::{info, warn};
|
2025-12-10 10:11:45 +01:00
|
|
|
|
|
|
|
|
use crate::{
|
2026-02-02 07:19:22 +01:00
|
|
|
env::ComposeDeployEnv,
|
2025-12-10 10:11:45 +01:00
|
|
|
errors::ComposeRunnerError,
|
2026-02-02 07:19:22 +01:00
|
|
|
infrastructure::{environment::StackEnvironment, ports::HostPortMapping},
|
2026-01-26 08:26:15 +01:00
|
|
|
lifecycle::readiness::ensure_nodes_ready_with_ports,
|
2025-12-10 10:11:45 +01:00
|
|
|
};
|
|
|
|
|
|
2026-02-02 07:19:22 +01:00
|
|
|
pub struct ReadinessChecker<E: ComposeDeployEnv> {
|
|
|
|
|
_env: PhantomData<E>,
|
|
|
|
|
}
|
2025-12-10 10:11:45 +01:00
|
|
|
|
2026-02-02 07:19:22 +01:00
|
|
|
impl<E: ComposeDeployEnv> ReadinessChecker<E> {
|
2025-12-10 10:11:45 +01:00
|
|
|
pub async fn wait_all(
|
2026-02-02 07:19:22 +01:00
|
|
|
descriptors: &E::Deployment,
|
2025-12-10 10:11:45 +01:00
|
|
|
host_ports: &HostPortMapping,
|
2026-02-02 07:19:22 +01:00
|
|
|
requirement: HttpReadinessRequirement,
|
2025-12-10 10:11:45 +01:00
|
|
|
environment: &mut StackEnvironment,
|
|
|
|
|
) -> Result<(), ComposeRunnerError> {
|
2026-01-26 08:26:15 +01:00
|
|
|
let node_ports = host_ports.node_api_ports();
|
|
|
|
|
info!(ports = ?node_ports, "waiting for node HTTP endpoints");
|
2026-02-02 07:19:22 +01:00
|
|
|
|
|
|
|
|
wait_local_readiness::<E>(environment, &node_ports, requirement).await?;
|
2025-12-10 10:11:45 +01:00
|
|
|
|
|
|
|
|
info!("waiting for remote service readiness");
|
2026-02-02 07:19:22 +01:00
|
|
|
wait_remote_readiness::<E>(environment, descriptors, host_ports, requirement).await?;
|
2025-12-10 10:11:45 +01:00
|
|
|
|
2025-12-11 09:00:14 +01:00
|
|
|
info!("compose readiness checks passed");
|
2025-12-10 10:11:45 +01:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-15 23:59:08 +01:00
|
|
|
|
2026-02-02 07:19:22 +01:00
|
|
|
async fn wait_local_readiness<E: ComposeDeployEnv>(
|
|
|
|
|
environment: &mut StackEnvironment,
|
|
|
|
|
node_ports: &[u16],
|
|
|
|
|
requirement: HttpReadinessRequirement,
|
|
|
|
|
) -> Result<(), ComposeRunnerError> {
|
|
|
|
|
let result = ensure_nodes_ready_with_ports::<E>(node_ports, requirement)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(ComposeRunnerError::from);
|
|
|
|
|
|
|
|
|
|
run_readiness_check(environment, "node readiness failed", result).await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn wait_remote_readiness<E: ComposeDeployEnv>(
|
|
|
|
|
environment: &mut StackEnvironment,
|
|
|
|
|
descriptors: &E::Deployment,
|
|
|
|
|
host_ports: &HostPortMapping,
|
|
|
|
|
requirement: HttpReadinessRequirement,
|
|
|
|
|
) -> Result<(), ComposeRunnerError> {
|
|
|
|
|
run_readiness_check(
|
|
|
|
|
environment,
|
|
|
|
|
"remote readiness probe failed",
|
|
|
|
|
E::wait_remote_readiness(descriptors, host_ports, requirement)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|source| {
|
|
|
|
|
ComposeRunnerError::Readiness(crate::errors::StackReadinessError::Remote { source })
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn run_readiness_check(
|
2025-12-15 23:59:08 +01:00
|
|
|
environment: &mut StackEnvironment,
|
2026-02-02 07:19:22 +01:00
|
|
|
fail_reason: &str,
|
|
|
|
|
result: Result<(), ComposeRunnerError>,
|
|
|
|
|
) -> Result<(), ComposeRunnerError> {
|
|
|
|
|
if let Err(error) = result {
|
|
|
|
|
environment.fail(fail_reason).await;
|
|
|
|
|
warn!(error = ?error, "{fail_reason}");
|
|
|
|
|
return Err(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
2025-12-15 23:59:08 +01:00
|
|
|
}
|