feat(aprs): add read-only AprsRepo for aprs.me database access
Wire up Microwaveprop.AprsRepo as an optional secondary Ecto repo that points at the sister aprs.me Postgres for read-only access. This is the foundation for upcoming 144 MHz calibration work that uses verified APRS RF hops as ground truth. * lib/microwaveprop/aprs_repo.ex declares a read_only repo; no schemas, no migrations, no writes — Microwaveprop never persists APRS data. * Application supervisor starts the repo only when configured (dev/test via config blocks, prod via APRS_DATABASE_URL). A missing config logs a warning and skips startup so the main app still boots. * config/dev.exs + config/test.exs add local aprsme_dev / aprsme_test endpoints. Test pool uses Ecto SQL Sandbox; tests that don't touch APRS data don't need to check the connection out. * config/runtime.exs guards the prod block on APRS_DATABASE_URL — unset env logs a warning and leaves the repo unconfigured.
This commit is contained in:
parent
1f8765f757
commit
714d1ce432
5 changed files with 88 additions and 5 deletions
|
|
@ -3,6 +3,15 @@ import Config
|
|||
# Do not include metadata nor timestamps in development logs
|
||||
config :logger, :default_formatter, format: "[$level] $message\n"
|
||||
|
||||
# Read-only secondary repo pointing at the local aprs.me dev database.
|
||||
# See lib/microwaveprop/aprs_repo.ex — used by APRS calibration tooling
|
||||
# only; the main app boots fine without it.
|
||||
config :microwaveprop, Microwaveprop.AprsRepo,
|
||||
username: "postgres",
|
||||
hostname: "localhost",
|
||||
database: "aprsme_dev",
|
||||
pool_size: 2
|
||||
|
||||
# Configure your database
|
||||
config :microwaveprop, Microwaveprop.Repo,
|
||||
username: "postgres",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
import Config
|
||||
|
||||
alias Microwaveprop.Workers.CanadianSoundingFetchWorker
|
||||
alias Oban.Plugins.Cron
|
||||
|
||||
require Logger
|
||||
|
||||
# config/runtime.exs is executed for all environments, including
|
||||
# during releases. It is executed after compilation and before the
|
||||
# system starts, so it is typically used to load production configuration
|
||||
|
|
@ -16,9 +21,6 @@ import Config
|
|||
#
|
||||
# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server`
|
||||
# script that automatically sets the env var above.
|
||||
alias Microwaveprop.Workers.CanadianSoundingFetchWorker
|
||||
alias Oban.Plugins.Cron
|
||||
|
||||
if System.get_env("PHX_SERVER") do
|
||||
config :microwaveprop, MicrowavepropWeb.Endpoint, server: true
|
||||
end
|
||||
|
|
@ -355,6 +357,24 @@ if config_env() == :prod do
|
|||
# pool_count: 4,
|
||||
socket_options: maybe_ipv6
|
||||
|
||||
# Optional secondary repo for read-only access to aprs.me's database.
|
||||
# Used by APRS-based 144 MHz calibration tooling. When the env var is
|
||||
# unset we leave the AprsRepo unconfigured; Microwaveprop.Application
|
||||
# logs a warning and skips starting it, and the rest of the app boots
|
||||
# normally.
|
||||
case System.get_env("APRS_DATABASE_URL") do
|
||||
nil ->
|
||||
Logger.warning("APRS_DATABASE_URL not set — Microwaveprop.AprsRepo will not start; APRS calibration disabled.")
|
||||
|
||||
:ok
|
||||
|
||||
aprs_url ->
|
||||
config :microwaveprop, Microwaveprop.AprsRepo,
|
||||
url: aprs_url,
|
||||
pool_size: String.to_integer(System.get_env("APRS_POOL_SIZE") || "2"),
|
||||
socket_options: maybe_ipv6
|
||||
end
|
||||
|
||||
config :microwaveprop, MicrowavepropWeb.Endpoint,
|
||||
# SSL terminated by Cloudflare tunnel; generated URLs still use https
|
||||
url: [host: host, port: 443, scheme: "https"],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import Config
|
||||
|
||||
alias Ecto.Adapters.SQL.Sandbox
|
||||
alias Microwaveprop.Qrz.Client
|
||||
|
||||
# Only in tests, remove the complexity from the password hashing algorithm
|
||||
|
|
@ -15,6 +16,21 @@ config :microwaveprop, Client,
|
|||
plug: {Req.Test, Client},
|
||||
retry: false
|
||||
|
||||
# Read-only secondary repo for aprs.me. Configured here so the app boots
|
||||
# under MIX_ENV=test, but uses the SQL.Sandbox in :manual mode so tests
|
||||
# that don't touch APRS data don't have to check the DB out. Tests that
|
||||
# do query the AprsRepo must call `Ecto.Adapters.SQL.Sandbox.checkout/1`
|
||||
# explicitly.
|
||||
config :microwaveprop, Microwaveprop.AprsRepo,
|
||||
username: "postgres",
|
||||
password: "postgres",
|
||||
hostname: "localhost",
|
||||
database: "aprsme_test#{System.get_env("MIX_TEST_PARTITION")}",
|
||||
pool: Sandbox,
|
||||
pool_size: 2,
|
||||
ownership_timeout: 60_000,
|
||||
timeout: 60_000
|
||||
|
||||
config :microwaveprop, Microwaveprop.Geocoder,
|
||||
plug: {Req.Test, Microwaveprop.Geocoder},
|
||||
retry: false
|
||||
|
|
@ -33,7 +49,7 @@ config :microwaveprop, Microwaveprop.Repo,
|
|||
password: "postgres",
|
||||
hostname: "localhost",
|
||||
database: "microwaveprop_test#{System.get_env("MIX_TEST_PARTITION")}",
|
||||
pool: Ecto.Adapters.SQL.Sandbox,
|
||||
pool: Sandbox,
|
||||
pool_size: System.schedulers_online() * 2,
|
||||
ownership_timeout: 60_000,
|
||||
timeout: 60_000
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ defmodule Microwaveprop.Application do
|
|||
MicrowavepropWeb.Telemetry,
|
||||
Microwaveprop.PromEx,
|
||||
Microwaveprop.Repo,
|
||||
# AprsRepo is optional — only starts when configured with a :url
|
||||
# (dev/test from config blocks, prod from APRS_DATABASE_URL). Missing
|
||||
# config logs a warning and skips startup so the app still boots.
|
||||
aprs_repo_child_spec(),
|
||||
{Cluster.Supervisor, [topologies, [name: Microwaveprop.ClusterSupervisor]]},
|
||||
{Phoenix.PubSub, name: Microwaveprop.PubSub},
|
||||
# Partitioned Task.Supervisor — callers route heavy `async_stream`
|
||||
|
|
@ -43,7 +47,7 @@ defmodule Microwaveprop.Application do
|
|||
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||
# for other strategies and supported options
|
||||
opts = [strategy: :one_for_one, name: Microwaveprop.Supervisor]
|
||||
result = Supervisor.start_link(children, opts)
|
||||
result = children |> Enum.reject(&is_nil/1) |> Supervisor.start_link(opts)
|
||||
|
||||
# Attach the Oban exception telemetry tap so per-worker recovery
|
||||
# callbacks and structured logs fire on job failure. Must run after
|
||||
|
|
@ -92,6 +96,23 @@ defmodule Microwaveprop.Application do
|
|||
:ok
|
||||
end
|
||||
|
||||
# Returns Microwaveprop.AprsRepo child spec if configured (has a :url
|
||||
# or :database key), otherwise logs a warning and returns nil so the
|
||||
# supervisor children list can filter it out. APRS calibration is an
|
||||
# optional integration with the sister aprs.me database — we never
|
||||
# crash boot when it's unavailable.
|
||||
defp aprs_repo_child_spec do
|
||||
config = Application.get_env(:microwaveprop, Microwaveprop.AprsRepo, [])
|
||||
|
||||
if Keyword.has_key?(config, :url) or Keyword.has_key?(config, :database) do
|
||||
Microwaveprop.AprsRepo
|
||||
else
|
||||
Logger.warning("Microwaveprop.AprsRepo not configured (no :url or :database) — APRS calibration disabled.")
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the deployment (image build) timestamp.
|
||||
|
||||
|
|
|
|||
17
lib/microwaveprop/aprs_repo.ex
Normal file
17
lib/microwaveprop/aprs_repo.ex
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
defmodule Microwaveprop.AprsRepo do
|
||||
@moduledoc """
|
||||
Secondary repo for read-only access to aprs.me's `packets` table.
|
||||
|
||||
Used by `Microwaveprop.Aprs` and the `Mix.Tasks.Calibrate.Aprs144` mix
|
||||
task to pull verified RF hops as ground truth for 144 MHz scoring.
|
||||
|
||||
This repo never owns schema, migrations, or writes — it only ever
|
||||
issues SELECT queries against aprs.me's existing partitioned `packets`
|
||||
table. The connection is configured to fail closed if `APRS_DATABASE_URL`
|
||||
is unset in production.
|
||||
"""
|
||||
use Ecto.Repo,
|
||||
otp_app: :microwaveprop,
|
||||
adapter: Ecto.Adapters.Postgres,
|
||||
read_only: true
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue