Raising the area cap to 4600 put it above the largest area clamp/1 can emit (45° lat × 100° lon = 4500 sq deg), so :viewport_too_large became unreachable and the 413 handlers in both cell controllers became dead code. Remove the cap, the error branch, the max_viewport_area_sq_deg/0 accessor and both payload_too_large/1 handlers. The clamp is what bounds request cost: post-clamp nothing can ask for more than the full grid (~92k cells, ~1.4 MB), which is materialized once per valid_time and served from cache, so a global viewport costs no more than a fully zoomed-out map. Replaces the cap test with one asserting the clamp never lets absurd input escape the supported extent — the property the guard was standing in for.
55 lines
2 KiB
Elixir
55 lines
2 KiB
Elixir
defmodule MicrowavepropWeb.GridBounds do
|
|
@moduledoc """
|
|
Bounds clamp + sanity checks for grid-cell HTTP endpoints
|
|
(`/scores/cells`, `/weather/cells`).
|
|
|
|
The propagation grid covers HRRR (CONUS) and HRDPS (Canada to
|
|
60°N): roughly lat 25-60, lon -141 to -52. Any caller-provided
|
|
viewport is clamped to a generous superset of that bbox, which is
|
|
what bounds the work: after clamping no request can ask for more
|
|
than the full grid (~92k cells, ~1.4 MB), already materialized once
|
|
per valid_time and served from cache. A global or otherwise absurd
|
|
viewport therefore costs no more than a fully zoomed-out map does.
|
|
|
|
`nil` bounds are passed through (caller intends the full grid).
|
|
"""
|
|
|
|
# Generous superset of HRRR + HRDPS — a few extra degrees on each
|
|
# edge so legitimate clients zoomed slightly past the data extent
|
|
# still get a 200 with the actual covered cells.
|
|
@lat_min 20.0
|
|
@lat_max 65.0
|
|
@lon_min -150.0
|
|
@lon_max -50.0
|
|
|
|
@type bounds :: %{optional(String.t()) => float()} | nil
|
|
|
|
@doc """
|
|
Clamp `bounds` to the supported grid extent. Returns:
|
|
|
|
* `{:ok, nil}` when bounds are nil (caller wants the full grid)
|
|
* `{:ok, clamped_bounds}` otherwise
|
|
* `{:error, :invalid_bounds}` when north < south or east < west
|
|
|
|
"""
|
|
@spec clamp(bounds()) :: {:ok, bounds()} | {:error, :invalid_bounds}
|
|
def clamp(nil), do: {:ok, nil}
|
|
|
|
def clamp(%{"south" => s, "north" => n, "west" => w, "east" => e})
|
|
when is_number(s) and is_number(n) and is_number(w) and is_number(e) do
|
|
south = clamp_value(s, @lat_min, @lat_max)
|
|
north = clamp_value(n, @lat_min, @lat_max)
|
|
west = clamp_value(w, @lon_min, @lon_max)
|
|
east = clamp_value(e, @lon_min, @lon_max)
|
|
|
|
if north < south or east < west do
|
|
{:error, :invalid_bounds}
|
|
else
|
|
{:ok, %{"south" => south, "north" => north, "west" => west, "east" => east}}
|
|
end
|
|
end
|
|
|
|
def clamp(_), do: {:error, :invalid_bounds}
|
|
|
|
defp clamp_value(v, lo, hi), do: v |> max(lo) |> min(hi)
|
|
end
|