Fundamental_Analysis/services/api-gateway/src/persistence.rs
Lv, Qi 0cb31e363e Refactor E2E tests and improve error handling in Orchestrator
- Fix `simple_test_analysis` template in E2E test setup to align with Orchestrator's data fetch logic.
- Implement and verify additional E2E scenarios:
    - Scenario C: Partial Provider Failure (verified error propagation fix in Orchestrator).
    - Scenario D: Invalid Symbol input.
    - Scenario E: Analysis Module failure.
- Update `WorkflowStateMachine::handle_report_failed` to correctly scope error broadcasting to the specific task instead of failing effectively silently or broadly.
- Update testing strategy documentation to reflect completed Phase 4 testing.
- Skip Scenario B (Orchestrator Restart) as persistence is not yet implemented (decision made to defer persistence).
2025-11-21 20:44:32 +08:00

164 lines
4.8 KiB
Rust

//!
//! 数据持久化服务客户端
//!
use crate::error::Result;
use common_contracts::dtos::{CompanyProfileDto, TimeSeriesFinancialDto};
use common_contracts::config_models::{LlmProvidersConfig, DataSourcesConfig, AnalysisTemplateSets};
#[derive(Clone)]
pub struct PersistenceClient {
client: reqwest::Client,
base_url: String,
}
impl PersistenceClient {
pub fn new(base_url: String) -> Self {
Self {
client: reqwest::Client::new(),
base_url,
}
}
pub async fn get_company_profile(&self, symbol: &str) -> Result<CompanyProfileDto> {
let url = format!("{}/companies/{}", self.base_url, symbol);
let profile = self
.client
.get(&url)
.send()
.await?
.error_for_status()?
.json::<CompanyProfileDto>()
.await?;
Ok(profile)
}
pub async fn get_financials(&self, symbol: &str) -> Result<Vec<TimeSeriesFinancialDto>> {
let url = format!("{}/market-data/financial-statements/{}", self.base_url, symbol);
let financials = self
.client
.get(&url)
.send()
.await?
.error_for_status()?
.json::<Vec<TimeSeriesFinancialDto>>()
.await?;
Ok(financials)
}
pub async fn get_session_data(&self, request_id: uuid::Uuid) -> Result<Vec<common_contracts::dtos::SessionDataDto>> {
let url = format!("{}/session-data/{}", self.base_url, request_id);
let data = self
.client
.get(&url)
.send()
.await?
.error_for_status()?
.json::<Vec<common_contracts::dtos::SessionDataDto>>()
.await?;
Ok(data)
}
pub async fn get_analysis_results(&self, symbol: &str) -> Result<Vec<common_contracts::dtos::AnalysisResultDto>> {
let url = format!("{}/analysis-results?symbol={}", self.base_url, symbol);
let results = self
.client
.get(&url)
.send()
.await?
.error_for_status()?
.json::<Vec<common_contracts::dtos::AnalysisResultDto>>()
.await?;
Ok(results)
}
// --- Config Methods ---
pub async fn get_llm_providers_config(&self) -> Result<LlmProvidersConfig> {
let url = format!("{}/configs/llm_providers", self.base_url);
let config = self
.client
.get(&url)
.send()
.await?
.error_for_status()?
.json::<LlmProvidersConfig>()
.await?;
Ok(config)
}
pub async fn update_llm_providers_config(
&self,
payload: &LlmProvidersConfig,
) -> Result<LlmProvidersConfig> {
let url = format!("{}/configs/llm_providers", self.base_url);
let updated_config = self
.client
.put(&url)
.json(payload)
.send()
.await?
.error_for_status()?
.json::<LlmProvidersConfig>()
.await?;
Ok(updated_config)
}
pub async fn get_analysis_template_sets(&self) -> Result<AnalysisTemplateSets> {
let url = format!("{}/configs/analysis_template_sets", self.base_url);
let config = self
.client
.get(&url)
.send()
.await?
.error_for_status()?
.json::<AnalysisTemplateSets>()
.await?;
Ok(config)
}
pub async fn update_analysis_template_sets(
&self,
payload: &AnalysisTemplateSets,
) -> Result<AnalysisTemplateSets> {
let url = format!("{}/configs/analysis_template_sets", self.base_url);
let updated_config = self
.client
.put(&url)
.json(payload)
.send()
.await?
.error_for_status()?
.json::<AnalysisTemplateSets>()
.await?;
Ok(updated_config)
}
pub async fn get_data_sources_config(&self) -> Result<DataSourcesConfig> {
let url = format!("{}/configs/data_sources", self.base_url);
let config = self
.client
.get(&url)
.send()
.await?
.error_for_status()?
.json::<DataSourcesConfig>()
.await?;
Ok(config)
}
pub async fn update_data_sources_config(&self, payload: &DataSourcesConfig) -> Result<DataSourcesConfig> {
let url = format!("{}/configs/data_sources", self.base_url);
let updated_config = self
.client
.put(&url)
.json(payload)
.send()
.await?
.error_for_status()?
.json::<DataSourcesConfig>()
.await?;
Ok(updated_config)
}
}