diff --git a/app.py b/app.py index a8e6350..efc8138 100644 --- a/app.py +++ b/app.py @@ -1,18 +1,23 @@ from flask import Flask, render_template, jsonify, request -from utils.weather import get_today_snowfall -from utils.geocode import get_city_name +from utils.weather import get_today_snowfall_async +from utils.geocode import get_city_name_async from config import MAX_SNOW_INCHES from flask_caching import Cache +import asyncio app = Flask(__name__) # Cache config: 10-minute default timeout cache = Cache(app, config={"CACHE_TYPE": "SimpleCache", "CACHE_DEFAULT_TIMEOUT": 600}) -@cache.memoize(600) # cache each request for 10 minutes +@cache.memoize() def get_snowfall_for_location(lat, lon): - inches, snowing, tz_name = get_today_snowfall(lat, lon) - city_name = get_city_name(lat, lon) + # Run async functions in an event loop + return asyncio.run(fetch_snow_and_city(lat, lon)) + +async def fetch_snow_and_city(lat, lon): + inches, snowing, tz_name = await get_today_snowfall_async(lat, lon) + city_name = await get_city_name_async(lat, lon) return inches, snowing, tz_name, city_name @app.route("/") @@ -43,6 +48,5 @@ def snowfall_api(): "updated": datetime.now().isoformat() }) - if __name__ == "__main__": app.run(host="0.0.0.0", port=5000) diff --git a/utils/geocode.py b/utils/geocode.py index f9345d9..a720e2d 100644 --- a/utils/geocode.py +++ b/utils/geocode.py @@ -1,17 +1,13 @@ -import requests +import httpx -def get_city_name(lat, lon): - try: - r = requests.get( +async def get_city_name_async(lat, lon): + async with httpx.AsyncClient(timeout=5) as client: + r = await client.get( "https://nominatim.openstreetmap.org/reverse", params={"lat": lat, "lon": lon, "format": "json", "zoom": 10, "addressdetails": 1}, headers={"User-Agent": "AreWeBuriedApp/1.0"} ) r.raise_for_status() data = r.json() - address = data.get("address", {}) - city = address.get("city") or address.get("town") or address.get("village") or address.get("county") or f"{lat:.2f},{lon:.2f}" - return city - except Exception as e: - print("Reverse geocoding error:", e) - return f"{lat:.2f},{lon:.2f}" + address = data.get("address", {}) + return address.get("city") or address.get("town") or address.get("village") or address.get("county") or f"{lat:.2f},{lon:.2f}" diff --git a/utils/weather.py b/utils/weather.py index 51ddd90..043a005 100644 --- a/utils/weather.py +++ b/utils/weather.py @@ -1,43 +1,33 @@ -import requests -from datetime import datetime +import httpx import pytz +from datetime import datetime from timezonefinder import TimezoneFinder from config import OPEN_METEO_URL tf = TimezoneFinder() -def get_today_snowfall(lat, lon): - try: - tz_name = tf.timezone_at(lat=lat, lng=lon) or "UTC" +async def get_today_snowfall_async(lat, lon): + tz_name = tf.timezone_at(lat=lat, lng=lon) or "UTC" - params = { - "latitude": lat, - "longitude": lon, - "hourly": "snowfall", - "timezone": tz_name - } - - r = requests.get(OPEN_METEO_URL, params=params, timeout=5) + async with httpx.AsyncClient(timeout=5) as client: + params = {"latitude": lat, "longitude": lon, "hourly": "snowfall", "timezone": tz_name} + r = await client.get(OPEN_METEO_URL, params=params) r.raise_for_status() data = r.json() - hourly = data.get("hourly", {}) - times = hourly.get("time", []) - snow_values = hourly.get("snowfall", []) + hourly = data.get("hourly", {}) + times = hourly.get("time", []) + snow_values = hourly.get("snowfall", []) - today_str = datetime.now(pytz.timezone(tz_name)).date().isoformat() + today_str = datetime.now(pytz.timezone(tz_name)).date().isoformat() - snowfall_cm = 0.0 - snowing_now = False - for t, s in zip(times, snow_values): - if t.startswith(today_str): - snowfall_cm += s - if s > 0: - snowing_now = True + snowfall_cm = 0.0 + snowing_now = False + for t, s in zip(times, snow_values): + if t.startswith(today_str): + snowfall_cm += s + if s > 0: + snowing_now = True - inches = round(snowfall_cm / 2.54, 1) - return inches, snowing_now, tz_name - - except Exception as e: - print("Error fetching snowfall:", e) - return 0.0, False, "UTC" + inches = round(snowfall_cm / 2.54, 1) + return inches, snowing_now, tz_name