@@ -5,38 +5,60 @@ use crate::hgnc::traits::HGNCData;
55use ratelimit:: Ratelimiter ;
66use reqwest:: blocking:: Client ;
77use std:: fmt:: { Debug , Formatter } ;
8+ use std:: sync:: OnceLock ;
89use std:: thread:: sleep;
910use std:: time:: Duration ;
1011
12+ static HGNC_RATE_LIMITER : OnceLock < Ratelimiter > = OnceLock :: new ( ) ;
13+
14+ fn hgnc_rate_limiter ( ) -> & ' static Ratelimiter {
15+ HGNC_RATE_LIMITER . get_or_init ( || {
16+ Ratelimiter :: builder ( 10 , Duration :: from_millis ( 1100 ) )
17+ . max_tokens ( 10 )
18+ . build ( )
19+ . expect ( "Building rate limiter failed" )
20+ } )
21+ }
22+
1123pub struct HGNCClient {
12- rate_limiter : Ratelimiter ,
24+ attempts : usize ,
1325 api_url : String ,
1426 client : Client ,
1527}
1628
1729impl HGNCClient {
18- pub fn new ( rate_limiter : Ratelimiter , api_url : String ) -> Self {
30+ pub fn new ( attempts : usize , api_url : String ) -> Self {
1931 HGNCClient {
20- rate_limiter ,
32+ attempts ,
2133 api_url,
2234 client : Client :: new ( ) ,
2335 }
2436 }
2537
26- fn fetch_request ( & self , url : String ) -> Result < Vec < GeneDoc > , HGNCError > {
27- if let Err ( duration) = self . rate_limiter . try_wait ( ) {
28- sleep ( duration) ;
38+ fn fetch_request ( & self , url : & str , query : & GeneQuery ) -> Result < Vec < GeneDoc > , HGNCError > {
39+ for _ in 0 ..self . attempts {
40+ if let Err ( duration) = hgnc_rate_limiter ( ) . try_wait ( ) {
41+ sleep ( duration) ;
42+ }
43+ let response = self
44+ . client
45+ . get ( url)
46+ . header ( "User-Agent" , "PIVOT" )
47+ . header ( "Accept" , "application/json" )
48+ . send ( ) ;
49+
50+ if let Ok ( response) = response
51+ && response. status ( ) . is_success ( )
52+ {
53+ let gene_response = response. json :: < GeneResponse > ( ) ?;
54+ return Ok ( gene_response. response . docs ) ;
55+ }
2956 }
30- let response = self
31- . client
32- . get ( url. clone ( ) )
33- . header ( "User-Agent" , "PIVOT" )
34- . header ( "Accept" , "application/json" )
35- . send ( ) ?;
3657
37- let gene_response = response. json :: < GeneResponse > ( ) ?;
38-
39- Ok ( gene_response. response . docs )
58+ Err ( HGNCError :: HgncAPI {
59+ gene : query. inner ( ) . to_string ( ) ,
60+ attempts : self . attempts ,
61+ } )
4062 }
4163}
4264
@@ -46,7 +68,7 @@ impl HGNCData for HGNCClient {
4668 GeneQuery :: Symbol ( symbol) => format ! ( "{}fetch/symbol/{}" , self . api_url, symbol) ,
4769 GeneQuery :: HgncId ( id) => format ! ( "{}fetch/hgnc_id/{}" , self . api_url, id) ,
4870 } ;
49- let docs = self . fetch_request ( fetch_url) ?;
71+ let docs = self . fetch_request ( & fetch_url, & query ) ?;
5072
5173 if docs. len ( ) == 1 {
5274 Ok ( docs. first ( ) . unwrap ( ) . clone ( ) )
@@ -62,12 +84,7 @@ impl HGNCData for HGNCClient {
6284
6385impl Default for HGNCClient {
6486 fn default ( ) -> Self {
65- let rate_limiter = Ratelimiter :: builder ( 10 , Duration :: from_secs ( 1 ) )
66- . max_tokens ( 10 )
67- . build ( )
68- . expect ( "Building rate limiter failed" ) ;
69-
70- HGNCClient :: new ( rate_limiter, "https://rest.genenames.org/" . to_string ( ) )
87+ HGNCClient :: new ( 3 , "https://rest.genenames.org/" . to_string ( ) )
7188 }
7289}
7390
0 commit comments