Skip to content

Commit fdf3522

Browse files
authored
feat: add-heathcheck-database (#48)
feat: add-heathcheck-database
2 parents a1e1875 + 1855c51 commit fdf3522

6 files changed

Lines changed: 45 additions & 26 deletions

File tree

docker-compose.prod.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,20 @@ services:
55
# dockerfile: docker/Dockerfile
66
# target: prod
77
image: portabase/agent:latest
8-
# platform: linux/arm64
98
container_name: rust-prod
109
volumes:
1110
- ./databases.json:/config/config.json
1211
environment:
13-
# APP_ENV: production
1412
LOG: info
1513
TZ: "Europe/Paris"
16-
# DATABASES_CONFIG_FILE: "config.toml"
17-
EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNWU1OGU2MGEtODhiMy00YTBjLWI0NDktNTQ3OWZhOTQzZDBkIiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ=="
14+
#DATABASES_CONFIG_FILE: "config.toml"
15+
EDGE_KEY: "<to complete>"
1816
extra_hosts:
1917
- "localhost:host-gateway"
2018
networks:
2119
- portabase
2220

2321

24-
2522
db-mongodb-auth:
2623
container_name: db-mongodb-auth
2724
image: mongo:latest

src/domain/redis/ping.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::services::config::DatabaseConfig;
22
use anyhow::{Context, Result};
33
use tokio::process::Command;
44
use tokio::time::{Duration, timeout};
5-
use tracing::{debug, info};
5+
use tracing::{debug, error, info};
66

77
pub async fn run(cfg: DatabaseConfig) -> Result<bool> {
88
let mut cmd = Command::new("redis-cli");
@@ -21,7 +21,7 @@ pub async fn run(cfg: DatabaseConfig) -> Result<bool> {
2121

2222
cmd.arg("PING");
2323

24-
debug!("Command Ping: {:?}", cmd);
24+
debug!("Command Ping Redis: {:?}", cmd);
2525

2626
let result = timeout(Duration::from_secs(10), cmd.output()).await;
2727

@@ -31,16 +31,17 @@ pub async fn run(cfg: DatabaseConfig) -> Result<bool> {
3131
let stdout = String::from_utf8_lossy(&output.stdout);
3232
let stderr = String::from_utf8_lossy(&output.stderr);
3333

34-
info!("Redis stdout: {}", stdout);
35-
info!("Redis stderr: {}", stderr);
34+
if !stdout.is_empty() {
35+
error!("Redis stderr: {}", stderr);
36+
}
3637

3738
if stderr.contains("NOAUTH") {
38-
info!("Redis authentication failed (NOAUTH required)");
39+
error!("Redis authentication failed (NOAUTH required)");
3940
return Ok(false);
4041
}
4142

4243
if !output.status.success() {
43-
info!("Redis command failed with status: {:?}", output.status);
44+
error!("Redis command failed with status: {:?}", output.status);
4445
return Ok(false);
4546
}
4647

src/domain/valkey/ping.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::services::config::DatabaseConfig;
22
use anyhow::{Context, Result};
33
use tokio::process::Command;
44
use tokio::time::{Duration, timeout};
5-
use tracing::{debug, info};
5+
use tracing::{debug, info, error};
66

77
pub async fn run(cfg: DatabaseConfig) -> Result<bool> {
88
let mut cmd = Command::new("valkey-cli");
@@ -21,33 +21,34 @@ pub async fn run(cfg: DatabaseConfig) -> Result<bool> {
2121

2222
cmd.arg("PING");
2323

24-
debug!("Command Ping: {:?}", cmd);
24+
debug!("Command Ping Valkey: {:?}", cmd);
2525

2626
let result = timeout(Duration::from_secs(10), cmd.output()).await;
2727

2828
match result {
2929
Ok(output) => {
30-
let output = output.context("Failed to execute redis-cli")?;
30+
let output = output.context("Failed to execute valkey-cli")?;
3131
let stdout = String::from_utf8_lossy(&output.stdout);
3232
let stderr = String::from_utf8_lossy(&output.stderr);
3333

34-
info!("Redis stdout: {}", stdout);
35-
info!("Redis stderr: {}", stderr);
34+
if !stdout.is_empty() {
35+
error!("Valkey stderr: {}", stderr);
36+
}
3637

3738
if stderr.contains("NOAUTH") {
38-
info!("Redis authentication failed (NOAUTH required)");
39+
error!("Valkey authentication failed (NOAUTH required)");
3940
return Ok(false);
4041
}
4142

4243
if !output.status.success() {
43-
info!("Redis command failed with status: {:?}", output.status);
44+
error!("Valkey command failed with status: {:?}", output.status);
4445
return Ok(false);
4546
}
4647

4748
Ok(stdout.contains("PONG"))
4849
}
4950
Err(_) => {
50-
info!("Timeout connecting to Redis at {}:{}", cfg.host, cfg.port);
51+
info!("Timeout connecting to Valkey at {}:{}", cfg.host, cfg.port);
5152
Ok(false)
5253
}
5354
}

src/services/api/endpoints/agent/status.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub struct DatabasePayload<'a> {
1111
pub dbms: &'a str,
1212
#[serde(rename = "generatedId")]
1313
pub generated_id: &'a str,
14+
#[serde(rename = "pingStatus")]
15+
pub ping_status: bool
1416
}
1517

1618
#[derive(Serialize)]

src/services/status.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use crate::settings::CONFIG;
88
use reqwest::Client;
99
use std::error::Error;
1010
use std::sync::Arc;
11+
use futures_util::future::try_join_all;
12+
use crate::domain::factory::DatabaseFactory;
1113

1214
pub struct StatusService {
1315
ctx: Arc<Context>,
@@ -25,14 +27,20 @@ impl StatusService {
2527
pub async fn ping(&self, databases: &[DatabaseConfig]) -> Result<PingResult, Box<dyn Error>> {
2628
let edge_key = &self.ctx.edge_key;
2729

28-
let databases_payload: Vec<DatabasePayload> = databases
29-
.iter()
30-
.map(|db| DatabasePayload {
31-
name: &db.name,
32-
dbms: &db.db_type.as_str(),
33-
generated_id: &db.generated_id,
30+
let databases_payload: Vec<DatabasePayload> = try_join_all(
31+
databases.into_iter().map(|db| async move {
32+
let db_engine = DatabaseFactory::create_for_backup(db.clone()).await;
33+
34+
let reachable = db_engine.ping().await?;
35+
36+
Ok::<DatabasePayload, anyhow::Error>(DatabasePayload {
37+
name: &db.name,
38+
dbms: &db.db_type.as_str(),
39+
generated_id: &db.generated_id,
40+
ping_status: reachable,
41+
})
3442
})
35-
.collect();
43+
).await?;
3644

3745
let version_str = CONFIG.app_version.as_str();
3846
let result = self

src/settings.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ impl Settings {
2525
.parse::<usize>()
2626
.expect("POOLING must be a valid positive integer");
2727

28+
if pooling_seconds < 1 || pooling_seconds > 600 {
29+
panic!("POOLING must be between 1 second and 600 seconds (10 minutes)");
30+
}
31+
32+
if pooling_seconds < 5 {
33+
eprintln!(
34+
"[WARNING] POOLING is set to {}s. Values under 5s are not recommended for production.",
35+
pooling_seconds
36+
);
37+
}
2838
let tz = env::var("TZ").unwrap_or_else(|_| "UTC".to_string());
2939

3040
Self {

0 commit comments

Comments
 (0)