use crate::settings::Settings;
use crate::stats::Stats;
use redis::{Client, RedisResult, Script};
use std::fs::read_to_string;
use std::thread;
#[derive(Clone)]
pub struct Bouncer<'a> {
pub key: u8,
pub rate_limit: u8,
pub wait_time: u8,
pub block: &'a dyn Fn(),
}
impl<'a> Default for Bouncer<'a> {
fn default() -> Bouncer<'a> {
Bouncer {
key: 1,
rate_limit: 5,
wait_time: 2,
block: &|| println!("Nothing to execute"),
}
}
}
impl<'a> Bouncer<'a> {
pub fn new(block: &'a dyn Fn()) -> Bouncer {
let mut bouncer = Bouncer::default();
bouncer.block = block;
bouncer
}
pub fn key(&'a mut self, key: u8) -> &'a mut Bouncer {
self.key = key;
self
}
pub fn rate_limit(&'a mut self, rate_limit: u8) -> &'a mut Bouncer {
self.rate_limit = rate_limit;
self
}
pub fn wait_time(&'a mut self, wait_time: u8) -> &'a mut Bouncer {
self.wait_time = wait_time;
self
}
pub fn run(&self) -> RedisResult<Stats> {
match Settings::new() {
Ok(settings) => {
let raw_script = read_to_string(settings.redis_script())?;
let script = Script::new(raw_script.as_str());
let client = Client::open(settings.redis_url())?;
let mut connection = client.get_connection()?;
loop {
let stats: Stats = script
.key(self.key)
.arg(self.rate_limit)
.arg(self.wait_time)
.invoke(&mut connection)
.unwrap();
if stats == Stats::default() {
(self.block)();
break Ok(stats);
} else {
thread::sleep(stats.wait)
}
}
}
Err(error) => panic!("{}", error),
}
}
}