Datenbank von SQLite auf Postgres umgestellt
Verbindung über KVER_DSN; Tabelle user heißt jetzt account (reserviertes Wort in Postgres). kver import-sqlite übernimmt die alte Datei einmalig in einer Transaktion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c6ab082f8c
commit
2714fdb1a5
@@ -192,7 +192,7 @@ func stopImpressionWorker() {
|
||||
// Netz. Gezielt nur auf den HTML-Seiten-Routen, nicht auf API oder Assets.
|
||||
//
|
||||
// Die Erfassung läuft asynchron über den Impression-Worker: der Seitenaufruf
|
||||
// darf nicht auf den DB-Schreib warten (SQLite serialisiert Schreiber). r ist
|
||||
// darf nicht auf den DB-Schreibvorgang warten. r ist
|
||||
// nach Rückkehr des Handlers nicht mehr sicher nutzbar -> wir kopieren die zwei
|
||||
// Werte vorher heraus.
|
||||
func trackImpression(next http.Handler) http.Handler {
|
||||
@@ -214,8 +214,8 @@ func recordImpression(path, anonIP, asn string) {
|
||||
}
|
||||
day := time.Now().UTC().Format("2006-01-02")
|
||||
db.Exec(
|
||||
`INSERT INTO impression (day, anon_ip, path, asn, hits) VALUES (?, ?, ?, ?, 1)
|
||||
ON CONFLICT(day, anon_ip, path) DO UPDATE SET hits = hits + 1`,
|
||||
`INSERT INTO impression (day, anon_ip, path, asn, hits) VALUES ($1, $2, $3, $4, 1)
|
||||
ON CONFLICT (day, anon_ip, path) DO UPDATE SET hits = impression.hits + 1`,
|
||||
day, anonIP, path, asn,
|
||||
)
|
||||
}
|
||||
@@ -225,21 +225,21 @@ func recordImpression(path, anonIP, asn string) {
|
||||
// rechnen. Öffentlich, kein Auth.
|
||||
func handleStatsDetail(w http.ResponseWriter, r *http.Request) {
|
||||
var users, entries, toplevel, votesLeft, votesRight int64
|
||||
db.QueryRow(`SELECT COUNT(*) FROM user`).Scan(&users)
|
||||
db.QueryRow(`SELECT COUNT(*) FROM account`).Scan(&users)
|
||||
db.QueryRow(`SELECT COUNT(*) FROM entry WHERE deleted = 0`).Scan(&entries)
|
||||
db.QueryRow(`SELECT COUNT(*) FROM entry WHERE deleted = 0 AND reply_to = 0`).Scan(&toplevel)
|
||||
db.QueryRow(`SELECT COUNT(*) FROM vote WHERE mode = 'left'`).Scan(&votesLeft)
|
||||
db.QueryRow(`SELECT COUNT(*) FROM vote WHERE mode = 'right'`).Scan(&votesRight)
|
||||
|
||||
var imprTotal, visitorsTotal int64
|
||||
db.QueryRow(`SELECT COALESCE(SUM(hits), 0), COUNT(DISTINCT anon_ip) FROM impression`).
|
||||
db.QueryRow(`SELECT COALESCE(SUM(hits), 0)::bigint, COUNT(DISTINCT anon_ip) FROM impression`).
|
||||
Scan(&imprTotal, &visitorsTotal)
|
||||
|
||||
// Tägliche Impressions + grobe Unique-Netze, jüngste 30 Tage zuerst. Das
|
||||
// Frontend dreht für die Achse auf aufsteigend.
|
||||
daily := []map[string]any{}
|
||||
if rows, err := db.Query(
|
||||
`SELECT day, SUM(hits), COUNT(DISTINCT anon_ip)
|
||||
`SELECT day, SUM(hits)::bigint, COUNT(DISTINCT anon_ip)
|
||||
FROM impression
|
||||
GROUP BY day
|
||||
ORDER BY day DESC
|
||||
@@ -257,7 +257,7 @@ func handleStatsDetail(w http.ResponseWriter, r *http.Request) {
|
||||
topASNs := []map[string]any{}
|
||||
if rows, err := db.Query(
|
||||
`SELECT CASE WHEN asn = '' THEN '(unbekannt)' ELSE asn END AS a,
|
||||
SUM(hits) AS h,
|
||||
SUM(hits)::bigint AS h,
|
||||
COUNT(DISTINCT anon_ip)
|
||||
FROM impression
|
||||
GROUP BY a
|
||||
|
||||
Reference in New Issue
Block a user