use acton_service::prelude::*;
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
struct MyCustomConfig {
#[serde(default)]
external_api_key: String,
#[serde(default)]
feature_flags: HashMap<String, bool>,
#[serde(default)]
custom_timeout_ms: u32,
#[serde(default)]
retry_config: RetryConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct RetryConfig {
max_attempts: u32,
backoff_ms: u32,
}
impl Default for RetryConfig {
fn default() -> Self {
Self {
max_attempts: 3,
backoff_ms: 1000,
}
}
}
#[derive(Serialize)]
struct ConfigInfoResponse {
service_name: String,
service_port: u16,
environment: String,
external_api_configured: bool,
enabled_features: Vec<String>,
retry_attempts: u32,
}
async fn config_info(State(state): State<AppState<MyCustomConfig>>) -> Json<ConfigInfoResponse> {
let config = state.config();
let service_name = config.service.name.clone();
let service_port = config.service.port;
let environment = config.service.environment.clone();
let external_api_configured = !config.custom.external_api_key.is_empty();
let enabled_features: Vec<String> = config
.custom
.feature_flags
.iter()
.filter_map(|(k, v)| if *v { Some(k.clone()) } else { None })
.collect();
let retry_attempts = config.custom.retry_config.max_attempts;
Json(ConfigInfoResponse {
service_name,
service_port,
environment,
external_api_configured,
enabled_features,
retry_attempts,
})
}
#[tokio::main]
async fn main() -> Result<()> {
let mut config = Config::<MyCustomConfig>::default();
config.service.name = "my-custom-service".to_string();
config.service.port = 8080;
config.service.environment = "dev".to_string();
config.custom = MyCustomConfig {
external_api_key: "my-secret-key-123".to_string(),
custom_timeout_ms: 5000,
feature_flags: {
let mut flags = HashMap::new();
flags.insert("new_dashboard".to_string(), true);
flags.insert("analytics".to_string(), false);
flags
},
retry_config: RetryConfig {
max_attempts: 5,
backoff_ms: 2000,
},
};
let routes = VersionedApiBuilder::<MyCustomConfig>::with_config()
.with_base_path("/api")
.add_version(ApiVersion::V1, |routes| {
routes.route("/config-info", get(config_info))
})
.build_routes();
ServiceBuilder::<MyCustomConfig>::new()
.with_config(config)
.with_routes(routes) .build()
.serve()
.await?;
Ok(())
}