Fix catastrophic targets query and remove emoji from night mode buttons
The seasonal peak subquery used a correlated SELECT inside a GROUP BY, causing a full nightly_cache scan per object (210-270s for 14k objects). Replaced with a simple MAX() GROUP BY — now instant. Also added three indexes on nightly_cache(night_date) that were missing and causing all dashboard queries to run 2+ second full table scans. Replaced 🔴 emoji in night mode buttons with CSS circles. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -269,8 +269,7 @@ pub async fn list_targets(
|
||||
nc.best_start_utc, nc.best_end_utc, nc.moon_sep_deg,
|
||||
COALESCE(nc.is_visible_tonight, CASE WHEN nc.max_alt_deg >= 15 THEN 1 ELSE 0 END) as is_visible_tonight,
|
||||
COALESCE(log_sum.total_min, 0) as total_integration,
|
||||
seas.peak_alt as seasonal_peak_alt,
|
||||
seas.peak_date as seasonal_peak_date
|
||||
seas.peak_alt as seasonal_peak_alt
|
||||
FROM catalog c
|
||||
LEFT JOIN nightly_cache nc ON nc.catalog_id = c.id AND nc.night_date = '{today}'
|
||||
LEFT JOIN (
|
||||
@@ -278,10 +277,8 @@ pub async fn list_targets(
|
||||
FROM imaging_log GROUP BY catalog_id
|
||||
) log_sum ON log_sum.catalog_id = c.id
|
||||
LEFT JOIN (
|
||||
SELECT catalog_id,
|
||||
MAX(max_alt_deg) as peak_alt,
|
||||
MIN(CASE WHEN max_alt_deg = (SELECT MAX(max_alt_deg) FROM nightly_cache n2 WHERE n2.catalog_id = n1.catalog_id AND n2.night_date BETWEEN '{today}' AND date('{today}', '+90 days')) THEN night_date ELSE NULL END) as peak_date
|
||||
FROM nightly_cache n1
|
||||
SELECT catalog_id, MAX(max_alt_deg) as peak_alt
|
||||
FROM nightly_cache
|
||||
WHERE night_date BETWEEN '{today}' AND date('{today}', '+90 days')
|
||||
GROUP BY catalog_id
|
||||
) seas ON seas.catalog_id = c.id
|
||||
@@ -311,14 +308,23 @@ pub async fn list_targets(
|
||||
use sqlx::Row;
|
||||
let tonight_alt: f64 = row.try_get::<Option<f64>, _>("max_alt_deg").unwrap_or_default().unwrap_or(0.0);
|
||||
let peak_alt: f64 = row.try_get::<Option<f64>, _>("seasonal_peak_alt").unwrap_or_default().unwrap_or(0.0);
|
||||
let peak_date: Option<String> = row.try_get("seasonal_peak_date").unwrap_or_default();
|
||||
// Urgency: compare tonight's altitude to the 90-day seasonal peak.
|
||||
// Direction (rising/declining) is estimated from the object's RA: objects whose
|
||||
// transit RA is ahead of the current sidereal time are rising into season.
|
||||
let ra_deg: f64 = row.try_get::<f64, _>("ra_deg").unwrap_or_default();
|
||||
let urgency: serde_json::Value = if peak_alt >= 15.0 && tonight_alt >= 15.0 {
|
||||
let ratio = tonight_alt / peak_alt;
|
||||
if ratio >= 0.90 {
|
||||
serde_json::json!("peak")
|
||||
} else if ratio >= 0.70 {
|
||||
let before_peak = peak_date.as_deref().map(|d| d > today.as_str()).unwrap_or(true);
|
||||
serde_json::json!(if before_peak { "rising" } else { "declining" })
|
||||
// Rising if the object's RA puts it transiting later this season:
|
||||
// April 17 → sun RA ≈ 27°. Objects with RA 90–270° ahead are rising.
|
||||
let sun_ra = {
|
||||
let day_of_year = chrono::Utc::now().format("%j").to_string().parse::<f64>().unwrap_or(107.0);
|
||||
(day_of_year / 365.25 * 360.0 + 280.46) % 360.0
|
||||
};
|
||||
let diff = (ra_deg - sun_ra).rem_euclid(360.0);
|
||||
serde_json::json!(if diff > 90.0 && diff < 270.0 { "rising" } else { "declining" })
|
||||
} else {
|
||||
serde_json::Value::Null
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ async fn run_migrations(pool: &SqlitePool) -> anyhow::Result<()> {
|
||||
"ALTER TABLE catalog ADD COLUMN arp_num INTEGER",
|
||||
"ALTER TABLE catalog ADD COLUMN melotte_num INTEGER",
|
||||
"ALTER TABLE catalog ADD COLUMN collinder_num INTEGER",
|
||||
// Performance indexes for nightly_cache date-range queries
|
||||
"CREATE INDEX IF NOT EXISTS idx_nc_date ON nightly_cache(night_date)",
|
||||
"CREATE INDEX IF NOT EXISTS idx_nc_date_alt ON nightly_cache(night_date, max_alt_deg)",
|
||||
"CREATE INDEX IF NOT EXISTS idx_nc_catalog_date ON nightly_cache(catalog_id, night_date)",
|
||||
];
|
||||
for sql in migrations {
|
||||
match sqlx::query(sql).execute(pool).await {
|
||||
|
||||
Reference in New Issue
Block a user