feat: add provider-key concurrent limit (#352)

* feat: add provider-key concurrent limit

* Fix provider key concurrent limit checks

---------

Co-authored-by: fawney19 <elky0401@gmail.com>
This commit is contained in:
Kayphoon
2026-05-03 01:55:23 +08:00
committed by GitHub
parent 11c5884d4f
commit fe27fb17fb
23 changed files with 1827 additions and 62 deletions

View File

@@ -25,6 +25,8 @@ pub(crate) struct AdminProviderKeyCreateRequest {
#[serde(default)]
pub(crate) rpm_limit: Option<u32>,
#[serde(default)]
pub(crate) concurrent_limit: Option<i32>,
#[serde(default)]
pub(crate) allowed_models: Option<Vec<String>>,
#[serde(default)]
pub(crate) capabilities: Option<serde_json::Value>,
@@ -69,6 +71,8 @@ pub(crate) struct AdminProviderKeyUpdateRequest {
#[serde(default)]
pub(crate) rpm_limit: Option<u32>,
#[serde(default)]
pub(crate) concurrent_limit: Option<i32>,
#[serde(default)]
pub(crate) allowed_models: Option<Vec<String>>,
#[serde(default)]
pub(crate) capabilities: Option<serde_json::Value>,

View File

@@ -9,6 +9,7 @@ use crate::handlers::admin::shared::{
decrypt_catalog_secret_with_fallbacks, encrypt_catalog_secret_with_fallbacks,
normalize_json_object, normalize_string_list, parse_catalog_auth_config_json,
};
use crate::handlers::shared::normalize_optional_api_key_concurrent_limit;
use aether_data_contracts::repository::provider_catalog::{
StoredProviderCatalogKey, StoredProviderCatalogProvider,
};
@@ -178,6 +179,7 @@ pub(crate) async fn build_admin_create_provider_key_record(
.filter(|value| !value.is_empty());
key.internal_priority = payload.internal_priority.unwrap_or(50);
key.rpm_limit = payload.rpm_limit;
key.concurrent_limit = normalize_optional_api_key_concurrent_limit(payload.concurrent_limit)?;
key.cache_ttl_minutes = payload.cache_ttl_minutes.unwrap_or(5);
key.max_probe_interval_minutes = payload.max_probe_interval_minutes.unwrap_or(32);
key.request_count = Some(0);

View File

@@ -9,6 +9,7 @@ use crate::handlers::admin::shared::{
decrypt_catalog_secret_with_fallbacks, encrypt_catalog_secret_with_fallbacks, json_string_list,
normalize_json_object, normalize_string_list, parse_catalog_auth_config_json,
};
use crate::handlers::shared::normalize_optional_api_key_concurrent_limit;
use crate::provider_key_auth::provider_key_is_oauth_managed;
use aether_data_contracts::repository::provider_catalog::{
StoredProviderCatalogKey, StoredProviderCatalogProvider,
@@ -277,6 +278,10 @@ pub(crate) async fn build_admin_update_provider_key_record(
updated.learned_rpm_limit = None;
}
}
if fields.contains("concurrent_limit") {
updated.concurrent_limit =
normalize_optional_api_key_concurrent_limit(payload.concurrent_limit)?;
}
if fields.contains("allowed_models") {
updated.allowed_models =
normalize_string_list(payload.allowed_models).map(|value| json!(value));

View File

@@ -1351,6 +1351,7 @@ pub(crate) fn build_admin_provider_key_response(
json!(key.global_priority_by_format),
);
payload.insert("rpm_limit".to_string(), json!(key.rpm_limit));
payload.insert("concurrent_limit".to_string(), json!(key.concurrent_limit));
payload.insert(
"allowed_models".to_string(),
serde_json::Value::Array(