feat(api): My Wave sessions with a Go fallback and wave metrics (M4)
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 40s
ci / mobile / mobile (Metro-бандл Android) (push) Failing after 9s
ci / api / api (push) Successful in 35s
ci / ts / ts (packages + web) (push) Successful in 51s

- /wave/options, POST /wave/sessions (activity, mood, seed),
  /next with reactions, PATCH to switch the context on the fly, DELETE
- the recommender is called with an 800 ms budget; on failure the api
  serves a fallback wave of likes, favourite artists and random
  available tracks with the same dislike / recent / served filters
- every served track is an impression with its source and model; wave
  events (context_type wave) set its outcome, reactions win
- library status shows the analysis queue and 7-day wave metrics:
  listen-through, early skip and like rate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Opus 5.5 committed 2026-10-20 12:23:17 +03:00
1 parent ef29b85320
commit 3908814cda
13 files changed
+1811 -162

No files matched your search

+14
View File
@@ -348,3 +348,17 @@ func (st *Store) PutState(ctx context.Context, userID uuid.UUID, s State) (State
// Begin открывает транзакцию.
func (st *Store) Begin(ctx context.Context) (pgx.Tx, error) { return st.pool.Begin(ctx) }
// MarkImpression записывает исход показа трека в сессии волны (для метрик и обучения).
// Реакция (like / dislike) важнее исхода прослушивания и перезаписывает его.
func (st *Store) MarkImpression(ctx context.Context, tx pgx.Tx, sessionID, trackID uuid.UUID, outcome string) error {
_, err := tx.Exec(ctx, `
UPDATE wave_impressions SET outcome = $3
WHERE wave_session_id = $1 AND track_id = $2
AND (outcome IS NULL OR $3 IN ('like', 'dislike') OR outcome NOT IN ('like', 'dislike'))`,
sessionID, trackID, outcome)
if err != nil {
return fmt.Errorf("playback: impression: %w", err)
}
return nil
}