diff --git a/lib/last_fm.ex b/lib/last_fm.ex index 1d4d6bce..f0974225 100644 --- a/lib/last_fm.ex +++ b/lib/last_fm.ex @@ -2,7 +2,7 @@ defmodule LastFm do alias LastFm.{API, Feed, Refresh, Scrobble, Track, Worker} 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() diff --git a/lib/last_fm/feed.ex b/lib/last_fm/feed.ex index ef29a454..d197a057 100644 --- a/lib/last_fm/feed.ex +++ b/lib/last_fm/feed.ex @@ -8,34 +8,44 @@ defmodule LastFm.Feed do to one track at a time, and the timestamp has second-level precision. """ - @spec create_table!() :: :ok | no_return - def create_table! do - __MODULE__ = :ets.new(__MODULE__, [:ordered_set, :named_table, :public]) - :ok - end + import Ecto.Query + + @insertable_fields [ + :musicbrainz_id, + :title, + :artist, + :album, + :cover_url, + :scrobbled_at_uts, + :scrobbled_at_label, + :last_fm_data + ] @spec update([LastFm.Track.t()]) :: :ok | no_return 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__) - :ets.insert(__MODULE__, data) + # 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] + ) Phoenix.PubSub.broadcast(LastFm.PubSub, "feed:update", %{tracks: tracks}) end - @spec all_tracks() :: [LastFm.Track.t()] - def all_tracks do - m = [ - { - {:_, :_}, - [], - [{:element, 2, :"$_"}] - } - ] + @spec all_tracks(non_neg_integer()) :: [LastFm.Track.t()] + def all_tracks(limit) do + q = + from t in LastFm.Track, + order_by: {:desc, t.scrobbled_at_uts}, + limit: ^limit - # reversing to get tracks in DESC order - :ets.select_reverse(__MODULE__, m) + MusicLibrary.Repo.all(q) end @spec subscribe() :: :ok diff --git a/lib/last_fm/import.ex b/lib/last_fm/import.ex index 2da2db15..e0747c6b 100644 --- a/lib/last_fm/import.ex +++ b/lib/last_fm/import.ex @@ -1,28 +1,7 @@ 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 with {:ok, tracks} <- LastFm.get_tracks(opts) do - track_params = - 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] - ) + LastFm.Feed.update(tracks) end end end diff --git a/lib/last_fm/supervisor.ex b/lib/last_fm/supervisor.ex index 767bb919..8e018f5f 100644 --- a/lib/last_fm/supervisor.ex +++ b/lib/last_fm/supervisor.ex @@ -7,8 +7,6 @@ defmodule LastFm.Supervisor do @impl true def init(config) do - :ok = LastFm.Feed.create_table!() - children = [ {Phoenix.PubSub, name: LastFm.PubSub}, {LastFm.Refresh, config} diff --git a/test/last_fm/feed_test.exs b/test/last_fm/feed_test.exs index 5c26dc98..ca4a2a31 100644 --- a/test/last_fm/feed_test.exs +++ b/test/last_fm/feed_test.exs @@ -1,5 +1,5 @@ defmodule LastFm.FeedTest do - use ExUnit.Case, async: true + use MusicLibrary.DataCase alias LastFm.{Album, Artist, Feed, Track} @@ -46,7 +46,13 @@ defmodule LastFm.FeedTest do test "it returns tracks in descending order of scrobble" do :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