feat(message): add comprehensive message system with database migrations and health checks
- Add database migrations for message base table with indexes for efficient querying - Implement rich content support with attachment, embed, and poll tables - Create social features including reactions, bookmarks, mentions, and read states - Add thread management with participant tracking and resolution capabilities - Include article posts with title, cover image, tags, and engagement metrics - Support scheduled messages, stickers, forwards, and interactive components - Fix UUID defaults and ensure proper uniqueness constraints for drafts - Add gRPC health server for imks and health check client for appks connectivity - Replace non-connectable 0.0.0.0 addresses with localhost in service discovery - Normalize addresses during RPC configuration to handle bind address issues
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
//! gRPC health module for imks.
|
||||
//!
|
||||
//! Provides:
|
||||
//! - imks's own gRPC health server (for external health checks)
|
||||
//! - Health check client for probing appks health (5s interval)
|
||||
|
||||
use std::net::SocketAddr;
|
||||
use std::time::Duration;
|
||||
|
||||
use tonic_health::pb::HealthCheckRequest;
|
||||
use tonic_health::pb::health_check_response::ServingStatus;
|
||||
use tonic_health::pb::health_client::HealthClient;
|
||||
|
||||
use crate::{ImksError, ImksResult};
|
||||
|
||||
/// Start imks's own gRPC health server on the given address.
|
||||
///
|
||||
/// Reports `SERVING` for the overall server status (empty service name).
|
||||
pub async fn start_health_server(addr: SocketAddr) -> ImksResult<()> {
|
||||
let (reporter, health_service) = tonic_health::server::health_reporter();
|
||||
|
||||
// Empty service name = overall server health.
|
||||
// reporter is an owned handle — the server will remain SERVING
|
||||
// indefinitely unless a caller updates the status.
|
||||
reporter
|
||||
.set_service_status("", tonic_health::ServingStatus::Serving)
|
||||
.await;
|
||||
|
||||
tracing::info!(%addr, "imks gRPC health server started");
|
||||
|
||||
tonic::transport::Server::builder()
|
||||
.add_service(health_service)
|
||||
.serve(addr)
|
||||
.await
|
||||
.map_err(|e| ImksError::Internal(format!("Health gRPC server: {e:?}")))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check appks health by opening a short-lived gRPC connection and calling `Check`.
|
||||
///
|
||||
/// Uses a 3-second connect timeout to fail fast when appks is unreachable.
|
||||
pub async fn check_appks_health(addr: &str) -> ImksResult<bool> {
|
||||
let endpoint = tonic::transport::Endpoint::from_shared(addr.to_string())
|
||||
.map_err(|e| ImksError::Internal(format!("health endpoint: {e}")))?;
|
||||
|
||||
// Short-lived connection for health probe only
|
||||
let channel = endpoint
|
||||
.connect_timeout(Duration::from_secs(3))
|
||||
.connect()
|
||||
.await
|
||||
.map_err(ImksError::GrpcTransport)?;
|
||||
|
||||
let mut client = HealthClient::new(channel);
|
||||
let resp = client
|
||||
.check(HealthCheckRequest {
|
||||
service: "".to_string(),
|
||||
})
|
||||
.await
|
||||
.map_err(ImksError::GrpcStatus)?;
|
||||
|
||||
Ok(resp.into_inner().status == ServingStatus::Serving as i32)
|
||||
}
|
||||
Reference in New Issue
Block a user