v0.3.2-pre.007

This commit is contained in:
2026-08-29 21:40:57 +02:00
parent c4f56d9e85
commit e39cf656b2
19 changed files with 849 additions and 53 deletions

View File

@@ -1,10 +1,122 @@
// file: crates/ksp-store-postgres-lib/src/runtime.rs
// version: 2
// version: 3
const APPLICATION_NAME: &str = "ksp-store";
const MAX_CONNECTION_URI_BYTES: usize = 4_096;
const SHUTDOWN_POLL_INTERVAL_MS: u64 = 10;
/// Safe PostgreSQL runtime counters exported only through the narrow backend bridge.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PostgresBackendRuntimeSnapshot {
pool_available: u32,
pool_capacity: u32,
pool_size: u32,
pool_waiting: u32,
}
impl PostgresBackendRuntimeSnapshot {
/// Creates a safe pool-counter projection from already bounded values.
#[must_use]
pub(crate) const fn new(pool_capacity: u32, pool_size: u32, pool_available: u32, pool_waiting: u32) -> Self {
return Self { pool_available, pool_capacity, pool_size, pool_waiting };
}
/// Returns the number of currently available pooled PostgreSQL clients.
#[must_use]
pub const fn pool_available(&self) -> u32 {
return self.pool_available;
}
/// Returns the configured maximum pooled PostgreSQL client count.
#[must_use]
pub const fn pool_capacity(&self) -> u32 {
return self.pool_capacity;
}
/// Returns the current pooled PostgreSQL client count.
#[must_use]
pub const fn pool_size(&self) -> u32 {
return self.pool_size;
}
/// Returns the number of tasks currently waiting for a pooled PostgreSQL client.
#[must_use]
pub const fn pool_waiting(&self) -> u32 {
return self.pool_waiting;
}
}
/// Safe PostgreSQL readiness projection returned to the common Store facade.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PostgresBackendHealthSnapshot {
error_kind: std::option::Option<crate::PostgresBackendErrorKind>,
migration_version: std::option::Option<u64>,
pending_migration_count: u32,
ready: bool,
runtime: PostgresBackendRuntimeSnapshot,
}
impl PostgresBackendHealthSnapshot {
/// Creates one successful safe readiness projection.
#[must_use]
pub(crate) const fn ready(runtime: PostgresBackendRuntimeSnapshot, migration_version: u64, pending_migration_count: u32) -> Self {
return Self {
error_kind: std::option::Option::None,
migration_version: std::option::Option::Some(migration_version),
pending_migration_count,
ready: true,
runtime,
};
}
/// Creates one failed safe readiness projection from a classified backend error.
#[must_use]
pub(crate) const fn not_ready(
runtime: PostgresBackendRuntimeSnapshot,
migration_version: std::option::Option<u64>,
pending_migration_count: u32,
error_kind: crate::PostgresBackendErrorKind,
) -> Self {
return Self {
error_kind: std::option::Option::Some(error_kind),
migration_version,
pending_migration_count,
ready: false,
runtime,
};
}
/// Returns the safe backend error classification when readiness could not be proven.
#[must_use]
pub const fn error_kind(&self) -> std::option::Option<crate::PostgresBackendErrorKind> {
return self.error_kind;
}
/// Returns whether the latest bounded PostgreSQL probe proved readiness.
#[must_use]
pub const fn is_ready(&self) -> bool {
return self.ready;
}
/// Returns the migration version observed by the readiness probe when available.
#[must_use]
pub const fn migration_version(&self) -> std::option::Option<u64> {
return self.migration_version;
}
/// Returns the number of embedded migrations newer than the observed applied version.
#[must_use]
pub const fn pending_migration_count(&self) -> u32 {
return self.pending_migration_count;
}
/// Returns the safe PostgreSQL pool counters captured for this probe.
#[must_use]
pub const fn runtime(&self) -> &PostgresBackendRuntimeSnapshot {
return &self.runtime;
}
}
/// TLS mode accepted by the physical PostgreSQL backend bridge.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
@@ -165,6 +277,17 @@ impl PostgresBackend {
return std::result::Result::Ok(Self { network: settings.network, pool });
}
/// Returns a safe synchronous snapshot of bounded pool counters without performing PostgreSQL I/O.
#[must_use]
pub fn runtime_snapshot(&self) -> PostgresBackendRuntimeSnapshot {
return runtime_snapshot_from_status(self.pool.status());
}
/// Runs a bounded lightweight PostgreSQL readiness probe and returns only safe classified diagnostics.
pub async fn health(&self) -> PostgresBackendHealthSnapshot {
return crate::probe_health(&self.pool).await;
}
/// Explicitly closes the pool and waits for all owned pooled objects to drain inside the supplied bound.
pub async fn close(self, timeout: std::time::Duration) -> std::result::Result<(), crate::PostgresBackendError> {
self.pool.close();
@@ -304,7 +427,8 @@ fn build_verified_tls() -> std::result::Result<tokio_postgres_rustls::MakeRustls
return std::result::Result::Ok(tokio_postgres_rustls::MakeRustlsConnect::new(client_config));
}
fn map_pool_error(error: deadpool_postgres::PoolError) -> crate::PostgresBackendError {
/// Maps one Deadpool acquisition error into a redacted backend classification.
pub(crate) fn map_pool_error(error: deadpool_postgres::PoolError) -> crate::PostgresBackendError {
return match error {
deadpool_postgres::PoolError::Timeout(timeout_type) => crate::PostgresBackendError::new(
crate::PostgresBackendErrorKind::PoolTimeout,
@@ -321,6 +445,23 @@ fn map_pool_error(error: deadpool_postgres::PoolError) -> crate::PostgresBackend
};
}
/// Converts Deadpool status into a bounded safe backend runtime projection.
pub(crate) fn runtime_snapshot_from_status(status: deadpool_postgres::Status) -> PostgresBackendRuntimeSnapshot {
return PostgresBackendRuntimeSnapshot::new(
bounded_count(status.max_size),
bounded_count(status.size),
bounded_count(status.available),
bounded_count(status.waiting),
);
}
fn bounded_count(value: usize) -> u32 {
if value > u32::MAX as usize {
return u32::MAX;
}
return value as u32;
}
#[cfg(test)]
#[path = "../unit_tests/runtime.rs"]
mod tests;