5749f48b4a
Milestone #160 Opt 3b. Adds device class as a third context axis on top of the #1531 time-of-day/weekday affinity: on the radio path, a candidate is boosted when its artist concentrates in the current (daypart × weekday × device) cell. Client-sent (client_id is opaque; no UA stored), so it's captured going forward and applies to radio only (daily mixes are cron-built with no device → stay device-agnostic). Server: - Migration 0048: play_events.device_class text NULL (no CHECK; normalized in Go — one whitelist entry per new client class, not a migration). - events.go: eventRequest.device_class + normalizeDeviceClass (whitelist → mobile/web/…, else "other", empty → NULL); threaded through both RecordPlayStartedWithSource and RecordOfflinePlay into InsertPlayEvent. - ListArtistContextPlayCountsForUser gains a current-device param; the cell FILTER adds AND ($2='' OR device_class=$2) — '' reproduces the #1531 time-only behaviour exactly (used by mixes). SessionVector.DeviceClass carries it; the radio handler derives the current device from the user's latest play (GetLatestPlayDeviceClassForUser) — request-free proxy. - No new tuning knob: device narrows the existing ContextAffinityScore (reuses context_time_weight). Clients: - web: play_started sends device_class 'web'. - android: play_started + offline replay send 'mobile' (EventsWire + PlayOfflinePayload + MutationReplayer + PlayEventsReporter). Test: LoadContextAffinity device-narrowing integration test (mobile vs web artist separation; device-agnostic parity). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
10 lines
671 B
SQL
10 lines
671 B
SQL
-- 0048_play_events_device_class.up.sql — device-class context conditioning
|
||
-- (#1551, milestone #160 Opt 3b). Records which class of device a play came
|
||
-- from (mobile / web / …), sent by the client on play-start and normalized
|
||
-- server-side. Extends the #1531 time-of-day/weekday affinity cell to
|
||
-- (daypart × weekday × device) for the radio path. Nullable + no CHECK: values
|
||
-- are normalized in Go (avoids a CHECK-migration each time a client class is
|
||
-- added, rule #36), and historical rows stay NULL → excluded from the device
|
||
-- dimension (a graceful cold-start; the facet ramps as new plays land).
|
||
ALTER TABLE play_events ADD COLUMN device_class text;
|