mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-25 01:02:15 +00:00
fix(rust): restore hot-path opt levels and validate s3 binding destination
Keep sigv4 signing, eventstream decoding, smithy runtime api and types at opt-level 3 since they serve Bedrock request and streaming hot paths, and make the S3 facade binding reject region and endpoint mismatches between the projected configuration and the native handle Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
0672fcbafe
commit
793efe3eb4
4 changed files with 88 additions and 11 deletions
|
|
@ -103,8 +103,6 @@ opt-level = "s"
|
|||
[profile.release.package."aws-sdk-sts"]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package."aws-sigv4"]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package."aws-smithy-async"]
|
||||
opt-level = "s"
|
||||
|
|
@ -112,8 +110,6 @@ opt-level = "s"
|
|||
[profile.release.package."aws-smithy-checksums"]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package."aws-smithy-eventstream"]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package."aws-smithy-http"]
|
||||
opt-level = "s"
|
||||
|
|
@ -133,8 +129,6 @@ opt-level = "s"
|
|||
[profile.release.package."aws-smithy-runtime"]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package."aws-smithy-runtime-api"]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package."aws-smithy-runtime-api-macros"]
|
||||
opt-level = "s"
|
||||
|
|
@ -142,8 +136,6 @@ opt-level = "s"
|
|||
[profile.release.package."aws-smithy-schema"]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package."aws-smithy-types"]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release.package."aws-smithy-xml"]
|
||||
opt-level = "s"
|
||||
|
|
|
|||
|
|
@ -36,18 +36,21 @@ pub struct S3Cache<C: CacheCodec> {
|
|||
runtime: Handle,
|
||||
bucket: Arc<str>,
|
||||
key_prefix: Arc<str>,
|
||||
region: Arc<str>,
|
||||
endpoint: Option<Arc<str>>,
|
||||
}
|
||||
|
||||
impl<C: CacheCodec> S3Cache<C> {
|
||||
pub fn new(config: S3CacheConfig, codec: C, runtime: Handle) -> Self {
|
||||
let mut builder = aws_sdk_s3::Config::builder()
|
||||
.behavior_version(BehaviorVersion::latest())
|
||||
.region(Region::new(config.region))
|
||||
.region(Region::new(config.region.clone()))
|
||||
.credentials_provider(Credentials::new(config.auth))
|
||||
.request_checksum_calculation(RequestChecksumCalculation::WhenRequired)
|
||||
.response_checksum_validation(ResponseChecksumValidation::WhenRequired);
|
||||
if let Some(endpoint) = config.endpoint {
|
||||
builder = builder.endpoint_url(endpoint.url).force_path_style(true);
|
||||
let endpoint_url: Option<String> = config.endpoint.map(|endpoint| endpoint.url);
|
||||
if let Some(url) = &endpoint_url {
|
||||
builder = builder.endpoint_url(url).force_path_style(true);
|
||||
}
|
||||
Self {
|
||||
client: aws_sdk_s3::Client::from_conf(builder.build()),
|
||||
|
|
@ -55,6 +58,8 @@ impl<C: CacheCodec> S3Cache<C> {
|
|||
runtime,
|
||||
bucket: config.bucket.into(),
|
||||
key_prefix: config.key_prefix.into(),
|
||||
region: config.region.into(),
|
||||
endpoint: endpoint_url.map(Into::into),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,6 +71,14 @@ impl<C: CacheCodec> S3Cache<C> {
|
|||
&self.key_prefix
|
||||
}
|
||||
|
||||
pub fn region(&self) -> &str {
|
||||
&self.region
|
||||
}
|
||||
|
||||
pub fn endpoint(&self) -> Option<&str> {
|
||||
self.endpoint.as_deref()
|
||||
}
|
||||
|
||||
pub fn to_s3_key(&self, key: &str) -> String {
|
||||
format!("{}{}", self.key_prefix, key.replace(':', "/"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,6 +212,18 @@ impl NativeCacheConfig {
|
|||
{
|
||||
Some("facade and native backend key prefixes must match")
|
||||
}
|
||||
CacheBackendConfig::S3(config) if service.region() != Some(config.region.as_str()) => {
|
||||
Some("facade and native backend regions must match")
|
||||
}
|
||||
CacheBackendConfig::S3(config)
|
||||
if service.endpoint()
|
||||
!= config
|
||||
.endpoint
|
||||
.as_ref()
|
||||
.map(|endpoint| endpoint.url.as_str()) =>
|
||||
{
|
||||
Some("facade and native backend endpoints must match")
|
||||
}
|
||||
CacheBackendConfig::S3(_) => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -593,6 +605,10 @@ mod tests {
|
|||
|
||||
use pyo3::{prelude::*, types::PyDict};
|
||||
|
||||
use litellm_auth_aws::AwsAuthConfig;
|
||||
use litellm_cache_s3::{S3CacheConfig, S3Endpoint};
|
||||
use litellm_host_python::run_sync_value;
|
||||
|
||||
use super::{
|
||||
CacheBackendConfig, CacheConfigProjection, CertificateRequirement, NativeCacheConfig,
|
||||
RedisProtocol,
|
||||
|
|
@ -858,4 +874,46 @@ mod tests {
|
|||
assert_eq!(s3.auth.region_name.as_deref(), Some("us-east-1"));
|
||||
});
|
||||
}
|
||||
|
||||
fn s3_service(py: Python<'_>, region: &str, endpoint: Option<&str>) -> NativeResponseCache {
|
||||
let config = S3CacheConfig {
|
||||
bucket: "bucket".to_string(),
|
||||
key_prefix: "team/".to_string(),
|
||||
region: region.to_string(),
|
||||
endpoint: endpoint.map(|url| S3Endpoint {
|
||||
url: url.to_string(),
|
||||
}),
|
||||
auth: AwsAuthConfig::default(),
|
||||
};
|
||||
run_sync_value(py, async move { Ok(NativeResponseCache::s3(config).await) }).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn s3_binding_rejects_region_and_endpoint_mismatches() {
|
||||
Python::initialize();
|
||||
Python::attach(|py| {
|
||||
let facade = s3_facade(py, "");
|
||||
let CacheConfigProjection::Native(config) =
|
||||
NativeCacheConfig::project(&facade).unwrap()
|
||||
else {
|
||||
panic!("S3 cache should be supported");
|
||||
};
|
||||
assert_eq!(
|
||||
config.service_mismatch(&s3_service(py, "us-east-1", Some("https://example.test"))),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
config.service_mismatch(&s3_service(py, "us-west-2", Some("https://example.test"))),
|
||||
Some("facade and native backend regions must match")
|
||||
);
|
||||
assert_eq!(
|
||||
config.service_mismatch(&s3_service(py, "us-east-1", Some("https://other.test"))),
|
||||
Some("facade and native backend endpoints must match")
|
||||
);
|
||||
assert_eq!(
|
||||
config.service_mismatch(&s3_service(py, "us-east-1", None)),
|
||||
Some("facade and native backend endpoints must match")
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,20 @@ impl NativeResponseCache {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn region(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::S3(cache) => Some(cache.backend().region()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn endpoint(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::S3(cache) => cache.backend().endpoint(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn namespace(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::Memory(_) => None,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue