mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-01 19:47:37 +03:00
parent
18143fa5a1
commit
f5df948eb1
4 changed files with 44 additions and 15 deletions
30
db/migration/20240426202913_add_id_to_scrobble_buffer.go
Normal file
30
db/migration/20240426202913_add_id_to_scrobble_buffer.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/pressly/goose/v3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
goose.AddMigrationContext(upAddIdToScrobbleBuffer, downAddIdToScrobbleBuffer)
|
||||
}
|
||||
|
||||
func upAddIdToScrobbleBuffer(ctx context.Context, tx *sql.Tx) error {
|
||||
_, err := tx.ExecContext(ctx, `
|
||||
delete from scrobble_buffer where user_id <> '';
|
||||
alter table scrobble_buffer add id varchar not null default '';
|
||||
create unique index scrobble_buffer_id_ix
|
||||
on scrobble_buffer (id);
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func downAddIdToScrobbleBuffer(ctx context.Context, tx *sql.Tx) error {
|
||||
_, err := tx.ExecContext(ctx, `
|
||||
drop index scrobble_buffer_id_ix;
|
||||
alter table scrobble_buffer drop id;
|
||||
`)
|
||||
return err
|
||||
}
|
|
@ -3,11 +3,13 @@ package model
|
|||
import "time"
|
||||
|
||||
type ScrobbleEntry struct {
|
||||
MediaFile
|
||||
ID string
|
||||
Service string
|
||||
UserID string `structs:"user_id"`
|
||||
UserID string
|
||||
PlayTime time.Time
|
||||
EnqueueTime time.Time
|
||||
MediaFileID string
|
||||
MediaFile
|
||||
}
|
||||
|
||||
type ScrobbleEntries []ScrobbleEntry
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
. "github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/pocketbase/dbx"
|
||||
)
|
||||
|
@ -37,6 +38,7 @@ func (r *scrobbleBufferRepository) UserIDs(service string) ([]string, error) {
|
|||
|
||||
func (r *scrobbleBufferRepository) Enqueue(service, userId, mediaFileId string, playTime time.Time) error {
|
||||
ins := Insert(r.tableName).SetMap(map[string]interface{}{
|
||||
"id": uuid.NewString(),
|
||||
"user_id": userId,
|
||||
"service": service,
|
||||
"media_file_id": mediaFileId,
|
||||
|
@ -48,7 +50,8 @@ func (r *scrobbleBufferRepository) Enqueue(service, userId, mediaFileId string,
|
|||
}
|
||||
|
||||
func (r *scrobbleBufferRepository) Next(service string, userId string) (*model.ScrobbleEntry, error) {
|
||||
sql := Select().Columns("s.*, m.*").
|
||||
// Put `s.*` last or else m.id overrides s.id
|
||||
sql := Select().Columns("m.*, s.*").
|
||||
From(r.tableName+" s").
|
||||
LeftJoin("media_file m on m.id = s.media_file_id").
|
||||
Where(And{
|
||||
|
@ -57,24 +60,20 @@ func (r *scrobbleBufferRepository) Next(service string, userId string) (*model.S
|
|||
}).
|
||||
OrderBy("play_time", "s.rowid").Limit(1)
|
||||
|
||||
res := model.ScrobbleEntries{}
|
||||
// TODO Rewrite queryOne to use QueryRows, to workaround the recursive embedded structs issue
|
||||
err := r.queryAll(sql, &res)
|
||||
if errors.Is(err, model.ErrNotFound) || len(res) == 0 {
|
||||
res := &model.ScrobbleEntry{}
|
||||
err := r.queryOne(sql, res)
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &res[0], nil
|
||||
res.MediaFile.ID = res.MediaFileID
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (r *scrobbleBufferRepository) Dequeue(entry *model.ScrobbleEntry) error {
|
||||
return r.delete(And{
|
||||
Eq{"service": entry.Service},
|
||||
Eq{"media_file_id": entry.MediaFile.ID},
|
||||
Eq{"play_time": entry.PlayTime},
|
||||
})
|
||||
return r.delete(Eq{"id": entry.ID})
|
||||
}
|
||||
|
||||
func (r *scrobbleBufferRepository) Length() (int64, error) {
|
||||
|
|
|
@ -157,8 +157,6 @@ func (r sqlRepository) toSQL(sq Sqlizer) (string, dbx.Params, error) {
|
|||
return query, params, nil
|
||||
}
|
||||
|
||||
// Note: Due to a bug in the QueryRow method, this function does not map any embedded structs (ex: annotations)
|
||||
// In this case, use the queryAll method and get the first item of the returned list
|
||||
func (r sqlRepository) queryOne(sq Sqlizer, response interface{}) error {
|
||||
query, args, err := r.toSQL(sq)
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue