From 9033efc9718d7cee43a6ea012d672c55889a2ee6 Mon Sep 17 00:00:00 2001 From: Deluan Date: Sun, 17 Oct 2021 22:58:12 -0400 Subject: [PATCH] Cache smart playlist refreshes for 5 seconds --- persistence/playlist_repository.go | 20 ++++++++++++++++---- persistence/sql_smartplaylist.go | 6 +++--- persistence/sql_smartplaylist_test.go | 6 +++--- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/persistence/playlist_repository.go b/persistence/playlist_repository.go index 37ff8a2df..cb1afd9a7 100644 --- a/persistence/playlist_repository.go +++ b/persistence/playlist_repository.go @@ -173,9 +173,11 @@ func (r *playlistRepository) GetAll(options ...model.QueryOptions) (model.Playli } func (r *playlistRepository) refreshSmartPlaylist(pls *model.Playlist) bool { - if !pls.IsSmartPlaylist() { //|| pls.EvaluatedAt.After(time.Now().Add(-5*time.Second)) { + // Only refresh if it is a smart playlist and was not refreshed in the last 5 seconds + if !pls.IsSmartPlaylist() || time.Since(pls.EvaluatedAt) < 5*time.Second { return false } + log.Debug(r.ctx, "Refreshing smart playlist", "playlist", pls.Name, "id", pls.ID) start := time.Now() @@ -186,7 +188,8 @@ func (r *playlistRepository) refreshSmartPlaylist(pls *model.Playlist) bool { return false } - sp := SmartPlaylist(*pls.Rules) + // Re-populate playlist based on Smart Playlist criteria + sp := smartPlaylist(*pls.Rules) sql := Select("row_number() over (order by "+sp.OrderBy()+") as id", "'"+pls.ID+"' as playlist_id", "media_file.id as media_file_id"). From("media_file").LeftJoin("annotation on (" + "annotation.item_id = media_file.id" + @@ -200,14 +203,23 @@ func (r *playlistRepository) refreshSmartPlaylist(pls *model.Playlist) bool { return false } + // Update playlist stats err = r.updateStats(pls.ID) if err != nil { log.Error(r.ctx, "Error updating smart playlist stats", "playlist", pls.Name, "id", pls.ID, err) return false } + // Update when the playlist was last refreshed (for cache purposes) + updSql := Update(r.tableName).Set("evaluated_at", time.Now()).Where(Eq{"id": pls.ID}) + _, err = r.executeSQL(updSql) + if err != nil { + log.Error(r.ctx, "Error updating smart playlist", "playlist", pls.Name, "id", pls.ID, err) + return false + } + log.Debug(r.ctx, "Refreshed playlist", "playlist", pls.Name, "id", pls.ID, "numTracks", c, "elapsed", time.Since(start)) - pls.EvaluatedAt = time.Now() + return true } @@ -251,8 +263,8 @@ func (r *playlistRepository) updatePlaylist(playlistId string, mediaFileIds []st return r.updateStats(playlistId) } +// updateStats updates total playlist duration, size and count func (r *playlistRepository) updateStats(playlistId string) error { - // Get total playlist duration, size and count statsSql := Select("sum(duration) as duration", "sum(size) as size", "count(*) as count"). From("media_file"). Join("playlist_tracks f on f.media_file_id = media_file.id"). diff --git a/persistence/sql_smartplaylist.go b/persistence/sql_smartplaylist.go index 0c2bda8db..a5bb4dad4 100644 --- a/persistence/sql_smartplaylist.go +++ b/persistence/sql_smartplaylist.go @@ -20,9 +20,9 @@ import ( //"order": "lastPlayed desc", //"limit": 10 //} -type SmartPlaylist model.SmartPlaylist +type smartPlaylist model.SmartPlaylist -func (sp SmartPlaylist) AddCriteria(sql SelectBuilder) SelectBuilder { +func (sp smartPlaylist) AddCriteria(sql SelectBuilder) SelectBuilder { sql = sql.Where(RuleGroup(sp.RuleGroup)).Limit(uint64(sp.Limit)) if order := sp.OrderBy(); order != "" { sql = sql.OrderBy(order) @@ -30,7 +30,7 @@ func (sp SmartPlaylist) AddCriteria(sql SelectBuilder) SelectBuilder { return sql } -func (sp SmartPlaylist) OrderBy() string { +func (sp smartPlaylist) OrderBy() string { order := strings.ToLower(sp.Order) for f, fieldDef := range fieldMap { if strings.HasPrefix(order, f) { diff --git a/persistence/sql_smartplaylist_test.go b/persistence/sql_smartplaylist_test.go index 11d982603..ca0dbc922 100644 --- a/persistence/sql_smartplaylist_test.go +++ b/persistence/sql_smartplaylist_test.go @@ -10,8 +10,8 @@ import ( . "github.com/onsi/gomega" ) -var _ = Describe("SmartPlaylist", func() { - var pls SmartPlaylist +var _ = Describe("smartPlaylist", func() { + var pls smartPlaylist Describe("AddCriteria", func() { BeforeEach(func() { sp := model.SmartPlaylist{ @@ -32,7 +32,7 @@ var _ = Describe("SmartPlaylist", func() { Order: "artist asc", Limit: 100, } - pls = SmartPlaylist(sp) + pls = smartPlaylist(sp) }) It("returns a proper SQL query", func() {