fix(taste): drop unused now param + tighten test (golangci-lint revive)
golangci-lint v2 (CI-only; local is v1) flagged two unused-parameter issues: - BuildTasteProfile's `now` was genuinely dead — decay/windowing are computed DB-side via now(), so no Go-side timestamp is threaded. Removed it (a phase-3 context model that needs a pinned reference time would re-add it); updated the scheduler call site. - the degenerate-params engagement test ignored t; reworked it to assert the result stays in [-1,1], which also strengthens the test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -227,7 +227,7 @@ func (s *Scheduler) runStartupCatchUp(ctx context.Context, users []dbq.ListActiv
|
||||
// build can read a fresh profile (phase-2 consumption); both steps are
|
||||
// best-effort and a failure in one is logged without blocking the other.
|
||||
func (s *Scheduler) rebuildUserDaily(ctx context.Context, userID pgtype.UUID, now time.Time) {
|
||||
if err := taste.BuildTasteProfile(ctx, s.pool, s.logger, userID, now, taste.DefaultConfig()); err != nil {
|
||||
if err := taste.BuildTasteProfile(ctx, s.pool, s.logger, userID, taste.DefaultConfig()); err != nil {
|
||||
s.logger.Warn("scheduler: taste profile rebuild failed",
|
||||
"user_id", uuidStringPL(userID), "err", err)
|
||||
}
|
||||
|
||||
@@ -44,11 +44,15 @@ func TestEngagement_MonotonicNonDecreasing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEngagement_DegenerateParamsNoPanic(t *testing.T) {
|
||||
// Non-increasing thresholds must collapse ramps, not divide by zero.
|
||||
func TestEngagement_DegenerateParamsStayInRange(t *testing.T) {
|
||||
// Non-increasing thresholds must collapse ramps (no divide-by-zero) and
|
||||
// still produce a value in [-1, 1].
|
||||
p := EngagementParams{HardSkip: 0.5, NeutralCompletion: 0.5, FullCompletion: 0.5}
|
||||
for _, c := range []float64{0, 0.25, 0.5, 0.75, 1} {
|
||||
_ = Engagement(c, p)
|
||||
got := Engagement(c, p)
|
||||
if got < -1 || got > 1 {
|
||||
t.Errorf("Engagement(%.2f) = %.3f out of [-1,1]", c, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"log/slog"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
@@ -81,9 +80,13 @@ func DefaultConfig() Config {
|
||||
// Self-contained transaction for the replace. Returns an error only on a
|
||||
// fatal DB failure; the daily caller logs and proceeds to playlist building
|
||||
// regardless (best-effort).
|
||||
//
|
||||
// The decay reference time is the database clock (age is computed in SQL via
|
||||
// now()), so no Go-side timestamp is threaded here; a phase-3 context model
|
||||
// that needs a pinned reference time would add one.
|
||||
func BuildTasteProfile(
|
||||
ctx context.Context, pool *pgxpool.Pool, logger *slog.Logger,
|
||||
userID pgtype.UUID, now time.Time, cfg Config,
|
||||
userID pgtype.UUID, cfg Config,
|
||||
) error {
|
||||
q := dbq.New(pool)
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ func TestBuildTasteProfile_PositiveVsNegative(t *testing.T) {
|
||||
seedPlay(t, pool, u.ID, skippedTrack.ID, now.Add(-time.Duration(i+1)*time.Hour), 0.02)
|
||||
}
|
||||
|
||||
if err := BuildTasteProfile(context.Background(), pool, discardLogger(), u.ID, now, DefaultConfig()); err != nil {
|
||||
if err := BuildTasteProfile(context.Background(), pool, discardLogger(), u.ID, DefaultConfig()); err != nil {
|
||||
t.Fatalf("build: %v", err)
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ func TestBuildTasteProfile_AggregationProtectsArtist(t *testing.T) {
|
||||
skipTrack := seedTrack(t, pool, fav.ID, "Indie")
|
||||
seedPlay(t, pool, u.ID, skipTrack.ID, now.Add(-2*time.Hour), 0.02)
|
||||
|
||||
if err := BuildTasteProfile(context.Background(), pool, discardLogger(), u.ID, now, DefaultConfig()); err != nil {
|
||||
if err := BuildTasteProfile(context.Background(), pool, discardLogger(), u.ID, DefaultConfig()); err != nil {
|
||||
t.Fatalf("build: %v", err)
|
||||
}
|
||||
w, ok := artistWeight(t, pool, u.ID, fav.ID)
|
||||
@@ -203,7 +203,6 @@ func TestBuildTasteProfile_AggregationProtectsArtist(t *testing.T) {
|
||||
// plays still earns a positive weight from the like bonus.
|
||||
func TestBuildTasteProfile_ArtistLikeBonus(t *testing.T) {
|
||||
pool := newPool(t)
|
||||
now := time.Now().UTC()
|
||||
u := seedUser(t, pool, "tp3")
|
||||
liked := seedArtist(t, pool, "LikedOnly")
|
||||
if _, err := pool.Exec(context.Background(),
|
||||
@@ -212,7 +211,7 @@ func TestBuildTasteProfile_ArtistLikeBonus(t *testing.T) {
|
||||
t.Fatalf("seed artist like: %v", err)
|
||||
}
|
||||
|
||||
if err := BuildTasteProfile(context.Background(), pool, discardLogger(), u.ID, now, DefaultConfig()); err != nil {
|
||||
if err := BuildTasteProfile(context.Background(), pool, discardLogger(), u.ID, DefaultConfig()); err != nil {
|
||||
t.Fatalf("build: %v", err)
|
||||
}
|
||||
w, ok := artistWeight(t, pool, u.ID, liked.ID)
|
||||
@@ -240,7 +239,7 @@ func TestBuildTasteProfile_AtomicReplace(t *testing.T) {
|
||||
return n
|
||||
}
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := BuildTasteProfile(ctx, pool, discardLogger(), u.ID, now, DefaultConfig()); err != nil {
|
||||
if err := BuildTasteProfile(ctx, pool, discardLogger(), u.ID, DefaultConfig()); err != nil {
|
||||
t.Fatalf("build %d: %v", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user