-
-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #145 from kpcyrd/ratelimits
Add ratelimit_throttle
- Loading branch information
Showing
10 changed files
with
164 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
-- Description: Run script with a global ratelimit | ||
-- Version: 0.1.0 | ||
-- License: GPL-3.0 | ||
|
||
function run() | ||
-- this shouldn't complete in less than 5 seconds | ||
for i=1, 20 do | ||
ratelimit_throttle('foo', 4, 1000) | ||
info(sn0int_time()) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use chrono::prelude::*; | ||
use crate::worker::RatelimitSender; | ||
use std::collections::HashMap; | ||
use std::time::Duration; | ||
|
||
pub struct Ratelimiter { | ||
buckets: HashMap<String, Bucket>, | ||
} | ||
|
||
impl Ratelimiter { | ||
pub fn new() -> Ratelimiter { | ||
Ratelimiter { | ||
buckets: HashMap::new(), | ||
} | ||
} | ||
|
||
pub fn pass(&mut self, tx: RatelimitSender, key: &str, passes: u32, time: u32) { | ||
let bucket = if let Some(bucket) = self.buckets.get_mut(key) { | ||
bucket | ||
} else { | ||
let bucket = Bucket::new(); | ||
self.buckets.insert(key.to_string(), bucket); | ||
self.buckets.get_mut(key).unwrap() | ||
}; | ||
let reply = bucket.pass(passes as usize, time); | ||
tx.send(Ok(reply)).unwrap(); | ||
} | ||
} | ||
|
||
struct Bucket { | ||
passes: Vec<DateTime<Utc>>, | ||
} | ||
|
||
impl Bucket { | ||
pub fn new() -> Bucket { | ||
Bucket { | ||
passes: Vec::new(), | ||
} | ||
} | ||
|
||
pub fn pass(&mut self, passes: usize, time: u32) -> RatelimitResponse { | ||
let now = Utc::now(); | ||
let time = chrono::Duration::milliseconds(time as i64); | ||
let retain = now - time; | ||
self.passes.retain(|x| *x >= retain); | ||
|
||
if self.passes.len() >= passes { | ||
if let Some(min) = self.passes.iter().min() { | ||
let delay = time - (now - *min); | ||
RatelimitResponse::Retry(delay.to_std().unwrap()) | ||
} else { | ||
// This should never happen unless passes is zero | ||
RatelimitResponse::Retry(Duration::from_millis(100)) | ||
} | ||
} else { | ||
let now = Utc::now(); | ||
self.passes.push(now); | ||
RatelimitResponse::Pass | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub enum RatelimitResponse { | ||
Retry(Duration), | ||
Pass, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use crate::errors::*; | ||
use crate::engine::ctx::State; | ||
use crate::hlua; | ||
use std::sync::Arc; | ||
|
||
|
||
pub fn ratelimit_throttle(lua: &mut hlua::Lua, state: Arc<dyn State>) { | ||
lua.set("ratelimit_throttle", hlua::function3(move |key: String, passes: u32, time: u32| -> Result<()> { | ||
state.ratelimit(key, passes, time) | ||
.map_err(|e| state.set_error(e)) | ||
})) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters