mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-09 20:50:20 +08:00
fix: repair missing routing profiles snapshot
This commit is contained in:
+82
@@ -0,0 +1,82 @@
|
||||
CREATE TABLE IF NOT EXISTS public.routing_groups (
|
||||
id character varying(64) NOT NULL,
|
||||
name character varying(255) NOT NULL,
|
||||
description text,
|
||||
enabled boolean DEFAULT true NOT NULL,
|
||||
is_system_default boolean DEFAULT false NOT NULL,
|
||||
config_json jsonb NOT NULL,
|
||||
version bigint DEFAULT 1 NOT NULL,
|
||||
created_at bigint NOT NULL,
|
||||
updated_at bigint NOT NULL,
|
||||
published_at bigint
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_groups_pkey'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_groups
|
||||
ADD CONSTRAINT routing_groups_pkey PRIMARY KEY (id);
|
||||
END IF;
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_groups_name_key'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_groups
|
||||
ADD CONSTRAINT routing_groups_name_key UNIQUE (name);
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE INDEX IF NOT EXISTS routing_groups_system_default_idx
|
||||
ON public.routing_groups USING btree (is_system_default, enabled);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.routing_group_bindings (
|
||||
id character varying(64) NOT NULL,
|
||||
group_id character varying(64) NOT NULL,
|
||||
subject_type character varying(32) NOT NULL,
|
||||
subject_id character varying(64) NOT NULL,
|
||||
is_default boolean DEFAULT false NOT NULL,
|
||||
allow_explicit_select boolean DEFAULT true NOT NULL,
|
||||
created_at bigint NOT NULL,
|
||||
updated_at bigint NOT NULL
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_bindings_pkey'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_group_bindings
|
||||
ADD CONSTRAINT routing_group_bindings_pkey PRIMARY KEY (id);
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE INDEX IF NOT EXISTS routing_group_bindings_group_id_idx
|
||||
ON public.routing_group_bindings USING btree (group_id);
|
||||
CREATE INDEX IF NOT EXISTS routing_group_bindings_subject_idx
|
||||
ON public.routing_group_bindings USING btree (subject_type, subject_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.routing_group_versions (
|
||||
id character varying(64) NOT NULL,
|
||||
group_id character varying(64) NOT NULL,
|
||||
version bigint NOT NULL,
|
||||
config_json jsonb NOT NULL,
|
||||
created_at bigint NOT NULL,
|
||||
created_by character varying(64)
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_versions_pkey'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_group_versions
|
||||
ADD CONSTRAINT routing_group_versions_pkey PRIMARY KEY (id);
|
||||
END IF;
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_versions_group_version_key'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_group_versions
|
||||
ADD CONSTRAINT routing_group_versions_group_version_key UNIQUE (group_id, version);
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE INDEX IF NOT EXISTS routing_group_versions_group_id_idx
|
||||
ON public.routing_group_versions USING btree (group_id);
|
||||
@@ -0,0 +1,82 @@
|
||||
CREATE TABLE IF NOT EXISTS public.routing_groups (
|
||||
id character varying(64) NOT NULL,
|
||||
name character varying(255) NOT NULL,
|
||||
description text,
|
||||
enabled boolean DEFAULT true NOT NULL,
|
||||
is_system_default boolean DEFAULT false NOT NULL,
|
||||
config_json jsonb NOT NULL,
|
||||
version bigint DEFAULT 1 NOT NULL,
|
||||
created_at bigint NOT NULL,
|
||||
updated_at bigint NOT NULL,
|
||||
published_at bigint
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_groups_pkey'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_groups
|
||||
ADD CONSTRAINT routing_groups_pkey PRIMARY KEY (id);
|
||||
END IF;
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_groups_name_key'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_groups
|
||||
ADD CONSTRAINT routing_groups_name_key UNIQUE (name);
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE INDEX IF NOT EXISTS routing_groups_system_default_idx
|
||||
ON public.routing_groups USING btree (is_system_default, enabled);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.routing_group_bindings (
|
||||
id character varying(64) NOT NULL,
|
||||
group_id character varying(64) NOT NULL,
|
||||
subject_type character varying(32) NOT NULL,
|
||||
subject_id character varying(64) NOT NULL,
|
||||
is_default boolean DEFAULT false NOT NULL,
|
||||
allow_explicit_select boolean DEFAULT true NOT NULL,
|
||||
created_at bigint NOT NULL,
|
||||
updated_at bigint NOT NULL
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_bindings_pkey'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_group_bindings
|
||||
ADD CONSTRAINT routing_group_bindings_pkey PRIMARY KEY (id);
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE INDEX IF NOT EXISTS routing_group_bindings_group_id_idx
|
||||
ON public.routing_group_bindings USING btree (group_id);
|
||||
CREATE INDEX IF NOT EXISTS routing_group_bindings_subject_idx
|
||||
ON public.routing_group_bindings USING btree (subject_type, subject_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.routing_group_versions (
|
||||
id character varying(64) NOT NULL,
|
||||
group_id character varying(64) NOT NULL,
|
||||
version bigint NOT NULL,
|
||||
config_json jsonb NOT NULL,
|
||||
created_at bigint NOT NULL,
|
||||
created_by character varying(64)
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_versions_pkey'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_group_versions
|
||||
ADD CONSTRAINT routing_group_versions_pkey PRIMARY KEY (id);
|
||||
END IF;
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_versions_group_version_key'
|
||||
) THEN
|
||||
ALTER TABLE ONLY public.routing_group_versions
|
||||
ADD CONSTRAINT routing_group_versions_group_version_key UNIQUE (group_id, version);
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE INDEX IF NOT EXISTS routing_group_versions_group_id_idx
|
||||
ON public.routing_group_versions USING btree (group_id);
|
||||
@@ -10,3 +10,4 @@
|
||||
130_stats_cost_savings.sql
|
||||
140_proxy_node_metrics.sql
|
||||
150_background_tasks.sql
|
||||
160_routing_profiles.sql
|
||||
|
||||
@@ -7,7 +7,7 @@ use tracing::info;
|
||||
// Generated by build.rs from schema/bootstrap/postgres.
|
||||
pub(crate) static EMPTY_DATABASE_SNAPSHOT_SQL: &str =
|
||||
include_str!(concat!(env!("OUT_DIR"), "/empty_database_snapshot.sql"));
|
||||
pub(crate) const EMPTY_DATABASE_SNAPSHOT_CUTOFF_VERSION: i64 = 20260527000000;
|
||||
pub(crate) const EMPTY_DATABASE_SNAPSHOT_CUTOFF_VERSION: i64 = 20260528000000;
|
||||
|
||||
const PUBLIC_BASE_TABLE_COUNT_SQL: &str = r#"
|
||||
SELECT COUNT(*)::BIGINT
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Child, Command, Stdio};
|
||||
@@ -315,10 +316,60 @@ fn empty_database_snapshot_covers_current_cutoff_versions() {
|
||||
20260522000000,
|
||||
20260524000000,
|
||||
20260527000000,
|
||||
20260528000000,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_database_snapshot_includes_tables_created_by_stamped_migrations() {
|
||||
let snapshot_tables = create_table_names(EMPTY_DATABASE_SNAPSHOT_SQL);
|
||||
let missing_tables = empty_database_snapshot_migrations(&POSTGRES_MIGRATOR)
|
||||
.expect("empty database snapshot migrations should resolve")
|
||||
.into_iter()
|
||||
.flat_map(|migration| create_table_names(migration.sql.as_ref()))
|
||||
.filter(|table| !snapshot_tables.contains(table.as_str()))
|
||||
.collect::<BTreeSet<_>>();
|
||||
|
||||
assert!(
|
||||
missing_tables.is_empty(),
|
||||
"empty database snapshot is missing tables created by stamped migrations: {missing_tables:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn routing_profiles_repair_migration_creates_missing_tables() {
|
||||
let migration = POSTGRES_MIGRATOR
|
||||
.iter()
|
||||
.find(|migration| migration.version == 20260528000000)
|
||||
.expect("routing profiles repair migration should be embedded");
|
||||
|
||||
assert!(migration
|
||||
.sql
|
||||
.contains("CREATE TABLE IF NOT EXISTS public.routing_groups"));
|
||||
assert!(migration
|
||||
.sql
|
||||
.contains("CREATE TABLE IF NOT EXISTS public.routing_group_bindings"));
|
||||
assert!(migration
|
||||
.sql
|
||||
.contains("CREATE TABLE IF NOT EXISTS public.routing_group_versions"));
|
||||
}
|
||||
|
||||
fn create_table_names(sql: &str) -> BTreeSet<String> {
|
||||
sql.lines()
|
||||
.filter_map(|line| {
|
||||
let trimmed = line.trim_start();
|
||||
let table_part = trimmed
|
||||
.strip_prefix("CREATE TABLE IF NOT EXISTS public.")
|
||||
.or_else(|| trimmed.strip_prefix("CREATE TABLE IF NOT EXISTS "))?;
|
||||
let table_name = table_part
|
||||
.split(|ch: char| ch.is_ascii_whitespace() || ch == '(')
|
||||
.next()?;
|
||||
Some(table_name.trim_matches('"').to_string())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_database_snapshot_sql_includes_usage_body_blobs_and_audit_admin_role() {
|
||||
assert!(EMPTY_DATABASE_SNAPSHOT_SQL.contains("'audit_admin'"));
|
||||
@@ -383,9 +434,10 @@ fn empty_database_snapshot_sql_includes_usage_body_blobs_and_audit_admin_role()
|
||||
assert!(
|
||||
EMPTY_DATABASE_SNAPSHOT_SQL.contains("cache_hit_total_requests bigint DEFAULT 0 NOT NULL")
|
||||
);
|
||||
assert!(EMPTY_DATABASE_SNAPSHOT_SQL.contains(
|
||||
"ALTER TABLE public.stats_daily_model\n ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_5m_tokens bigint DEFAULT '0'::bigint NOT NULL,"
|
||||
));
|
||||
let normalized_snapshot_sql = EMPTY_DATABASE_SNAPSHOT_SQL.replace("\r\n", "\n");
|
||||
assert!(normalized_snapshot_sql.contains(
|
||||
"ALTER TABLE public.stats_daily_model\n ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_5m_tokens bigint DEFAULT '0'::bigint NOT NULL,"
|
||||
));
|
||||
assert!(EMPTY_DATABASE_SNAPSHOT_SQL
|
||||
.contains("CREATE TABLE IF NOT EXISTS public.usage_counter_deltas"));
|
||||
assert!(EMPTY_DATABASE_SNAPSHOT_SQL.contains("ix_usage_counter_deltas_unprocessed"));
|
||||
@@ -1222,6 +1274,7 @@ fn pending_migrations_from_applied_skips_versions_already_applied() {
|
||||
20260522000000,
|
||||
20260524000000,
|
||||
20260527000000,
|
||||
20260528000000,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user