* HH-441: harden durable storage and recovery * HH-441: clear recovery review blockers * HH-441: enforce offsite backup failure domain --------- Co-authored-by: Rogee <rogee@ipao.vip>
108 lines
4.4 KiB
PL/PgSQL
108 lines
4.4 KiB
PL/PgSQL
-- Convert the legacy rollup schema without dropping its data. The explicit
|
|
-- transaction makes lock/statement timeout failures leave the old table intact.
|
|
BEGIN;
|
|
LOCK TABLE reporting_events_rollups IN ACCESS EXCLUSIVE MODE;
|
|
|
|
DO $$
|
|
DECLARE
|
|
invalid_periods BIGINT;
|
|
invalid_dimensions BIGINT;
|
|
invalid_counts BIGINT;
|
|
oversized_dimensions BIGINT;
|
|
collision_groups BIGINT;
|
|
BEGIN
|
|
SELECT count(*) INTO invalid_periods
|
|
FROM reporting_events_rollups
|
|
WHERE NOT pg_input_is_valid(period, 'date');
|
|
IF invalid_periods > 0 THEN
|
|
RAISE EXCEPTION 'migration 000048: % rollup period value(s) cannot convert to date', invalid_periods
|
|
USING HINT = 'Repair or remove the reported legacy rows explicitly, then retry the migration.';
|
|
END IF;
|
|
|
|
SELECT count(*) INTO invalid_dimensions
|
|
FROM reporting_events_rollups
|
|
WHERE NOT pg_input_is_valid(dimension_value, 'bigint');
|
|
IF invalid_dimensions > 0 THEN
|
|
RAISE EXCEPTION 'migration 000048: % rollup dimension_value(s) cannot convert to bigint', invalid_dimensions
|
|
USING HINT = 'Map non-numeric legacy dimensions explicitly, then retry the migration.';
|
|
END IF;
|
|
|
|
SELECT count(*) INTO invalid_counts
|
|
FROM reporting_events_rollups
|
|
WHERE metric_name LIKE '%count%' AND NOT pg_input_is_valid(value::text, 'bigint');
|
|
IF invalid_counts > 0 THEN
|
|
RAISE EXCEPTION 'migration 000048: % count value(s) cannot convert losslessly to bigint', invalid_counts
|
|
USING HINT = 'Repair fractional, non-finite, or out-of-range count values, then retry the migration.';
|
|
END IF;
|
|
|
|
SELECT count(*) INTO oversized_dimensions
|
|
FROM reporting_events_rollups
|
|
WHERE length(dimension) > 20;
|
|
IF oversized_dimensions > 0 THEN
|
|
RAISE EXCEPTION 'migration 000048: % dimension value(s) exceed the new 20-character limit', oversized_dimensions
|
|
USING HINT = 'Shorten or explicitly map oversized dimensions, then retry the migration.';
|
|
END IF;
|
|
|
|
SELECT count(*) INTO collision_groups
|
|
FROM (
|
|
SELECT 1
|
|
FROM reporting_events_rollups
|
|
GROUP BY account_id, period::date, dimension, dimension_value::BIGINT, metric_name
|
|
HAVING count(*) > 1
|
|
) collisions;
|
|
IF collision_groups > 0 THEN
|
|
RAISE EXCEPTION 'migration 000048: % unique-key collision group(s) appear after type conversion', collision_groups
|
|
USING HINT = 'Merge or choose one legacy row in each collision group explicitly, then retry the migration.';
|
|
END IF;
|
|
END $$;
|
|
|
|
CREATE TABLE reporting_events_rollups_v2 (
|
|
id SERIAL PRIMARY KEY,
|
|
account_id INTEGER NOT NULL,
|
|
date DATE NOT NULL,
|
|
dimension_type VARCHAR(20) NOT NULL,
|
|
dimension_id BIGINT NOT NULL,
|
|
metric VARCHAR(50) NOT NULL,
|
|
count BIGINT NOT NULL DEFAULT 0,
|
|
sum_value DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
sum_value_business_hours DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
deleted_at TIMESTAMP WITH TIME ZONE,
|
|
UNIQUE(account_id, date, dimension_type, dimension_id, metric)
|
|
);
|
|
|
|
INSERT INTO reporting_events_rollups_v2 (
|
|
id, account_id, date, dimension_type, dimension_id, metric, count,
|
|
sum_value, sum_value_business_hours, created_at, updated_at, deleted_at
|
|
)
|
|
SELECT
|
|
id,
|
|
account_id,
|
|
period::date,
|
|
dimension,
|
|
dimension_value::BIGINT,
|
|
metric_name,
|
|
CASE WHEN metric_name LIKE '%count%' THEN value::BIGINT ELSE 1 END,
|
|
value,
|
|
COALESCE(value_in_business_hours, 0),
|
|
created_at,
|
|
updated_at,
|
|
deleted_at
|
|
FROM reporting_events_rollups;
|
|
|
|
SELECT setval(
|
|
pg_get_serial_sequence('reporting_events_rollups_v2', 'id'),
|
|
COALESCE((SELECT MAX(id) FROM reporting_events_rollups_v2), 1),
|
|
EXISTS (SELECT 1 FROM reporting_events_rollups_v2)
|
|
);
|
|
|
|
DROP TABLE reporting_events_rollups;
|
|
ALTER TABLE reporting_events_rollups_v2 RENAME TO reporting_events_rollups;
|
|
ALTER INDEX reporting_events_rollups_v2_pkey RENAME TO reporting_events_rollups_pkey;
|
|
CREATE INDEX idx_reporting_events_rollups_deleted_at ON reporting_events_rollups(deleted_at);
|
|
CREATE INDEX idx_reporting_events_rollups_account_id ON reporting_events_rollups(account_id) WHERE deleted_at IS NULL;
|
|
CREATE INDEX idx_reporting_events_rollups_date ON reporting_events_rollups(date) WHERE deleted_at IS NULL;
|
|
CREATE INDEX idx_reporting_events_rollups_dimension ON reporting_events_rollups(dimension_type, dimension_id) WHERE deleted_at IS NULL;
|
|
COMMIT;
|