Skip to content

Commit 0fcca71

Browse files
committed
model
1 parent d548813 commit 0fcca71

File tree

6 files changed

+65
-11
lines changed

6 files changed

+65
-11
lines changed

lib/bencher_schema/src/macros/rate_limit.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
error::BencherResource,
77
model::{
88
organization::QueryOrganization,
9-
project::{branch::QueryBranch, QueryProject},
9+
project::{branch::QueryBranch, threshold::QueryThreshold, QueryProject},
1010
user::QueryUser,
1111
},
1212
};
@@ -17,6 +17,11 @@ pub const CLAIMED_RATE_LIMIT: u32 = u16::MAX as u32;
1717

1818
#[derive(Debug, thiserror::Error)]
1919
pub enum RateLimitError {
20+
#[error("User ({uuid}) has exceeded the daily rate limit ({UNCLAIMED_RATE_LIMIT}) for {resource} creation. Please, reduce your daily usage.", uuid = user.uuid)]
21+
User {
22+
user: QueryUser,
23+
resource: BencherResource,
24+
},
2025
#[error("Organization ({uuid}) has exceeded the daily rate limit ({UNCLAIMED_RATE_LIMIT}) for {resource} creation. Please, reduce your daily usage.", uuid = organization.uuid)]
2126
Organization {
2227
organization: QueryOrganization,
@@ -32,14 +37,14 @@ pub enum RateLimitError {
3237
project: QueryProject,
3338
resource: BencherResource,
3439
},
35-
#[error("Branch ({uuid}) has exceeded the daily rate limit ({UNCLAIMED_RATE_LIMIT}) for {resource} creation. Please, reduce your daily usage.", uuid = branch.uuid)]
40+
#[error("Branch ({uuid}) has exceeded the daily rate limit ({CLAIMED_RATE_LIMIT}) for {resource} creation. Please, reduce your daily usage.", uuid = branch.uuid)]
3641
Branch {
3742
branch: QueryBranch,
3843
resource: BencherResource,
3944
},
40-
#[error("User ({uuid}) has exceeded the daily rate limit ({UNCLAIMED_RATE_LIMIT}) for {resource} creation. Please, reduce your daily usage.", uuid = user.uuid)]
41-
User {
42-
user: QueryUser,
45+
#[error("Threshold ({uuid}) has exceeded the daily rate limit ({CLAIMED_RATE_LIMIT}) for {resource} creation. Please, reduce your daily usage.", uuid = threshold.uuid)]
46+
Threshold {
47+
threshold: QueryThreshold,
4348
resource: BencherResource,
4449
},
4550
}

lib/bencher_schema/src/model/organization/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ impl InsertOrganization {
316316
.filter(schema::organization::created.le(end_time))
317317
.count()
318318
.get_result::<i64>(conn_lock!(context))
319-
.map_err(resource_not_found_err!(Token, (query_user, start_time, end_time)))?
319+
.map_err(resource_not_found_err!(Organization, (query_user, start_time, end_time)))?
320320
.try_into()
321321
.map_err(|e| {
322322
issue_error(

lib/bencher_schema/src/model/project/branch/head.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl InsertHead {
219219
.filter(schema::head::created.le(end_time))
220220
.count()
221221
.get_result::<i64>(conn_lock!(context))
222-
.map_err(resource_not_found_err!(Token, (query_branch, start_time, end_time)))?
222+
.map_err(resource_not_found_err!(Head, (query_branch, start_time, end_time)))?
223223
.try_into()
224224
.map_err(|e| {
225225
issue_error(

lib/bencher_schema/src/model/project/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ impl InsertProject {
513513
.filter(schema::project::created.le(end_time))
514514
.count()
515515
.get_result::<i64>(conn_lock!(context))
516-
.map_err(resource_not_found_err!(Token, (query_organization, start_time, end_time)))?
516+
.map_err(resource_not_found_err!(Project, (query_organization, start_time, end_time)))?
517517
.try_into()
518518
.map_err(|e| {
519519
issue_error(

lib/bencher_schema/src/model/project/threshold/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl QueryThreshold {
8888
(None, None) => Ok(()),
8989
// No current model but a new model,
9090
// insert the new model.
91-
(None, Some(model)) => self.update_from_model(conn_lock!(context), model),
91+
(None, Some(model)) => self.update_from_model(context, model).await,
9292
// Current model but no new model,
9393
// remove the current model.
9494
(Some(_), None) => self.remove_current_model(conn_lock!(context)),
@@ -101,13 +101,19 @@ impl QueryThreshold {
101101
if current_model == model {
102102
Ok(())
103103
} else {
104-
self.update_from_model(conn_lock!(context), model)
104+
self.update_from_model(context, model).await
105105
}
106106
},
107107
}
108108
}
109109

110-
pub fn update_from_model(
110+
async fn update_from_model(&self, context: &ApiContext, model: Model) -> Result<(), HttpError> {
111+
#[cfg(feature = "plus")]
112+
InsertModel::rate_limit(context, self).await?;
113+
self.update_from_model_inner(conn_lock!(context), model)
114+
}
115+
116+
fn update_from_model_inner(
111117
&self,
112118
conn: &mut DbConnection,
113119
model: Model,

lib/bencher_schema/src/model/project/threshold/model.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,49 @@ pub struct InsertModel {
123123
}
124124

125125
impl InsertModel {
126+
#[cfg(feature = "plus")]
127+
pub async fn rate_limit(
128+
context: &crate::ApiContext,
129+
query_threshold: &QueryThreshold,
130+
) -> Result<(), HttpError> {
131+
use crate::{
132+
conn_lock,
133+
error::issue_error,
134+
macros::rate_limit::{one_day, RateLimitError, CLAIMED_RATE_LIMIT},
135+
};
136+
137+
let resource = BencherResource::Model;
138+
let (start_time, end_time) = one_day();
139+
let creation_count: u32 = schema::model::table
140+
.filter(schema::model::threshold_id.eq(query_threshold.id))
141+
.filter(schema::model::created.ge(start_time))
142+
.filter(schema::model::created.le(end_time))
143+
.count()
144+
.get_result::<i64>(conn_lock!(context))
145+
.map_err(resource_not_found_err!(Model, (query_threshold, start_time, end_time)))?
146+
.try_into()
147+
.map_err(|e| {
148+
issue_error(
149+
"Failed to count creation",
150+
&format!("Failed to count {resource} creation for threshold ({uuid}) between {start_time} and {end_time}.", uuid = query_threshold.uuid),
151+
e
152+
)}
153+
)?;
154+
155+
// The only way that new Model can be crated is either through running a Report
156+
// or by updating an existing threshold using the API.
157+
// The running of a Report will be rate limited already for unclaimed projects,
158+
// and the API endpoint to update an existing threshold would require authentication and would therefore be a claimed project.
159+
if creation_count >= CLAIMED_RATE_LIMIT {
160+
Err(crate::error::too_many_requests(RateLimitError::Threshold {
161+
threshold: query_threshold.clone(),
162+
resource,
163+
}))
164+
} else {
165+
Ok(())
166+
}
167+
}
168+
126169
pub fn new(threshold_id: ThresholdId, model: Model) -> Self {
127170
let Model {
128171
test,

0 commit comments

Comments
 (0)