- 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).
164 lines
4.8 KiB
Rust
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)
|
|
}
|
|
}
|