- fix: infinite message loop in workflow orchestrator - feat: restore realtime LLM streaming from report generator to frontend - refactor: major update to provider services (generic workers, workflow adapters) - refactor: common contracts and message definitions updated - feat: enhanced logging and observability in orchestrator - docs: update project management tasks and status - chore: dependency updates and config adjustments
124 lines
3.8 KiB
Rust
124 lines
3.8 KiB
Rust
mod api;
|
|
mod config;
|
|
mod error;
|
|
mod fh_client;
|
|
mod finnhub;
|
|
mod mapping;
|
|
mod message_consumer;
|
|
// mod persistence; // Removed
|
|
mod state;
|
|
mod workflow_adapter;
|
|
mod generic_worker;
|
|
mod config_poller;
|
|
|
|
use crate::config::AppConfig;
|
|
use crate::error::Result;
|
|
use crate::state::AppState;
|
|
use tracing::info;
|
|
use common_contracts::lifecycle::ServiceRegistrar;
|
|
use common_contracts::registry::{ServiceRegistration, ProviderMetadata, ConfigFieldSchema, FieldType, ConfigKey};
|
|
use std::sync::Arc;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
// Initialize logging
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
|
|
.init();
|
|
|
|
info!("Starting finnhub-provider-service...");
|
|
|
|
// Load configuration
|
|
let config = AppConfig::load().map_err(|e| error::AppError::Configuration(e.to_string()))?;
|
|
let port = config.server_port;
|
|
|
|
// Initialize application state
|
|
let app_state = AppState::new(config.clone());
|
|
|
|
// --- Start the config poller ---
|
|
tokio::spawn(config_poller::run_config_poller(app_state.clone()));
|
|
|
|
// Create the Axum router
|
|
let app = api::create_router(app_state.clone());
|
|
|
|
// --- Start the message consumer ---
|
|
tokio::spawn(message_consumer::run(app_state));
|
|
|
|
// --- Service Registration ---
|
|
let registrar = ServiceRegistrar::new(
|
|
config.api_gateway_url.clone(),
|
|
ServiceRegistration {
|
|
service_id: format!("{}-{}", "finnhub-provider", uuid::Uuid::new_v4()),
|
|
service_name: "finnhub".to_string(),
|
|
role: common_contracts::registry::ServiceRole::DataProvider,
|
|
base_url: format!("http://{}:{}", config.service_host, port),
|
|
health_check_url: format!("http://{}:{}/health", config.service_host, port),
|
|
metadata: Some(ProviderMetadata {
|
|
id: "finnhub".to_string(),
|
|
name_en: "Finnhub".to_string(),
|
|
name_cn: "Finnhub".to_string(),
|
|
description: "Finnhub Stock API".to_string(),
|
|
icon_url: None,
|
|
config_schema: vec![
|
|
ConfigFieldSchema {
|
|
key: ConfigKey::ApiKey,
|
|
label: "API Key".to_string(),
|
|
field_type: FieldType::Password,
|
|
required: true,
|
|
placeholder: Some("Enter your API key...".to_string()),
|
|
default_value: None,
|
|
description: Some("Get it from https://finnhub.io".to_string()),
|
|
options: None,
|
|
},
|
|
],
|
|
supports_test_connection: true,
|
|
}),
|
|
}
|
|
);
|
|
|
|
let _ = registrar.register().await;
|
|
|
|
let registrar = Arc::new(registrar);
|
|
tokio::spawn(registrar.clone().start_heartbeat_loop());
|
|
|
|
// Start the HTTP server
|
|
let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", port))
|
|
.await
|
|
.unwrap();
|
|
info!("HTTP server listening on port {}", port);
|
|
|
|
axum::serve(listener, app)
|
|
.with_graceful_shutdown(shutdown_signal(registrar))
|
|
.await
|
|
.unwrap();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn shutdown_signal(registrar: Arc<ServiceRegistrar>) {
|
|
let ctrl_c = async {
|
|
tokio::signal::ctrl_c()
|
|
.await
|
|
.expect("failed to install Ctrl+C handler");
|
|
};
|
|
|
|
#[cfg(unix)]
|
|
let terminate = async {
|
|
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
|
|
.expect("failed to install signal handler")
|
|
.recv()
|
|
.await;
|
|
};
|
|
|
|
#[cfg(not(unix))]
|
|
let terminate = std::future::pending::<()>();
|
|
|
|
tokio::select! {
|
|
_ = ctrl_c => {},
|
|
_ = terminate => {},
|
|
}
|
|
|
|
info!("Shutdown signal received, deregistering service...");
|
|
let _ = registrar.deregister().await;
|
|
}
|