Fix listener minutes tracking for accurate geo stats
- Add register-web-listener to now-playing-json API endpoint This keeps listeners registered during continuous playback instead of timing out after 5 minutes of inactivity - Fix listen_minutes calculation to increment by listener_count per poll Previously incremented by 1 regardless of how many listeners, now properly tracks listener-minutes (1 minute per listener per 60s poll interval) - Add migration 009 documenting the calculation fix
This commit is contained in:
parent
8b6209e4e0
commit
249844160f
|
|
@ -138,6 +138,8 @@
|
||||||
(define-api-with-limit asteroid/partial/now-playing-json (&optional mount) (:limit 2 :timeout 1)
|
(define-api-with-limit asteroid/partial/now-playing-json (&optional mount) (:limit 2 :timeout 1)
|
||||||
"Get JSON with now playing info including track ID for favorites.
|
"Get JSON with now playing info including track ID for favorites.
|
||||||
Optional MOUNT parameter specifies which stream to get metadata from."
|
Optional MOUNT parameter specifies which stream to get metadata from."
|
||||||
|
;; Register web listener for geo stats (keeps listener active during playback)
|
||||||
|
(register-web-listener)
|
||||||
(with-error-handling
|
(with-error-handling
|
||||||
(let* ((mount-name (or mount "asteroid.mp3"))
|
(let* ((mount-name (or mount "asteroid.mp3"))
|
||||||
(now-playing-stats (icecast-now-playing *stream-base-url* mount-name)))
|
(now-playing-stats (icecast-now-playing *stream-base-url* mount-name)))
|
||||||
|
|
|
||||||
|
|
@ -268,18 +268,18 @@
|
||||||
(defun update-geo-stats (country-code listener-count &optional city)
|
(defun update-geo-stats (country-code listener-count &optional city)
|
||||||
"Update geo stats for today, optionally including city.
|
"Update geo stats for today, optionally including city.
|
||||||
listener_count tracks peak concurrent listeners (max seen today).
|
listener_count tracks peak concurrent listeners (max seen today).
|
||||||
listen_minutes increments by 1 per poll (approximates total listen time)."
|
listen_minutes increments by listener_count per poll (1 minute per listener per poll)."
|
||||||
(when country-code
|
(when country-code
|
||||||
(handler-case
|
(handler-case
|
||||||
(with-db
|
(with-db
|
||||||
(let ((city-sql (if city (format nil "'~a'" city) "NULL")))
|
(let ((city-sql (if city (format nil "'~a'" city) "NULL")))
|
||||||
(postmodern:execute
|
(postmodern:execute
|
||||||
(format nil "INSERT INTO listener_geo_stats (date, country_code, city, listener_count, listen_minutes)
|
(format nil "INSERT INTO listener_geo_stats (date, country_code, city, listener_count, listen_minutes)
|
||||||
VALUES (CURRENT_DATE, '~a', ~a, ~a, 1)
|
VALUES (CURRENT_DATE, '~a', ~a, ~a, ~a)
|
||||||
ON CONFLICT (date, country_code, city)
|
ON CONFLICT (date, country_code, city)
|
||||||
DO UPDATE SET listener_count = GREATEST(listener_geo_stats.listener_count, ~a),
|
DO UPDATE SET listener_count = GREATEST(listener_geo_stats.listener_count, ~a),
|
||||||
listen_minutes = listener_geo_stats.listen_minutes + 1"
|
listen_minutes = listener_geo_stats.listen_minutes + ~a"
|
||||||
country-code city-sql listener-count listener-count))))
|
country-code city-sql listener-count listener-count listener-count listener-count))))
|
||||||
(error (e)
|
(error (e)
|
||||||
(log:error "Failed to update geo stats: ~a" e)))))
|
(log:error "Failed to update geo stats: ~a" e)))))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
-- Migration: Fix Listen Minutes Calculation
|
||||||
|
-- Version: 009
|
||||||
|
-- Date: 2026-01-11
|
||||||
|
-- Description: Document the fix for listen_minutes calculation
|
||||||
|
--
|
||||||
|
-- ISSUE: listen_minutes was incrementing by 1 per poll regardless of listener count.
|
||||||
|
-- This meant a country with 5 listeners for 1 hour would only show 60 minutes,
|
||||||
|
-- not 300 listener-minutes.
|
||||||
|
--
|
||||||
|
-- FIX: Application code in listener-stats.lisp now increments listen_minutes by
|
||||||
|
-- the listener_count value (1 minute per listener per poll interval).
|
||||||
|
--
|
||||||
|
-- ADDITIONAL FIX: register-web-listener is now called from the now-playing-json API
|
||||||
|
-- endpoint, keeping listeners registered during continuous playback
|
||||||
|
-- instead of timing out after 5 minutes.
|
||||||
|
--
|
||||||
|
-- No schema changes required - this migration documents the application logic fix.
|
||||||
|
|
||||||
|
-- Add a comment to the table for future reference
|
||||||
|
COMMENT ON COLUMN listener_geo_stats.listen_minutes IS
|
||||||
|
'Total listener-minutes: increments by listener_count per poll (1 min per listener per 60s poll)';
|
||||||
|
|
||||||
|
-- Success message
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
RAISE NOTICE 'Migration 009: listen_minutes calculation fix documented';
|
||||||
|
RAISE NOTICE 'listen_minutes now represents true listener-minutes (count * time)';
|
||||||
|
END $$;
|
||||||
Loading…
Reference in New Issue