From 3f05200aeb012ee157c26267c9feed41e6307af2 Mon Sep 17 00:00:00 2001 From: irrlicht Date: Fri, 19 Jun 2026 22:53:43 +0200 Subject: [PATCH] migration function --- main.go | 4 ++++ stats.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/main.go b/main.go index af38b8b..509482d 100644 --- a/main.go +++ b/main.go @@ -26,6 +26,10 @@ func main() { initGeoASN() defer closeGeoASN() + // TEMPORÄR: einmalig die Bestands-Impressions ohne asn nachträglich auflösen. + // Nach einem erfolgreichen Lauf wieder entfernen/reverten (samt backfillASN). + backfillASN() + srv := &http.Server{ Addr: envOr("KVER_ADDR", ":8080"), Handler: routes(), diff --git a/stats.go b/stats.go index 3eef3da..8ba53ab 100644 --- a/stats.go +++ b/stats.go @@ -147,6 +147,51 @@ func lookupASN(ip net.IP) string { return label } +// backfillASN setzt das asn-Feld für bereits erfasste Impressions nach, die noch +// keins haben (asn = ''). Nötig, weil recordImpression das asn nur beim ersten +// Insert pro (Tag, Netz, Pfad) schreibt -> Zeilen, die vor aktiver ASN-DB +// entstanden, blieben "(unbekannt)". +// +// TEMPORÄR: einmalig beim Start ausführen, danach den Aufruf (und diese Funktion) +// wieder entfernen/reverten. Arbeitet nur auf dem bereits anonymisierten Netz +// (anon_ip), nie auf einer vollen IP. +func backfillASN() { + if geoASN == nil { + return + } + rows, err := db.Query(`SELECT DISTINCT anon_ip FROM impression WHERE asn = ''`) + if err != nil { + log.Printf("ASN-Backfill: Abfrage fehlgeschlagen: %v", err) + return + } + var nets []string + for rows.Next() { + var anon string + if rows.Scan(&anon) == nil && anon != "" { + nets = append(nets, anon) + } + } + rows.Close() + + var updated, resolved int + for _, anon := range nets { + asn := lookupASN(net.ParseIP(anon)) + if asn == "" { + continue // kein Treffer -> bleibt "(unbekannt)" + } + res, err := db.Exec(`UPDATE impression SET asn = ? WHERE anon_ip = ? AND asn = ''`, asn, anon) + if err != nil { + log.Printf("ASN-Backfill: Update für %s fehlgeschlagen: %v", anon, err) + continue + } + resolved++ + if n, _ := res.RowsAffected(); n > 0 { + updated += int(n) + } + } + log.Printf("ASN-Backfill: %d Netze aufgelöst, %d Zeilen aktualisiert (von %d offenen Netzen)", resolved, updated, len(nets)) +} + // trackImpression zählt einen Seitenaufruf pro (Tag, anonymisiertes Netz, Pfad) // und vermerkt das autonome System. Die IP wird zuerst maskiert; sowohl die // Speicherung als auch die ASN-Auflösung arbeiten nur auf dem anonymisierten