Skip to content

Commit e482446

Browse files
committed
Added metrics provider to aggregate metrics instead of fetching in router
1 parent 1c7e4ae commit e482446

File tree

2 files changed

+69
-42
lines changed

2 files changed

+69
-42
lines changed

app/routers/v2.py

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""app.routers.v2"""
2+
from typing import Any
3+
from app.services.repo.metricsprovider import MetricsProvider
24
import enum
35

46
from fastapi import APIRouter, HTTPException, Request
@@ -7,6 +9,7 @@
79
from ..models import LatestResponse, LocationResponse, LocationsResponse
810

911
V2 = APIRouter()
12+
metrics_provider = MetricsProvider()
1013

1114

1215
class Sources(str, enum.Enum):
@@ -26,14 +29,7 @@ async def get_latest(
2629
"""
2730
Getting latest amount of total confirmed cases, deaths, and recoveries.
2831
"""
29-
locations = await request.state.source.get_all()
30-
return {
31-
"latest": {
32-
"confirmed": sum(map(lambda location: location.confirmed, locations)),
33-
"deaths": sum(map(lambda location: location.deaths, locations)),
34-
"recovered": sum(map(lambda location: location.recovered, locations)),
35-
}
36-
}
32+
return await metrics_provider.get_latest_global(request.state.source)
3733

3834

3935
# pylint: disable=unused-argument,too-many-arguments,redefined-builtin
@@ -56,38 +52,13 @@ async def get_locations(
5652
params.pop("source", None)
5753
params.pop("timelines", None)
5854

59-
# Retrieve all the locations.
60-
locations = await request.state.source.get_all()
61-
62-
# Attempt to filter out locations with properties matching the provided query params.
63-
for key, value in params.items():
64-
# Clean keys for security purposes.
65-
key = key.lower()
66-
value = value.lower().strip("__")
67-
68-
# Do filtering.
69-
try:
70-
locations = [
71-
location
72-
for location in locations
73-
if str(getattr(location, key)).lower() == str(value)
74-
]
75-
except AttributeError:
76-
pass
77-
if not locations:
78-
raise HTTPException(
79-
404, detail=f"Source `{source}` does not have the desired location data.",
80-
)
81-
82-
# Return final serialized data.
83-
return {
84-
"latest": {
85-
"confirmed": sum(map(lambda location: location.confirmed, locations)),
86-
"deaths": sum(map(lambda location: location.deaths, locations)),
87-
"recovered": sum(map(lambda location: location.recovered, locations)),
88-
},
89-
"locations": [location.serialize(timelines) for location in locations],
90-
}
55+
# # Retrieve all the locations.
56+
try:
57+
return await metrics_provider.get_available_locations(request.state.source, params, timelines)
58+
except Exception as err:
59+
raise HTTPException(404, str(err))
60+
61+
9162

9263

9364
# pylint: disable=invalid-name
@@ -98,8 +69,7 @@ async def get_location_by_id(
9869
"""
9970
Getting specific location by id.
10071
"""
101-
location = await request.state.source.get(id)
102-
return {"location": location.serialize(timelines)}
72+
return await metrics_provider.get_location_by_id(request.state.source, id, timelines)
10373

10474

10575
@V2.get("/sources")
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
class MetricsProvider():
2+
"""
3+
Gets latest global metrics from the given source
4+
"""
5+
async def get_latest_global(self, source):
6+
locations = await source.get_all()
7+
return {
8+
"latest": {
9+
"confirmed": sum(map(lambda location: location.confirmed, locations)),
10+
"deaths": sum(map(lambda location: location.deaths, locations)),
11+
"recovered": sum(map(lambda location: location.recovered, locations)),
12+
}
13+
}
14+
15+
"""
16+
Gets the available locations for a given source, params and with timeline (if requested)
17+
"""
18+
async def get_available_locations(self, source, params, timelines):
19+
# Retrieve all the locations.
20+
locations = await source.get_all()
21+
22+
# Attempt to filter out locations with properties matching the provided query params.
23+
for key, value in params.items():
24+
# Clean keys for security purposes.
25+
key = key.lower()
26+
value = value.lower().strip("__")
27+
28+
# Do filtering.
29+
try:
30+
locations = [
31+
location
32+
for location in locations
33+
if str(getattr(location, key)).lower() == str(value)
34+
]
35+
except AttributeError:
36+
pass
37+
if not locations:
38+
raise Exception(
39+
detail=f"Source `{source}` does not have the desired location data.",
40+
)
41+
42+
# Return final serialized data.
43+
return {
44+
"latest": {
45+
"confirmed": sum(map(lambda location: location.confirmed, locations)),
46+
"deaths": sum(map(lambda location: location.deaths, locations)),
47+
"recovered": sum(map(lambda location: location.recovered, locations)),
48+
},
49+
"locations": [location.serialize(timelines) for location in locations],
50+
}
51+
52+
"""
53+
Gets the location data by id
54+
"""
55+
async def get_location_by_id(self, source, id, timelines):
56+
location = await source.get(id)
57+
return {"location": location.serialize(timelines)}

0 commit comments

Comments
 (0)