- All menus and UI text now say Contacts instead of QSOs - Add 68, 122, 134, 241 GHz bands to submit form and validation - Add info box on submit page explaining why contacts matter - Larger submit button with icon - Make HRRR partition migration idempotent for partial re-runs
144 lines
5.1 KiB
Elixir
144 lines
5.1 KiB
Elixir
defmodule Microwaveprop.Repo.Migrations.PartitionHrrrProfiles do
|
|
use Ecto.Migration
|
|
|
|
@disable_ddl_transaction true
|
|
@disable_migration_lock true
|
|
|
|
def up do
|
|
# Clean up any partial previous run: drop the partitioned table and orphaned
|
|
# partition tables, then rename _old back so we can start fresh.
|
|
execute """
|
|
DO $$
|
|
DECLARE
|
|
tbl text;
|
|
BEGIN
|
|
IF EXISTS (SELECT 1 FROM pg_tables WHERE tablename = 'hrrr_profiles_old' AND schemaname = 'public') THEN
|
|
DROP TABLE IF EXISTS hrrr_profiles CASCADE;
|
|
-- Drop orphaned partition tables left behind after CASCADE
|
|
FOR tbl IN
|
|
SELECT tablename FROM pg_tables
|
|
WHERE schemaname = 'public' AND tablename LIKE 'hrrr_profiles_%'
|
|
AND tablename != 'hrrr_profiles_old'
|
|
LOOP
|
|
EXECUTE 'DROP TABLE IF EXISTS ' || tbl || ' CASCADE';
|
|
END LOOP;
|
|
ALTER TABLE hrrr_profiles_old RENAME TO hrrr_profiles;
|
|
END IF;
|
|
END $$
|
|
"""
|
|
|
|
# 1. Rename old table
|
|
execute "ALTER TABLE hrrr_profiles RENAME TO hrrr_profiles_old"
|
|
|
|
# 2. Create partitioned table with identical schema
|
|
execute """
|
|
CREATE TABLE hrrr_profiles (
|
|
id uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
valid_time timestamp(0) WITHOUT TIME ZONE NOT NULL,
|
|
lat double precision NOT NULL,
|
|
lon double precision NOT NULL,
|
|
run_time timestamp(0) WITHOUT TIME ZONE,
|
|
profile jsonb[] DEFAULT ARRAY[]::jsonb[],
|
|
hpbl_m double precision,
|
|
pwat_mm double precision,
|
|
surface_temp_c double precision,
|
|
surface_dewpoint_c double precision,
|
|
surface_pressure_mb double precision,
|
|
surface_refractivity double precision,
|
|
min_refractivity_gradient double precision,
|
|
ducting_detected boolean DEFAULT false,
|
|
duct_characteristics jsonb[],
|
|
inserted_at timestamp(0) WITHOUT TIME ZONE NOT NULL,
|
|
updated_at timestamp(0) WITHOUT TIME ZONE NOT NULL
|
|
) PARTITION BY RANGE (valid_time)
|
|
"""
|
|
|
|
# 3. Create partitions
|
|
partitions = [
|
|
{"2016-01-01", "2017-01-01"},
|
|
{"2017-01-01", "2018-01-01"},
|
|
{"2018-01-01", "2018-07-01"},
|
|
{"2018-07-01", "2019-01-01"},
|
|
{"2019-01-01", "2019-07-01"},
|
|
{"2019-07-01", "2019-10-01"},
|
|
{"2019-10-01", "2020-01-01"},
|
|
{"2020-01-01", "2020-07-01"},
|
|
{"2020-07-01", "2020-10-01"},
|
|
{"2020-10-01", "2021-01-01"},
|
|
{"2021-01-01", "2021-07-01"},
|
|
{"2021-07-01", "2021-10-01"},
|
|
{"2021-10-01", "2022-01-01"},
|
|
{"2022-01-01", "2022-07-01"},
|
|
{"2022-07-01", "2022-10-01"},
|
|
{"2022-10-01", "2023-01-01"},
|
|
{"2023-01-01", "2023-07-01"},
|
|
{"2023-07-01", "2023-10-01"},
|
|
{"2023-10-01", "2024-01-01"},
|
|
{"2024-01-01", "2024-07-01"},
|
|
{"2024-07-01", "2024-10-01"},
|
|
{"2024-10-01", "2025-01-01"},
|
|
{"2025-01-01", "2025-07-01"},
|
|
{"2025-07-01", "2026-01-01"},
|
|
{"2026-01-01", "2026-04-01"},
|
|
{"2026-04-01", "2026-07-01"},
|
|
{"2026-07-01", "2026-10-01"},
|
|
{"2026-10-01", "2027-01-01"},
|
|
{"2027-01-01", "2027-07-01"},
|
|
{"2027-07-01", "2028-01-01"}
|
|
]
|
|
|
|
for {from_date, to_date} <- partitions do
|
|
suffix = from_date |> String.replace("-", "_") |> String.slice(0..6)
|
|
|
|
execute """
|
|
CREATE TABLE hrrr_profiles_#{suffix} PARTITION OF hrrr_profiles
|
|
FOR VALUES FROM ('#{from_date}') TO ('#{to_date}')
|
|
"""
|
|
end
|
|
|
|
# 4. Indexes on partitioned table
|
|
execute "DROP INDEX IF EXISTS hrrr_profiles_lat_lon_valid_time_index"
|
|
execute "DROP INDEX IF EXISTS hrrr_profiles_valid_time_index"
|
|
|
|
execute "CREATE UNIQUE INDEX hrrr_profiles_lat_lon_valid_time_index ON hrrr_profiles (lat, lon, valid_time)"
|
|
execute "CREATE INDEX hrrr_profiles_valid_time_index ON hrrr_profiles (valid_time)"
|
|
|
|
# 5. Migrate data
|
|
execute "INSERT INTO hrrr_profiles SELECT * FROM hrrr_profiles_old"
|
|
|
|
# 6. Drop old table
|
|
execute "DROP TABLE hrrr_profiles_old"
|
|
end
|
|
|
|
def down do
|
|
execute """
|
|
CREATE TABLE hrrr_profiles_flat (
|
|
id uuid NOT NULL,
|
|
valid_time timestamp(0) WITHOUT TIME ZONE NOT NULL,
|
|
lat double precision NOT NULL,
|
|
lon double precision NOT NULL,
|
|
run_time timestamp(0) WITHOUT TIME ZONE,
|
|
profile jsonb[] DEFAULT ARRAY[]::jsonb[],
|
|
hpbl_m double precision,
|
|
pwat_mm double precision,
|
|
surface_temp_c double precision,
|
|
surface_dewpoint_c double precision,
|
|
surface_pressure_mb double precision,
|
|
surface_refractivity double precision,
|
|
min_refractivity_gradient double precision,
|
|
ducting_detected boolean DEFAULT false,
|
|
duct_characteristics jsonb[],
|
|
inserted_at timestamp(0) WITHOUT TIME ZONE NOT NULL,
|
|
updated_at timestamp(0) WITHOUT TIME ZONE NOT NULL,
|
|
PRIMARY KEY (id)
|
|
)
|
|
"""
|
|
|
|
execute "INSERT INTO hrrr_profiles_flat SELECT * FROM hrrr_profiles"
|
|
execute "DROP TABLE hrrr_profiles"
|
|
execute "ALTER TABLE hrrr_profiles_flat RENAME TO hrrr_profiles"
|
|
|
|
execute "CREATE UNIQUE INDEX hrrr_profiles_lat_lon_valid_time_index ON hrrr_profiles (lat, lon, valid_time)"
|
|
execute "CREATE INDEX hrrr_profiles_valid_time_index ON hrrr_profiles (valid_time)"
|
|
end
|
|
end
|