refactor(api-server): narrow puzzle state surface

This commit is contained in:
kdletters
2026-05-21 18:55:25 +08:00
parent cc23b6020d
commit 5834a99107
31 changed files with 1087 additions and 169 deletions

View File

@@ -141,6 +141,86 @@ impl FromRef<AppState> for BackpressureState {
}
}
#[derive(Clone, Debug)]
pub struct PuzzleApiState {
root_state: AppState,
spacetime_client: SpacetimeClient,
puzzle_gallery_cache: PuzzleGalleryCache,
oss_client: Option<OssClient>,
auth_user_service: AuthUserService,
llm_client: Option<LlmClient>,
creative_agent_gpt5_client: Option<LlmClient>,
creation_agent_llm_web_search_enabled: bool,
vector_engine_image_request_timeout_ms: u64,
}
impl PuzzleApiState {
pub fn root_state(&self) -> &AppState {
&self.root_state
}
pub fn spacetime_client(&self) -> &SpacetimeClient {
&self.spacetime_client
}
pub fn puzzle_gallery_cache(&self) -> &PuzzleGalleryCache {
&self.puzzle_gallery_cache
}
pub fn oss_client(&self) -> Option<&OssClient> {
self.oss_client.as_ref()
}
pub fn auth_user_service(&self) -> &AuthUserService {
&self.auth_user_service
}
pub fn llm_client(&self) -> Option<&LlmClient> {
self.llm_client.as_ref()
}
pub fn creative_agent_gpt5_client(&self) -> Option<&LlmClient> {
self.creative_agent_gpt5_client.as_ref()
}
pub fn creation_agent_llm_web_search_enabled(&self) -> bool {
self.creation_agent_llm_web_search_enabled
}
pub fn vector_engine_image_request_timeout_ms(&self) -> u64 {
self.vector_engine_image_request_timeout_ms
}
pub fn vector_engine_base_url(&self) -> &str {
self.root_state.config.vector_engine_base_url.as_str()
}
pub fn vector_engine_api_key(&self) -> Option<&str> {
self.root_state.config.vector_engine_api_key.as_deref()
}
}
impl FromRef<AppState> for PuzzleApiState {
fn from_ref(state: &AppState) -> Self {
// 中文注释:拼图路由只暴露本能力需要的依赖快照,避免 handler 直接看见完整 AppState。
Self {
root_state: state.clone(),
spacetime_client: state.spacetime_client.clone(),
puzzle_gallery_cache: state.puzzle_gallery_cache.clone(),
oss_client: state.oss_client.clone(),
auth_user_service: state.auth_user_service.clone(),
llm_client: state.llm_client.clone(),
creative_agent_gpt5_client: state.creative_agent_gpt5_client.clone(),
creation_agent_llm_web_search_enabled: state
.config
.creation_agent_llm_web_search_enabled,
vector_engine_image_request_timeout_ms: state
.config
.vector_engine_image_request_timeout_ms,
}
}
}
// Axum/Hyper 会在路由树和连接 service 上频繁 clone stateAppState 外层必须保持浅拷贝。
#[derive(Debug)]
pub struct AppStateInner {
@@ -1319,4 +1399,23 @@ mod tests {
);
assert!(client.config().official_fallback());
}
#[test]
fn puzzle_api_state_exposes_puzzle_dependency_snapshot() {
let mut config = AppConfig::default();
config.creation_agent_llm_web_search_enabled = false;
config.vector_engine_image_request_timeout_ms = 987_654;
let state = AppState::new(config).expect("state should build");
let puzzle_state: PuzzleApiState = FromRef::from_ref(&state);
assert!(!puzzle_state.creation_agent_llm_web_search_enabled());
assert_eq!(
puzzle_state.vector_engine_image_request_timeout_ms(),
987_654
);
assert!(puzzle_state.llm_client().is_none());
assert!(puzzle_state.creative_agent_gpt5_client().is_none());
assert!(puzzle_state.oss_client().is_none());
}
}