refactor: replace anyhow with thiserror for typed error handling

main
Yoo1tic 2025-07-28 20:23:27 +08:00
parent 660367d8a3
commit f10c2a8afb
8 changed files with 36 additions and 26 deletions

24
Cargo.lock generated
View File

@ -568,7 +568,7 @@ dependencies = [
"libc", "libc",
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2 0.5.10",
"tokio", "tokio",
"tower-service", "tower-service",
"tracing", "tracing",
@ -930,7 +930,7 @@ dependencies = [
"quinn-udp", "quinn-udp",
"rustc-hash", "rustc-hash",
"rustls", "rustls",
"socket2", "socket2 0.5.10",
"thiserror", "thiserror",
"tokio", "tokio",
"tracing", "tracing",
@ -967,7 +967,7 @@ dependencies = [
"cfg_aliases", "cfg_aliases",
"libc", "libc",
"once_cell", "once_cell",
"socket2", "socket2 0.5.10",
"tracing", "tracing",
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
@ -1247,6 +1247,16 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "socket2"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
dependencies = [
"libc",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.0" version = "1.2.0"
@ -1343,9 +1353,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.46.1" version = "1.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
@ -1354,9 +1364,9 @@ dependencies = [
"mio", "mio",
"pin-project-lite", "pin-project-lite",
"slab", "slab",
"socket2", "socket2 0.6.0",
"tokio-macros", "tokio-macros",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]

View File

@ -5,13 +5,13 @@ edition = "2024"
[dependencies] [dependencies]
mimalloc = { version = "*" } mimalloc = { version = "*" }
backon = "1" backon = "1.5"
clap = { version = "4.5", features = ["derive"] } clap = { version = "4.5", features = ["derive"] }
futures = "0.3" futures = "0.3"
regex = "1.11" regex = "1.11"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls","http2"] } reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls","http2"] }
serde_json = "1.0" serde_json = "1.0"
tokio = { version = "1.46", features = [ tokio = { version = "1.47", features = [
"macros", "macros",
"rt-multi-thread", "rt-multi-thread",
"time", "time",
@ -22,4 +22,4 @@ async-stream = "0.3"
figment = { version = "0.10", features = ["env", "toml"] } figment = { version = "0.10", features = ["env", "toml"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
toml = "0.9" toml = "0.9"
thiserror = "2.0.12" thiserror = "2.0"

View File

@ -1,4 +1,4 @@
use crate::error::ValidationError; use crate::error::ValidatorError;
use clap::Parser; use clap::Parser;
use figment::{ use figment::{
Figment, Figment,
@ -85,7 +85,7 @@ impl Default for KeyCheckerConfig {
} }
} }
impl KeyCheckerConfig { impl KeyCheckerConfig {
pub fn load_config() -> Result<Self, ValidationError> { pub fn load_config() -> Result<Self, ValidatorError> {
// Define the path to the configuration file // Define the path to the configuration file
static CONFIG_PATH: LazyLock<PathBuf> = LazyLock::new(|| "Config.toml".into()); static CONFIG_PATH: LazyLock<PathBuf> = LazyLock::new(|| "Config.toml".into());

View File

@ -1,7 +1,7 @@
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ValidationError { pub enum ValidatorError {
#[error("HTTP error: {0}")] #[error("HTTP error: {0}")]
ReqwestError(#[from] reqwest::Error), ReqwestError(#[from] reqwest::Error),
@ -30,4 +30,4 @@ pub enum ValidationError {
Validation(String), Validation(String),
} }
pub type Result<T> = std::result::Result<T, ValidationError>; pub type Result<T> = std::result::Result<T, ValidatorError>;

View File

@ -1,4 +1,4 @@
use gemini_keychecker::error::ValidationError; use gemini_keychecker::error::ValidatorError;
use gemini_keychecker::{BANNER, config::KeyCheckerConfig, service::start_validation}; use gemini_keychecker::{BANNER, config::KeyCheckerConfig, service::start_validation};
use mimalloc::MiMalloc; use mimalloc::MiMalloc;
@ -8,7 +8,7 @@ static GLOBAL: MiMalloc = MiMalloc;
/// Main function - displays banner and starts validation service /// Main function - displays banner and starts validation service
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), ValidationError> { async fn main() -> Result<(), ValidatorError> {
// Display banner and configuration status at startup // Display banner and configuration status at startup
println!("{BANNER}"); println!("{BANNER}");

View File

@ -1,8 +1,8 @@
use crate::{config::KeyCheckerConfig, error::ValidationError}; use crate::{config::KeyCheckerConfig, error::ValidatorError};
use reqwest::Client; use reqwest::Client;
use std::time::Duration; use std::time::Duration;
pub fn client_builder(config: &KeyCheckerConfig) -> Result<Client, ValidationError> { pub fn client_builder(config: &KeyCheckerConfig) -> Result<Client, ValidatorError> {
// Set the maximum number of connections per host based on concurrency. // Set the maximum number of connections per host based on concurrency.
let pool_size = config.concurrency / 2; let pool_size = config.concurrency / 2;

View File

@ -4,14 +4,14 @@ use tokio::time::Duration;
use url::Url; use url::Url;
use crate::config::TEST_MESSAGE_BODY; use crate::config::TEST_MESSAGE_BODY;
use crate::error::ValidationError; use crate::error::ValidatorError;
use crate::types::GeminiKey; use crate::types::GeminiKey;
pub async fn validate_key( pub async fn validate_key(
client: Client, client: Client,
api_endpoint: impl IntoUrl, api_endpoint: impl IntoUrl,
api_key: GeminiKey, api_key: GeminiKey,
) -> Result<GeminiKey, ValidationError> { ) -> Result<GeminiKey, ValidatorError> {
let api_endpoint = api_endpoint.into_url()?; let api_endpoint = api_endpoint.into_url()?;
match send_test_request(client, &api_endpoint, api_key.clone()).await { match send_test_request(client, &api_endpoint, api_key.clone()).await {
@ -21,13 +21,13 @@ pub async fn validate_key(
StatusCode::OK => Ok(api_key), StatusCode::OK => Ok(api_key),
StatusCode::UNAUTHORIZED StatusCode::UNAUTHORIZED
| StatusCode::FORBIDDEN | StatusCode::FORBIDDEN
| StatusCode::TOO_MANY_REQUESTS => Err(ValidationError::KeyInvalid), | StatusCode::TOO_MANY_REQUESTS => Err(ValidatorError::KeyInvalid),
_ => Err(ValidationError::ReqwestError( _ => Err(ValidatorError::ReqwestError(
response.error_for_status().unwrap_err(), response.error_for_status().unwrap_err(),
)), )),
} }
} }
Err(e) => Err(ValidationError::ReqwestError(e)), Err(e) => Err(ValidatorError::ReqwestError(e)),
} }
} }

View File

@ -1,4 +1,4 @@
use crate::error::ValidationError; use crate::error::ValidatorError;
use async_stream::stream; use async_stream::stream;
use futures::{pin_mut, stream::StreamExt}; use futures::{pin_mut, stream::StreamExt};
use reqwest::Client; use reqwest::Client;
@ -26,7 +26,7 @@ impl ValidationService {
} }
} }
pub async fn validate_keys(&self, keys: Vec<GeminiKey>) -> Result<(), ValidationError> { pub async fn validate_keys(&self, keys: Vec<GeminiKey>) -> Result<(), ValidatorError> {
let start_time = Instant::now(); let start_time = Instant::now();
// Create channel for streaming keys from producer to consumer // Create channel for streaming keys from producer to consumer
@ -74,7 +74,7 @@ impl ValidationService {
} }
/// 启动验证服务 - 封装了所有启动逻辑 /// 启动验证服务 - 封装了所有启动逻辑
pub async fn start_validation() -> Result<(), ValidationError> { pub async fn start_validation() -> Result<(), ValidatorError> {
let config = KeyCheckerConfig::load_config()?; let config = KeyCheckerConfig::load_config()?;
// 加载密钥 // 加载密钥