mirror of
https://github.com/hansjone/netx.git
synced 2026-10-11 05:43:20 +08:00
fix(ume): key-alert DB migration fails on psycopg3 LIKE placeholder
Use starts_with() instead of LIKE kw:% and run each DDL step in its own transaction so match_type/match_value columns are added reliably. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
b54a6e5ad4
commit
300fd74565
1 changed files with 59 additions and 37 deletions
|
|
@ -693,43 +693,55 @@ def _configure_ume_diag_logging() -> None:
|
||||||
|
|
||||||
|
|
||||||
def _migrate_key_alert_rule_schema() -> None:
|
def _migrate_key_alert_rule_schema() -> None:
|
||||||
"""Evolve ume_key_alert_rule in its own transaction (avoid rollback with bulk startup DDL)."""
|
"""Evolve ume_key_alert_rule in isolated transactions (psycopg3 rejects unescaped % in SQL)."""
|
||||||
try:
|
steps = [
|
||||||
with engine.begin() as conn:
|
(
|
||||||
conn.exec_driver_sql(
|
"add match_type",
|
||||||
"ALTER TABLE ume_key_alert_rule ADD COLUMN IF NOT EXISTS match_type VARCHAR(32) DEFAULT 'notification_id'"
|
"ALTER TABLE ume_key_alert_rule ADD COLUMN IF NOT EXISTS match_type VARCHAR(32) DEFAULT 'notification_id'",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"add match_value",
|
||||||
|
"ALTER TABLE ume_key_alert_rule ADD COLUMN IF NOT EXISTS match_value VARCHAR(256) DEFAULT ''",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"create monitor_config",
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS ume_key_alert_monitor_config (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
forward_on_clear INTEGER DEFAULT 0,
|
||||||
|
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW()
|
||||||
)
|
)
|
||||||
conn.exec_driver_sql(
|
""",
|
||||||
"ALTER TABLE ume_key_alert_rule ADD COLUMN IF NOT EXISTS match_value VARCHAR(256) DEFAULT ''"
|
),
|
||||||
)
|
(
|
||||||
conn.exec_driver_sql(
|
"seed monitor_config",
|
||||||
"UPDATE ume_key_alert_rule SET match_value = notification_id "
|
"INSERT INTO ume_key_alert_monitor_config (id, forward_on_clear, updated_at) "
|
||||||
"WHERE (match_value IS NULL OR match_value = '') AND notification_id NOT LIKE 'kw:%'"
|
"VALUES (1, 0, NOW()) ON CONFLICT (id) DO NOTHING",
|
||||||
)
|
),
|
||||||
conn.exec_driver_sql(
|
(
|
||||||
"UPDATE ume_key_alert_rule SET match_type = 'keyword', match_value = SUBSTRING(notification_id FROM 4) "
|
"backfill match_value from notification_id",
|
||||||
"WHERE notification_id LIKE 'kw:%' "
|
"UPDATE ume_key_alert_rule SET match_value = notification_id "
|
||||||
"AND (match_type IS NULL OR match_type = '' OR match_type = 'notification_id')"
|
"WHERE (match_value IS NULL OR match_value = '') "
|
||||||
)
|
"AND NOT starts_with(notification_id, 'kw:')",
|
||||||
conn.exec_driver_sql(
|
),
|
||||||
"""
|
(
|
||||||
CREATE TABLE IF NOT EXISTS ume_key_alert_monitor_config (
|
"backfill keyword rules",
|
||||||
id INTEGER PRIMARY KEY,
|
"UPDATE ume_key_alert_rule SET match_type = 'keyword', match_value = SUBSTRING(notification_id FROM 4) "
|
||||||
forward_on_clear INTEGER DEFAULT 0,
|
"WHERE starts_with(notification_id, 'kw:') "
|
||||||
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW()
|
"AND (match_type IS NULL OR match_type = '' OR match_type = 'notification_id')",
|
||||||
)
|
),
|
||||||
"""
|
(
|
||||||
)
|
"migrate forward_on_clear to global config",
|
||||||
conn.exec_driver_sql(
|
"UPDATE ume_key_alert_monitor_config SET forward_on_clear = 1, updated_at = NOW() "
|
||||||
"INSERT INTO ume_key_alert_monitor_config (id, forward_on_clear, updated_at) "
|
"WHERE id = 1 AND EXISTS (SELECT 1 FROM ume_key_alert_rule WHERE forward_on_clear = 1)",
|
||||||
"VALUES (1, 0, NOW()) ON CONFLICT (id) DO NOTHING"
|
),
|
||||||
)
|
]
|
||||||
conn.exec_driver_sql(
|
for label, sql in steps:
|
||||||
"UPDATE ume_key_alert_monitor_config SET forward_on_clear = 1, updated_at = NOW() "
|
try:
|
||||||
"WHERE id = 1 AND EXISTS (SELECT 1 FROM ume_key_alert_rule WHERE forward_on_clear = 1)"
|
with engine.begin() as conn:
|
||||||
)
|
conn.exec_driver_sql(sql)
|
||||||
except Exception:
|
except Exception:
|
||||||
_schedule_log.exception("startup: ume_key_alert_rule schema migration failed")
|
_schedule_log.exception("startup: ume_key_alert_rule schema migration failed at %s", label)
|
||||||
invalidate_key_alert_config_cache()
|
invalidate_key_alert_config_cache()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1348,7 +1360,17 @@ def ume_upsert_key_alert_rule(payload: dict[str, Any], db: Session = Depends(get
|
||||||
"enabled": bool(enabled),
|
"enabled": bool(enabled),
|
||||||
"label": label,
|
"label": label,
|
||||||
}
|
}
|
||||||
db.commit()
|
try:
|
||||||
|
db.commit()
|
||||||
|
except Exception as exc:
|
||||||
|
db.rollback()
|
||||||
|
msg = str(exc).lower()
|
||||||
|
if "match_type" in msg or "match_value" in msg or "undefinedcolumn" in msg:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=503,
|
||||||
|
detail="key_alert_schema_outdated: restart netx API to apply database migration",
|
||||||
|
) from exc
|
||||||
|
raise
|
||||||
invalidate_key_alert_rule_cache()
|
invalidate_key_alert_rule_cache()
|
||||||
return {"ok": True, "item": saved}
|
return {"ok": True, "item": saved}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue