import gc import requests from datetime import datetime, timedelta from requests.utils import urlparse from zoneinfo import ZoneInfo from fastapi import FastAPI, BackgroundTasks from fastapi.responses import JSONResponse from fastapi.middleware import Middleware from starlette.middleware.cors import CORSMiddleware from fastapi_utils.tasks import repeat_every from app.settings import * # App middleware = [ Middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ), ] app = FastAPI(title="noaa", middleware=middleware) # API # GET 'test' @app.get("/test/") async def get_test(): # check source availability # fresh one might be missing and old ones get deleted, so check yesterday's yesterday_news = datetime.now(tz=ZoneInfo("US/Eastern")) - timedelta(days=1) url = form_gfswave_link(target_time=yesterday_news) if not is_reachable(url): # just one should be fine print(url, " is not reachable at this time") # TODO: should we actually error out? return JSONResponse(content={"status": "success"}) # GET 'test_background' @app.get("/test_background/{field_1}") async def get_test_background(field_1: str, background_tasks: BackgroundTasks): # background_tasks - for "heavy" processes # TODO background_tasks.add_task(service_example.run_test, field_1) return JSONResponse(content={"status": "Background task started"}) # Tasks # gc @app.on_event("startup") @repeat_every(seconds=(1 * 60)) async def task_gc() -> None: gc.collect() def is_reachable(url: str): """Check if url is reachable at all with the current setup :param url: URL to check :return: True if url is reachable, False otherwise """ if requests.head(url): return True return False def form_gfs_link(target_time=None, prod_hour=384): """Return well formed link to gfs data which should be available by given time :param target_time: time to check, defaults to current time :param prod_hour: forecast hour to link to, defaults to 384 :returns: URL to gfs file """ if not target_time: target_time = datetime.now( tz=ZoneInfo("US/Eastern") ) # noaa is located in washington looking_at = "atmos" date_str = target_time.strftime("%Y%m%d") hour_str = str((target_time.hour // 6) * 6).zfill(2) target_url = f"https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.{date_str}/{hour_str}/{looking_at}/gfs.t{hour_str}z.pgrb2.0p25.f{prod_hour}" return target_url def form_gfswave_link(target_time=None, prod_hour=384): """Return well formed link to gfs data which should be available by given time :param target_time: time to check, defaults to current time :param prod_hour: forecast hour to link to, defaults to 384 :returns: URL to gfs file """ if not target_time: target_time = datetime.now( tz=ZoneInfo("US/Eastern") ) # noaa is located in washington looking_at = "wave" date_str = target_time.strftime("%Y%m%d") hour_str = str((target_time.hour // 6) * 6).zfill(2) target_url = f"https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.{date_str}/{hour_str}/{looking_at}/gridded/gfs{looking_at}.t{hour_str}z.global.0p25.f{prod_hour}.grib2" return target_url