File size: 1,255 Bytes
b69651d
 
6523621
 
 
b69651d
 
 
 
8e8bfa6
b69651d
 
6523621
 
b69651d
6523621
 
b69651d
3ef2946
b69651d
 
6523621
 
b69651d
 
6523621
b69651d
6523621
b69651d
 
 
 
6523621
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
"""
MyGene.info async helper
Docs: https://docs.mygene.info/en/latest/api_service.html
• Key is OPTIONAL – set MYGENE_KEY only for >500 QPS quota.
• One retry on 5xx/timeout then returns {} so UI never crashes.
"""

from __future__ import annotations
import os, asyncio, httpx
from functools import lru_cache
from typing import Dict

_URL   = "https://mygene.info/v3/query"
_KEY   = os.getenv("MYGENE_KEY")          # optional
_FIELDS = "symbol,name,summary,alias,entrezgene,location"
_TIMEOUT = 8
_RETRIES = 2            # initial + one retry

@lru_cache(maxsize=512)
async def fetch_gene_info(symbol: str) -> Dict:
    params = {"q": symbol, "fields": _FIELDS, "size": 1}
    if _KEY:
        params["api_key"] = _KEY

    delay = 0.0
    for _ in range(_RETRIES):
        try:
            async with httpx.AsyncClient(timeout=_TIMEOUT) as cli:
                r = await cli.get(_URL, params=params)
                r.raise_for_status()
                return r.json().get("hits", [{}])[0]
        except (httpx.HTTPStatusError, httpx.ReadTimeout):
            await asyncio.sleep(delay or 0.6)   # back-off once
            delay = 0.0                         # only retry once
    return {}                                   # graceful fallback