towerops/lib/towerops/lidar/sync_log.ex
Graham McIntire 158ee9d323 feat: add Texas LIDAR DEM catalog with on-demand elevation reads
Catalog-only system for LIDAR-derived 1m DEMs covering Texas. We do not
mirror raster data — the DB stores tile metadata (URL + footprint
geometry) and elevation values are streamed on-demand from public USGS
3DEP / TNRIS Cloud-Optimized GeoTIFFs via GDAL /vsicurl/ HTTP byte-range
reads. Used for future tower coverage line-of-sight calculations.

- Enable PostGIS extension; tile footprints indexed via GiST
- Catalog sync from USGS 3DEP (primary) and TNRIS (fallback for gaps)
- Tile dedup by ST_Contains so TNRIS doesn't duplicate 3DEP coverage
- Single-point reads via gdallocationinfo with tile fallthrough on nodata
- Grid retrieval via gdal_translate AAIGrid with multi-tile mosaicing
- Monthly Oban cron worker keeps catalog fresh
- gdal-bin added to runtime image; geo_postgis dep added
2026-05-04 13:03:28 -05:00

39 lines
945 B
Elixir

defmodule Towerops.Lidar.SyncLog do
@moduledoc """
Audit log for LIDAR catalog sync operations.
"""
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@valid_statuses ~w(success partial failed)
@valid_sources ~w(3dep tnris)
schema "lidar_sync_logs" do
field :source, :string
field :status, :string
field :projects_synced, :integer, default: 0
field :tiles_upserted, :integer, default: 0
field :errors, :map
field :duration_ms, :integer
field :inserted_at, :utc_datetime
end
def changeset(sync_log, attrs) do
sync_log
|> cast(attrs, [
:source,
:status,
:projects_synced,
:tiles_upserted,
:errors,
:duration_ms,
:inserted_at
])
|> validate_required([:source, :status, :inserted_at])
|> validate_inclusion(:source, @valid_sources)
|> validate_inclusion(:status, @valid_statuses)
end
end