Last active
June 27, 2016 12:52
-
-
Save eidge/087d2b5527293ffaeb9303178bc07801 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Weather.NOAA.Forecast do | |
@moduledoc """ | |
Implements primitives to download forecasts from the NOAA servers. | |
""" | |
defstruct params: nil, data: :not_computed, format: :grib2 | |
@type t :: %__MODULE__{ | |
params: nil | Params.t, | |
format: :grib2, | |
data: nil | binary | |
} | |
alias Weather.NOAA.Forecast.Params | |
alias Weather.NOAA.Forecast.PathBuilder | |
alias HTTPotion.Response | |
@doc """ | |
Downloads a grib2 forecast given a model name and an optional list of options. | |
Args: | |
- params - Forecast params to fetch, Weather.NOAA.ForecastParams.t | |
- options - Keyword.t | |
options: | |
- timeout - timeout in ms, integer | :infinity (default: 20000) | |
""" | |
def get(%Params{} = params, options \\ []) do | |
http_options = Keyword.merge([timeout: 20000], options) | |
file_url = PathBuilder.path_for(params) | |
case fetch(file_url, http_options) do | |
{:ok, forecast_grib2} -> {:ok, build_forecast(params, forecast_grib2)} | |
{:error, explanation} -> {:error, explanation} | |
end | |
end | |
defp build_forecast(params, grib2) do | |
%__MODULE__{ | |
params: params, | |
data: grib2 | |
} | |
end | |
@doc """ | |
Fetches a list of available forecast cycles from NOAA | |
Args: | |
- model_name - atom (see Forecast.PathBuilder.directory_path_for/1) | |
- options - Keyword.t | |
options: | |
- timeout - timeout in ms, integer | :infinity (default: 20000) | |
""" | |
def available_cycles(model_name, options \\ []) do | |
file_url = PathBuilder.directory_path_for(model_name) | |
case fetch(file_url, options) do | |
{:ok, cycles_html} -> {:ok, DirectoryListingHTMLParser.cycles(cycles_html)} | |
{:error, explanation} -> {:error, explanation} | |
end | |
end | |
defp fetch(url, options) do | |
try do | |
case HTTPotion.get(url, options) do | |
%Response{status_code: 200, body: body} -> {:ok, body} | |
%Response{status_code: status, body: error} -> {:error, {status, error}} | |
end | |
rescue | |
e in HTTPotion.HTTPError -> | |
if e.message == "req_timedout" do | |
{:error, :timeout} | |
else | |
raise e | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment