Skip to content

Commit 0c36551

Browse files
Merge pull request #9 from ga4gh/dc-cache-and-clean
Removed dictionary cache
2 parents 5d2f76b + af6b881 commit 0c36551

9 files changed

Lines changed: 39 additions & 55 deletions

File tree

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.11-slim
1+
FROM python:3.12-slim
22

33
WORKDIR /app
44

app/callbacks/epmc_callbacks.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ def show_epmc_details(selected_rows, search_value, year_filter, affiliation_filt
271271
)
272272
affiliation_rows = get_affiliations_by_article(pm_id) if pm_id else []
273273
affiliation_rows = [r for r in affiliation_rows if isinstance(r, dict)]
274+
275+
def _row_display_affiliation_order(row):
276+
return row.get("display_affiliation_order") or row.get("affiliation_order")
277+
274278
affiliation_rows = sorted(
275279
affiliation_rows,
276280
key=lambda r: (
@@ -303,8 +307,8 @@ def show_epmc_details(selected_rows, search_value, year_filter, affiliation_filt
303307
for row in sorted(
304308
affiliation_rows,
305309
key=lambda r: (
306-
r.get("affiliation_order") is None,
307-
r.get("affiliation_order") or 0,
310+
_row_display_affiliation_order(r) is None,
311+
_row_display_affiliation_order(r) or 0,
308312
r.get("author_order") is None,
309313
r.get("author_order") or 0,
310314
),

app/constants/api.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
All external API endpoints live here
33
"""
44

5+
from app.config import settings
6+
57
#BASE API endpoint
6-
BASE_API = "http://AnalyticsDashboardAlbBalancer-1386294349.us-east-2.elb.amazonaws.com:8000"
7-
#BASE_API = "http://0.0.0.0:8000" # local test url
8+
#BASE_API = "http://AnalyticsDashboardAlbBalancer-1386294349.us-east-2.elb.amazonaws.com:8000"
9+
BASE_API = settings.API_BASE_URL.rstrip("/")
810

911
# PyPI API endpoint
1012
ALL_PACKAGES_API = BASE_API + "/pypi/all-packages"
@@ -32,4 +34,4 @@
3234
EPMC_ALL_ARTICLES = BASE_API + "/epmc/all-articles"
3335
EPMC_GET_AUTHORS_BY_ARTICLE = BASE_API + "/epmc/get-authors-by-article-id/"
3436
EPMC_CITATION_OVER_YEARS = BASE_API + "/epmc/citations-over-years"
35-
EPMC_AFFILIATION_BY_ARTICLE = BASE_API + "/epmc/get-affiliations-by-article-id/"
37+
EPMC_AFFILIATION_BY_ARTICLE = BASE_API + "/epmc/get-affiliations-by-article-id/"

app/layouts/datatables_layout.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ def get_datatables_layout(
3939

4040
if not epmc_entries_df.empty:
4141
if "pub_year" in epmc_entries_df.columns:
42+
years = pd.to_numeric(epmc_entries_df["pub_year"], errors="coerce").dropna().astype(int).unique()
4243
epmc_year_options = [
4344
{"label": str(y), "value": str(y)}
44-
for y in sorted(epmc_entries_df["pub_year"].dropna().unique(), reverse=True)
45+
for y in sorted(years, reverse=True)
4546
]
4647

4748
if "raw_json" in epmc_entries_df.columns:

app/services/epmc_client.py

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
import logging
12
import requests
23
import pandas as pd
34
import json
45
import app.constants.api as api_constants
56

7+
logger = logging.getLogger(__name__)
8+
69

710
def get_json(endpoint):
811
"""
912
Generic GET → JSON helper (same as pypi_client.get_json).
1013
"""
11-
print(f"Calling API: {endpoint}")
14+
logger.debug("Calling API: %s", endpoint)
1215
resp = requests.get(endpoint, timeout=30)
1316
resp.raise_for_status()
1417
return resp.json()
@@ -25,7 +28,7 @@ def get_all_paginated(endpoint, limit=1000):
2528

2629
while True:
2730
params = {"limit": limit, "skip": skip}
28-
print(f"Calling API: {endpoint} params={params}")
31+
logger.debug("Calling API: %s params=%s", endpoint, params)
2932
resp = requests.get(endpoint, params=params, timeout=30)
3033
resp.raise_for_status()
3134
data = resp.json()
@@ -187,13 +190,6 @@ def get_affiliations_by_article(pm_id):
187190

188191

189192

190-
# ---------------------------------------------------------------------------
191-
# Convenience: prepare a DataFrame ready for the layout / callbacks
192-
# ---------------------------------------------------------------------------
193-
194-
_epmc_cache = {}
195-
196-
197193
def _normalize_pub_year(value):
198194
"""Return a 4-digit publication year as int, or None when invalid."""
199195
if value is None:
@@ -210,20 +206,16 @@ def prepare_epmc_data():
210206
"""
211207
Fetch and process all EPMC data in a single pass to avoid redundant API calls.
212208
Returns all data needed for the dashboard: DataFrames, counts, and metadata.
213-
Results are cached after the first call.
214209
215210
Returns:
216211
tuple: (entries_df, countries_df, authors_df, total_entries, citations,
217212
unique_authors_count, top_authors_data)
218213
"""
219-
if "result" in _epmc_cache:
220-
return _epmc_cache["result"]
221214
# Fetch all API data upfront (no redundancy)
222215
raw_entries = get_all_articles(limit=1000)
223216
total_entries = len(raw_entries)
224217

225218
raw_countries = get_affiliation_countries_count()
226-
raw_authors = get_all_pmc_authors()
227219

228220
unique_authors_resp = get_json(api_constants.EPMC_UNIQUE_AUTHOR_COUNT)
229221
unique_authors_count = unique_authors_resp.get("unique_authors", 0) if isinstance(unique_authors_resp, dict) else 0
@@ -257,9 +249,8 @@ def prepare_epmc_data():
257249
else:
258250
countries_df = pd.DataFrame()
259251

260-
# Build authors DataFrame
261-
authors_df = pd.DataFrame.from_records(raw_authors) if raw_authors and isinstance(raw_authors, list) else pd.DataFrame()
252+
# The current UI uses summary author endpoints and article-specific author lookups,
253+
# so avoid fetching every author row during app startup.
254+
authors_df = pd.DataFrame()
262255

263-
result = (entries_df, countries_df, authors_df, total_entries, citations, unique_authors_count, top_authors_data)
264-
_epmc_cache["result"] = result
265-
return result
256+
return entries_df, countries_df, authors_df, total_entries, citations, unique_authors_count, top_authors_data

app/services/github_client.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import requests
23
import pandas as pd
34
import numpy as np
@@ -6,24 +7,21 @@
67

78
import app.constants.api as api_constants
89

10+
logger = logging.getLogger(__name__)
11+
912

1013
def get_json(endpoint: str, token: Optional[str] = None):
1114
headers = {}
1215
if token:
1316
headers["Authorization"] = f"token {token}"
1417

15-
print(f"Calling API: {endpoint}")
18+
logger.debug("Calling API: %s", endpoint)
1619
resp = requests.get(endpoint, headers=headers, timeout=30)
1720
resp.raise_for_status()
1821
return resp.json()
1922

2023

21-
_github_cache = {}
22-
2324
def prepare_github_data(fetch_date="2025-10-01"):
24-
if "result" in _github_cache:
25-
return _github_cache["result"]
26-
2725
GA4GH_json = get_json(api_constants.GITHUB_REPOS_API)
2826

2927
gh_df = pd.DataFrame.from_records(GA4GH_json)
@@ -74,5 +72,4 @@ def prepare_github_data(fetch_date="2025-10-01"):
7472
workstreams = gh_df["workstream"].dropna().unique().tolist()
7573

7674
result = (gh_df, gh_activity_df, gh_activity_counts, gh_interest_df, total_repositories, workstreams)
77-
_github_cache["result"] = result
7875
return result

app/services/pypi_client.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import logging
12
import requests
23
import app.constants.api as api_constants
34
import pandas as pd
45

6+
logger = logging.getLogger(__name__)
7+
8+
59
def get_json(endpoint):
610
"""
711
Function to get JSON response from API for get_json
@@ -10,13 +14,11 @@ def get_json(endpoint):
1014
Returns:
1115
dict: JSON response from the API
1216
"""
13-
print(f"Calling API: {endpoint}")
17+
logger.debug("Calling API: %s", endpoint)
1418
resp = requests.get(endpoint, timeout=30)
1519
resp.raise_for_status()
1620
return resp.json()
1721

18-
_pypi_cache = {}
19-
2022
def get_all_packages():
2123
"""
2224
Returns the full list of all PyPI package records stored in DB.
@@ -32,19 +34,14 @@ def get_total_packages():
3234
Returns:
3335
int: total number of packages
3436
"""
35-
if "total" in _pypi_cache:
36-
return _pypi_cache["total"]
3737
total_packages = get_json(api_constants.TOTAL_PACKAGES_API)
3838
total_packages = int(total_packages.get("total_packages", 0))
39-
_pypi_cache["total"] = total_packages
4039
return total_packages
4140

4241
def get_pypi_details():
4342
"""
4443
Returns detailed metadata for each PyPI project.
4544
"""
46-
if "details" in _pypi_cache:
47-
return _pypi_cache["details"]
4845
pypi_details = get_json(api_constants.PYPI_DETAILS_API)
4946
# Build DataFrame
5047
rows = []
@@ -61,15 +58,11 @@ def get_pypi_details():
6158
})
6259

6360
df = pd.DataFrame(rows)
64-
_pypi_cache["details"] = df
6561
return df
6662

6763
def get_first_releases():
6864
"""
6965
Returns the first release date for each PyPI project.
7066
"""
71-
if "first_releases" in _pypi_cache:
72-
return _pypi_cache["first_releases"]
7367
first_releases = get_json(api_constants.FIRST_RELEASES_API)
74-
_pypi_cache["first_releases"] = first_releases
75-
return first_releases
68+
return first_releases

app/services/service_map_client.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import logging
12
import requests
23
import pandas as pd
34
from typing import Optional
45

6+
logger = logging.getLogger(__name__)
7+
58
BASE_URL = "https://implementation-registry.ga4gh.org/api"
69
STANDARDS_ENDPOINT = f"{BASE_URL}/standards"
710
SERVICES_ENDPOINT = f"{BASE_URL}/services"
@@ -12,25 +15,18 @@ def get_json(endpoint: str, token: Optional[str] = None):
1215
if token:
1316
headers["Authorization"] = f"token {token}"
1417

15-
print(f"Calling API: {endpoint}")
18+
logger.debug("Calling API: %s", endpoint)
1619
resp = requests.get(endpoint, headers=headers, timeout=30)
1720
resp.raise_for_status()
1821
return resp.json()
1922

20-
_service_map_cache = {}
21-
2223
def prepare_service_map_data(fetch_date="2025-10-01"):
23-
if "result" in _service_map_cache:
24-
return _service_map_cache["result"]
25-
2624
standards_json = get_json(STANDARDS_ENDPOINT)
2725
services_json = get_json(SERVICES_ENDPOINT)
2826
deployments_json = get_json(DEPLOYMENTS_ENDPOINT)
2927

3028
standards_df = pd.DataFrame.from_records(standards_json)
3129
services_df = pd.DataFrame.from_records(services_json)
3230
deployments_df = pd.DataFrame.from_records(deployments_json)
33-
34-
_service_map_cache["result"] = (standards_df, services_df, deployments_df)
3531

36-
return _service_map_cache["result"]
32+
return standards_df, services_df, deployments_df

run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
server = app.server
44

55
if __name__ == "__main__":
6-
app.run(debug=True, host="0.0.0.0", port=8050)
6+
app.run(debug=True, host="0.0.0.0", port=8050, use_reloader=False)

0 commit comments

Comments
 (0)