|
| 1 | +-- Two related changes bundled here: |
| 2 | +-- |
| 3 | +-- 1. package_criticality_spotlight: replace text-based (ecosystem, namespace, name) |
| 4 | +-- matching with a package_id FK so the spotlight join uses an indexed integer key. |
| 5 | +-- |
| 6 | +-- 2. rank_packages(): replace the weighted PERCENT_RANK formula and arbitrary |
| 7 | +-- per-ecosystem top-N caps with cumulative-coverage scoring. |
| 8 | +-- The smallest set of packages that together account for coverage_cutoff (default 90%) |
| 9 | +-- of each signal is critical. impact = average of (1 − cumulative_coverage) across |
| 10 | +-- available signals. is_critical = true if in that set for any signal. |
| 11 | + |
| 12 | +-- ── 1. package_criticality_spotlight schema change ─────────────────────────── |
| 13 | + |
| 14 | +DROP INDEX IF EXISTS package_criticality_spotlight_ecosystem_coalesce_name_idx; |
| 15 | + |
| 16 | +ALTER TABLE package_criticality_spotlight |
| 17 | + ADD COLUMN IF NOT EXISTS package_id bigint NOT NULL REFERENCES packages(id), |
| 18 | + DROP COLUMN IF EXISTS name, |
| 19 | + DROP COLUMN IF EXISTS namespace; |
| 20 | + |
| 21 | +CREATE UNIQUE INDEX IF NOT EXISTS package_criticality_spotlight_package_id_idx |
| 22 | + ON package_criticality_spotlight (package_id); |
| 23 | + |
| 24 | +-- ── 2. rank_packages() ─────────────────────────────────────────────────────── |
| 25 | + |
| 26 | +DROP FUNCTION IF EXISTS rank_packages(numeric, numeric, numeric, jsonb); |
| 27 | + |
| 28 | +CREATE OR REPLACE FUNCTION rank_packages( |
| 29 | + coverage_cutoff numeric DEFAULT 0.90, |
| 30 | + ecosystems text[] DEFAULT NULL |
| 31 | +) |
| 32 | +RETURNS TABLE(processed_rows int) |
| 33 | +LANGUAGE plpgsql AS $$ |
| 34 | +DECLARE |
| 35 | + processed_count int; |
| 36 | + effective_ecosystems text[]; |
| 37 | +BEGIN |
| 38 | + IF ecosystems IS NULL THEN |
| 39 | + SELECT ARRAY_AGG(DISTINCT ecosystem) |
| 40 | + INTO effective_ecosystems |
| 41 | + FROM packages; |
| 42 | + ELSE |
| 43 | + effective_ecosystems := ecosystems; |
| 44 | + END IF; |
| 45 | + |
| 46 | + WITH base AS ( |
| 47 | + SELECT |
| 48 | + id, |
| 49 | + ecosystem, |
| 50 | + COALESCE(downloads_last_30d, 0) AS downloads, |
| 51 | + COALESCE(dependent_count, 0) AS direct_dependents, |
| 52 | + COALESCE(transitive_dependent_count, 0) AS transitive_dependents, |
| 53 | + SUM(COALESCE(downloads_last_30d, 0)) OVER (PARTITION BY ecosystem) AS ecosystem_total_downloads, |
| 54 | + SUM(COALESCE(dependent_count, 0)) OVER (PARTITION BY ecosystem) AS ecosystem_total_direct_dependents, |
| 55 | + SUM(COALESCE(transitive_dependent_count, 0)) OVER (PARTITION BY ecosystem) AS ecosystem_total_transitive_dependents |
| 56 | + FROM packages |
| 57 | + WHERE ecosystem = ANY(effective_ecosystems) |
| 58 | + ), |
| 59 | + walked AS ( |
| 60 | + -- One row per (package × signal). Signals with a zero ecosystem total are |
| 61 | + -- excluded so they don't factor into the average (e.g. downloads for maven). |
| 62 | + -- cumulative_share_exclusive for the top-ranked package equals 0 by arithmetic |
| 63 | + -- (sum of rows above it is 0), so the top package is always inside the critical set. |
| 64 | + SELECT |
| 65 | + id, |
| 66 | + ecosystem, |
| 67 | + SUM(signal_value) OVER coverage_window / ecosystem_signal_total::numeric AS cumulative_share_inclusive, |
| 68 | + (SUM(signal_value) OVER coverage_window - signal_value) / ecosystem_signal_total::numeric AS cumulative_share_exclusive |
| 69 | + FROM base |
| 70 | + CROSS JOIN LATERAL (VALUES |
| 71 | + ('downloads', downloads, ecosystem_total_downloads), |
| 72 | + ('direct_dependents', direct_dependents, ecosystem_total_direct_dependents), |
| 73 | + ('transitive_dependents', transitive_dependents, ecosystem_total_transitive_dependents) |
| 74 | + ) AS signal(signal_name, signal_value, ecosystem_signal_total) |
| 75 | + WHERE ecosystem_signal_total > 0 |
| 76 | + WINDOW coverage_window AS ( |
| 77 | + PARTITION BY ecosystem, signal_name |
| 78 | + ORDER BY signal_value DESC, id |
| 79 | + ROWS UNBOUNDED PRECEDING |
| 80 | + ) |
| 81 | + ), |
| 82 | + combined AS ( |
| 83 | + SELECT |
| 84 | + id, |
| 85 | + ecosystem, |
| 86 | + AVG(1.0 - cumulative_share_inclusive)::numeric(10, 4) AS new_impact, |
| 87 | + BOOL_OR(cumulative_share_exclusive < coverage_cutoff) AS new_is_critical |
| 88 | + FROM walked |
| 89 | + GROUP BY id, ecosystem |
| 90 | + ), |
| 91 | + final AS ( |
| 92 | + SELECT |
| 93 | + combined.id, |
| 94 | + combined.new_impact, |
| 95 | + combined.new_is_critical OR (spotlight.package_id IS NOT NULL) AS new_is_critical, |
| 96 | + ROW_NUMBER() OVER ( |
| 97 | + PARTITION BY combined.ecosystem |
| 98 | + ORDER BY combined.new_impact DESC NULLS LAST, combined.id |
| 99 | + ) AS new_rank_in_ecosystem |
| 100 | + FROM combined |
| 101 | + LEFT JOIN package_criticality_spotlight spotlight ON spotlight.package_id = combined.id |
| 102 | + ) |
| 103 | + UPDATE packages p |
| 104 | + SET impact = final.new_impact, |
| 105 | + is_critical = final.new_is_critical, |
| 106 | + rank_in_ecosystem = final.new_rank_in_ecosystem, |
| 107 | + last_rank_pass_at = NOW(), |
| 108 | + last_synced_at = NOW() |
| 109 | + FROM final |
| 110 | + WHERE p.id = final.id; |
| 111 | + |
| 112 | + GET DIAGNOSTICS processed_count = ROW_COUNT; |
| 113 | + |
| 114 | + RETURN QUERY SELECT processed_count; |
| 115 | +END; |
| 116 | +$$; |
0 commit comments