Implement Client trait for StreamContext (#134)

Signed-off-by: José Ulises Niño Rivera <junr03@users.noreply.github.com>
This commit is contained in:
José Ulises Niño Rivera 2024-10-07 19:50:15 -04:00 committed by GitHub
parent 5bfccd3959
commit c1cfbcd44d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 216 additions and 218 deletions

View file

@ -2,6 +2,7 @@ use governor::{DefaultKeyedRateLimiter, InsufficientCapacity, Quota};
use log::debug;
use public_types::configuration;
use public_types::configuration::{Limit, Ratelimit, TimeUnit};
use std::fmt::Display;
use std::num::{NonZero, NonZeroU32};
use std::sync::RwLock;
use std::{collections::HashMap, sync::OnceLock};
@ -28,13 +29,18 @@ pub struct RatelimitMap {
}
// This version of Header demands that the user passes a header value to match on.
#[allow(unused)]
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Header {
pub key: String,
pub value: String,
}
impl Display for Header {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
impl From<Header> for configuration::Header {
fn from(header: Header) -> Self {
Self {
@ -44,6 +50,16 @@ impl From<Header> for configuration::Header {
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("exceeded limit provider={provider}, selector={selector}, tokens_used={tokens_used}")]
ExceededLimit {
provider: String,
selector: Header,
tokens_used: NonZeroU32,
},
}
impl RatelimitMap {
// n.b new is private so that the only access to the Ratelimits can be done via the static
// reference inside a RwLock via ratelimit::ratelimits().
@ -82,7 +98,7 @@ impl RatelimitMap {
provider: String,
selector: Header,
tokens_used: NonZeroU32,
) -> Result<(), String> {
) -> Result<(), Error> {
debug!(
"Checking limit for provider={}, with selector={:?}, consuming tokens={:?}",
provider, selector, tokens_used
@ -96,7 +112,7 @@ impl RatelimitMap {
Some(limit) => limit,
};
let mut config_selector = configuration::Header::from(selector);
let mut config_selector = configuration::Header::from(selector.clone());
let (limit, limit_key) = match provider_limits.get(&config_selector) {
// This is a specific limit, i.e one that was configured with both key, and value.
@ -119,8 +135,11 @@ impl RatelimitMap {
match limit.check_key_n(&limit_key, tokens_used) {
Ok(Ok(())) => Ok(()),
Ok(Err(_)) => Err(String::from("Not allowed")),
Err(InsufficientCapacity(_)) => Err(String::from("Not allowed")),
Ok(Err(_)) | Err(InsufficientCapacity(_)) => Err(Error::ExceededLimit {
provider,
selector,
tokens_used,
}),
}
}
}