Files
minstrel/internal/playevents/contextual_likes.go
T
bvandeusen fe1cc46752 feat(api): capture contextual_likes on like during open play_event
Two new helpers in internal/playevents (CaptureContextualLikeIfPlaying,
SoftDeleteContextualLikes) called by both api and subsonic surfaces.
Like inserts a new contextual_likes row when LikeTrack actually
inserted (rows=1) AND there's an open play_event with a vector.
Unlike soft-deletes via deleted_at. Idempotent in both directions.

Subsonic wiring lands in the next commit.
2026-04-27 11:22:35 -04:00

60 lines
1.7 KiB
Go

package playevents
import (
"context"
"errors"
"log/slog"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
)
// CaptureContextualLikeIfPlaying snapshots the user's currently-playing
// session context into a new contextual_likes row. No-op if no open
// play_event exists or its session_vector is NULL. Failures are logged
// but never returned to the caller — contextual capture is best-effort
// and must not break the like response.
func CaptureContextualLikeIfPlaying(
ctx context.Context,
q *dbq.Queries,
userID, trackID pgtype.UUID,
logger *slog.Logger,
) error {
event, err := q.GetOpenPlayEventForUser(ctx, userID)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil // no play in progress; nothing to capture
}
logger.Error("playevents: get open play_event", "err", err)
return nil // best-effort
}
if event.SessionVectorAtPlay == nil {
return nil // event predates this slice; no vector to snapshot
}
if err := q.InsertContextualLike(ctx, dbq.InsertContextualLikeParams{
UserID: userID,
TrackID: trackID,
SessionVector: event.SessionVectorAtPlay,
SessionID: event.SessionID,
}); err != nil {
logger.Error("playevents: insert contextual_like", "err", err)
return nil
}
return nil
}
// SoftDeleteContextualLikes marks all currently-active contextual_likes
// rows for (user, track) as deleted. Idempotent.
func SoftDeleteContextualLikes(
ctx context.Context,
q *dbq.Queries,
userID, trackID pgtype.UUID,
) error {
return q.SoftDeleteContextualLikesForUserTrack(ctx, dbq.SoftDeleteContextualLikesForUserTrackParams{
UserID: userID,
TrackID: trackID,
})
}