Use stored scrobbled tracks
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@ defmodule LastFm do
|
|||||||
alias LastFm.{API, Feed, Refresh, Scrobble, Track, Worker}
|
alias LastFm.{API, Feed, Refresh, Scrobble, Track, Worker}
|
||||||
alias MusicLibrary.{BackgroundRepo, Repo}
|
alias MusicLibrary.{BackgroundRepo, Repo}
|
||||||
|
|
||||||
def get_scrobbled_tracks, do: Feed.all_tracks()
|
def get_scrobbled_tracks, do: Feed.all_tracks(100)
|
||||||
|
|
||||||
def subscribe_to_feed, do: Feed.subscribe()
|
def subscribe_to_feed, do: Feed.subscribe()
|
||||||
|
|
||||||
|
|||||||
+29
-19
@@ -8,34 +8,44 @@ defmodule LastFm.Feed do
|
|||||||
to one track at a time, and the timestamp has second-level precision.
|
to one track at a time, and the timestamp has second-level precision.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@spec create_table!() :: :ok | no_return
|
import Ecto.Query
|
||||||
def create_table! do
|
|
||||||
__MODULE__ = :ets.new(__MODULE__, [:ordered_set, :named_table, :public])
|
@insertable_fields [
|
||||||
:ok
|
:musicbrainz_id,
|
||||||
end
|
:title,
|
||||||
|
:artist,
|
||||||
|
:album,
|
||||||
|
:cover_url,
|
||||||
|
:scrobbled_at_uts,
|
||||||
|
:scrobbled_at_label,
|
||||||
|
:last_fm_data
|
||||||
|
]
|
||||||
|
|
||||||
@spec update([LastFm.Track.t()]) :: :ok | no_return
|
@spec update([LastFm.Track.t()]) :: :ok | no_return
|
||||||
def update(tracks) do
|
def update(tracks) do
|
||||||
data = Enum.map(tracks, fn t -> {t.scrobbled_at_uts, t} end)
|
track_params =
|
||||||
|
tracks
|
||||||
|
|> Enum.map(fn t -> Map.take(t, @insertable_fields) end)
|
||||||
|
|> Enum.map(&Map.to_list/1)
|
||||||
|
|
||||||
:ets.delete_all_objects(__MODULE__)
|
# HACK: if two tracks happen to have the exact same scrobbled_at_uts,
|
||||||
:ets.insert(__MODULE__, data)
|
# we move it by a sec.
|
||||||
|
MusicLibrary.Repo.insert_all(LastFm.Track, track_params,
|
||||||
|
on_conflict: :nothing,
|
||||||
|
conflict_target: [:scrobbled_at_uts, :title]
|
||||||
|
)
|
||||||
|
|
||||||
Phoenix.PubSub.broadcast(LastFm.PubSub, "feed:update", %{tracks: tracks})
|
Phoenix.PubSub.broadcast(LastFm.PubSub, "feed:update", %{tracks: tracks})
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec all_tracks() :: [LastFm.Track.t()]
|
@spec all_tracks(non_neg_integer()) :: [LastFm.Track.t()]
|
||||||
def all_tracks do
|
def all_tracks(limit) do
|
||||||
m = [
|
q =
|
||||||
{
|
from t in LastFm.Track,
|
||||||
{:_, :_},
|
order_by: {:desc, t.scrobbled_at_uts},
|
||||||
[],
|
limit: ^limit
|
||||||
[{:element, 2, :"$_"}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
# reversing to get tracks in DESC order
|
MusicLibrary.Repo.all(q)
|
||||||
:ets.select_reverse(__MODULE__, m)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec subscribe() :: :ok
|
@spec subscribe() :: :ok
|
||||||
|
|||||||
+1
-22
@@ -1,28 +1,7 @@
|
|||||||
defmodule LastFm.Import do
|
defmodule LastFm.Import do
|
||||||
@insertable_fields [
|
|
||||||
:musicbrainz_id,
|
|
||||||
:title,
|
|
||||||
:artist,
|
|
||||||
:album,
|
|
||||||
:cover_url,
|
|
||||||
:scrobbled_at_uts,
|
|
||||||
:scrobbled_at_label,
|
|
||||||
:last_fm_data
|
|
||||||
]
|
|
||||||
|
|
||||||
def batch(opts) do
|
def batch(opts) do
|
||||||
with {:ok, tracks} <- LastFm.get_tracks(opts) do
|
with {:ok, tracks} <- LastFm.get_tracks(opts) do
|
||||||
track_params =
|
LastFm.Feed.update(tracks)
|
||||||
tracks
|
|
||||||
|> Enum.map(fn t -> Map.take(t, @insertable_fields) end)
|
|
||||||
|> Enum.map(&Map.to_list/1)
|
|
||||||
|
|
||||||
# HACK: if two tracks happen to have the exact same scrobbled_at_uts,
|
|
||||||
# we move it by a sec.
|
|
||||||
MusicLibrary.Repo.insert_all(LastFm.Track, track_params,
|
|
||||||
on_conflict: :nothing,
|
|
||||||
conflict_target: [:scrobbled_at_uts, :title]
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ defmodule LastFm.Supervisor do
|
|||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def init(config) do
|
def init(config) do
|
||||||
:ok = LastFm.Feed.create_table!()
|
|
||||||
|
|
||||||
children = [
|
children = [
|
||||||
{Phoenix.PubSub, name: LastFm.PubSub},
|
{Phoenix.PubSub, name: LastFm.PubSub},
|
||||||
{LastFm.Refresh, config}
|
{LastFm.Refresh, config}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
defmodule LastFm.FeedTest do
|
defmodule LastFm.FeedTest do
|
||||||
use ExUnit.Case, async: true
|
use MusicLibrary.DataCase
|
||||||
|
|
||||||
alias LastFm.{Album, Artist, Feed, Track}
|
alias LastFm.{Album, Artist, Feed, Track}
|
||||||
|
|
||||||
@@ -46,7 +46,13 @@ defmodule LastFm.FeedTest do
|
|||||||
|
|
||||||
test "it returns tracks in descending order of scrobble" do
|
test "it returns tracks in descending order of scrobble" do
|
||||||
:ok = Feed.update([@track_two, @track_one])
|
:ok = Feed.update([@track_two, @track_one])
|
||||||
assert [@track_two, @track_one] == Feed.all_tracks()
|
track_two_scrobbled_at_uts = @track_two.scrobbled_at_uts
|
||||||
|
track_one_scrobbled_at_uts = @track_one.scrobbled_at_uts
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{scrobbled_at_uts: ^track_two_scrobbled_at_uts},
|
||||||
|
%{scrobbled_at_uts: ^track_one_scrobbled_at_uts}
|
||||||
|
] = Feed.all_tracks(10)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user