Skip to content

Instantly share code, notes, and snippets.

@se1983
Last active January 3, 2024 12:51
Show Gist options
  • Save se1983/d0ab09f306f3b2db83369456bd7baba2 to your computer and use it in GitHub Desktop.
Save se1983/d0ab09f306f3b2db83369456bd7baba2 to your computer and use it in GitHub Desktop.
Caching http requests
use ureq;
use std::collections::HashMap;
use std::time::{Instant, Duration};
pub struct Cacher {
call: Box<dyn Fn(&str) -> String>,
data: HashMap<String, (String, Instant)>,
cache_time: Duration,
}
impl Cacher {
pub fn new<T: Fn(&str) -> String + 'static>(call: T) -> Cacher {
Cacher {
call: Box::new(call),
data: HashMap::new(),
cache_time: Duration::from_millis(10000),
}
}
fn data(&mut self, url: &str) -> String {
println!("Calling request {}", &url);
match self.data.get(url) {
Some((data, created)) if created.elapsed() < self.cache_time => data.clone(),
_ => {
let now = Instant::now();
let data = (self.call)(url);
self.data.insert(String::from(url), (data.clone(), now));
data
}
}
}
}
struct Client {
cacher: Cacher
}
impl Client {
pub fn new() -> Client {
Client {
cacher: Cacher::new(|url| {
ureq::get(url).call().into_string().unwrap()
})
}
}
pub fn get(&mut self, url: &str) -> String {
self.cacher.data(url)
}
}
fn main() {
let mut c = Client::new();
println!("{}", c.get("https://www.rust-lang.org/"));
println!("{}", c.get("https://example.com/"));
}
use ureq;
use std::collections::HashMap;
use std::time::{Instant, Duration};
pub struct Cacher<T> where T: Fn(&str) -> String {
call: T,
html: HashMap<String, (String, Instant)>,
cache_time: Duration,
}
impl<T> Cacher<T> where T: Fn(&str) -> String {
pub fn new(call: T) -> Cacher<T> {
Cacher {
call,
html: HashMap::new(),
cache_time: Duration::from_millis(10000),
}
}
fn html(&mut self, url: &str) -> String {
println!("Calling request {}", &url);
match self.html.get(url) {
Some((data, created)) if created.elapsed() < self.cache_time => data.clone(),
_ => {
let now = Instant::now();
let data = (self.call)(url);
self.html.insert(String::from(url), (data.clone(), now));
data
}
}
}
}
fn main() {
let mut request_cacher = Cacher::new(|url| {
ureq::get(url).call().into_string().unwrap()
});
for url in vec![
"https://apod.nasa.gov/apod/archivepix.html",
"https://www.reddit.com/r/all.json?limit=30&count=1"
] {
println!("\nCalling {}", url);
for i in 0..2 {
println!("Request [{}]", i);
let now = Instant::now();
let _ = request_cacher.html(url);
println!("Time elapsed: {} ms.", now.elapsed().as_millis());
}
}
}
@se1983
Copy link
Author

se1983 commented Apr 3, 2020

Calling https://apod.nasa.gov/apod/archivepix.html
Request [0]
Calling request https://apod.nasa.gov/apod/archivepix.html
Time elapsed: 3808 ms.
Request [1]
Calling request https://apod.nasa.gov/apod/archivepix.html
Time elapsed: 0 ms.

Calling https://www.reddit.com/r/all.json?limit=30&count=1
Request [0]
Calling request https://www.reddit.com/r/all.json?limit=30&count=1
Time elapsed: 1026 ms.
Request [1]
Calling request https://www.reddit.com/r/all.json?limit=30&count=1
Time elapsed: 0 ms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment