feat(adminrpc): new standalone binary for admin gRPC service
Separate binary for Kubernetes internal admin RPC communication (SessionAdmin service on port 9090). Includes: - Redis cluster pool via session_manager - OTLP tracing with env-driven configuration - Tracing subscriber init (JSON to stderr) - Graceful startup with connection verification
This commit is contained in:
parent
4aaee59fa4
commit
fbd228f17e
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -335,6 +335,21 @@ version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "adminrpc"
|
||||
version = "0.2.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"config",
|
||||
"deadpool-redis",
|
||||
"observability",
|
||||
"rpc",
|
||||
"session_manager",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.2"
|
||||
@ -6795,10 +6810,11 @@ dependencies = [
|
||||
"prost 0.14.3",
|
||||
"prost-types 0.14.3",
|
||||
"session_manager",
|
||||
"slog",
|
||||
"tokio",
|
||||
"tonic 0.14.5",
|
||||
"tonic-prost",
|
||||
"tonic-prost-build",
|
||||
"tracing",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
@ -7589,9 +7605,9 @@ dependencies = [
|
||||
"redis",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"slog",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ members = [
|
||||
"libs/agent-tool-derive",
|
||||
"apps/migrate",
|
||||
"apps/app",
|
||||
"apps/adminrpc",
|
||||
"apps/git-hook",
|
||||
"apps/gitserver",
|
||||
"apps/email",
|
||||
|
||||
44
apps/adminrpc/Cargo.toml
Normal file
44
apps/adminrpc/Cargo.toml
Normal file
@ -0,0 +1,44 @@
|
||||
[package]
|
||||
name = "adminrpc"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
repository.workspace = true
|
||||
readme.workspace = true
|
||||
homepage.workspace = true
|
||||
license.workspace = true
|
||||
keywords.workspace = true
|
||||
categories.workspace = true
|
||||
documentation.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "adminrpc"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
# gRPC
|
||||
rpc = { workspace = true }
|
||||
|
||||
# Session / Redis
|
||||
session_manager = { workspace = true }
|
||||
deadpool-redis = { workspace = true, features = ["cluster"] }
|
||||
|
||||
# Observability
|
||||
observability = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
# Config
|
||||
config = { workspace = true }
|
||||
|
||||
# Utilities
|
||||
anyhow = { workspace = true }
|
||||
|
||||
# Async runtime
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "signal"] }
|
||||
|
||||
# CLI
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
9
apps/adminrpc/src/args.rs
Normal file
9
apps/adminrpc/src/args.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name = "adminrpc")]
|
||||
pub struct Args {
|
||||
/// Override the bind address (default: 0.0.0.0:9090)
|
||||
#[arg(short, long)]
|
||||
pub bind: Option<String>,
|
||||
}
|
||||
68
apps/adminrpc/src/main.rs
Normal file
68
apps/adminrpc/src/main.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use std::net::SocketAddr;
|
||||
use anyhow::Context as _;
|
||||
use clap::Parser;
|
||||
use config::AppConfig;
|
||||
use deadpool_redis::{cluster, Runtime};
|
||||
use session_manager::{SessionManager, SessionStorage};
|
||||
use rpc::admin::server::{serve, DEFAULT_GRPC_PORT};
|
||||
|
||||
mod args;
|
||||
use args::Args;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let cfg = AppConfig::load();
|
||||
let log_level = cfg.log_level().unwrap_or_else(|_| "info".to_string());
|
||||
observability::init_tracing_subscriber(&log_level);
|
||||
|
||||
let args = Args::parse();
|
||||
let bind_addr: SocketAddr = args
|
||||
.bind
|
||||
.map(|s| s.parse())
|
||||
.unwrap_or_else(|| format!("0.0.0.0:{}", DEFAULT_GRPC_PORT).parse())
|
||||
.context("invalid bind address")?;
|
||||
|
||||
tracing::info!(
|
||||
app_name = %cfg.app_name().unwrap_or_default(),
|
||||
bind_addr = %bind_addr,
|
||||
"Starting admin RPC server"
|
||||
);
|
||||
|
||||
// ── Phase 6: OTLP tracing ──────────────────────────────────────────────
|
||||
let _otel_guard = if cfg.otel_enabled().unwrap_or(false) {
|
||||
let endpoint = cfg.otel_endpoint().unwrap_or_else(|_| "http://localhost:4317".to_string());
|
||||
let service_name = cfg.otel_service_name().unwrap_or_else(|_| "adminrpc".to_string());
|
||||
let service_version = cfg.otel_service_version().unwrap_or_else(|_| "0.1.0".to_string());
|
||||
tracing::info!(endpoint = %endpoint, service = %service_name, "OTLP tracing enabled");
|
||||
let guard = observability::init_otlp(&endpoint, &service_name, &service_version, &log_level)
|
||||
.map_err(|e| anyhow::anyhow!("OTLP init failed: {}", e))?;
|
||||
guard
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Redis connection pool
|
||||
let redis_url = cfg.redis_url()?;
|
||||
tracing::info!(redis_url = %redis_url, "Connecting to Redis");
|
||||
let manager = cluster::Manager::new(vec![redis_url.clone()], false)
|
||||
.map_err(|e| anyhow::anyhow!("failed to create redis cluster manager: {}", e))?;
|
||||
let pool: cluster::Pool = cluster::Pool::builder(manager)
|
||||
.max_size(16)
|
||||
.runtime(Runtime::Tokio1)
|
||||
.build()
|
||||
.map_err(|e| anyhow::anyhow!("failed to build redis pool: {}", e))?;
|
||||
|
||||
// Test connection
|
||||
let _conn = pool.get().await
|
||||
.context("redis pool connection failed")?;
|
||||
tracing::info!("Redis connected");
|
||||
|
||||
let storage = SessionStorage::new(pool);
|
||||
let session_manager = SessionManager::new(storage);
|
||||
|
||||
tracing::info!(addr = %bind_addr, "Admin gRPC server listening");
|
||||
serve(bind_addr, session_manager).await?;
|
||||
|
||||
tracing::info!("Admin RPC server stopped");
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user