Make stats feed update automatically
This commit is contained in:
@@ -14,11 +14,18 @@ defmodule LastFm.Feed do
|
|||||||
def update(tracks) do
|
def update(tracks) do
|
||||||
data = Enum.map(tracks, fn t -> {t.scrobbled_at_uts, t} end)
|
data = Enum.map(tracks, fn t -> {t.scrobbled_at_uts, t} end)
|
||||||
|
|
||||||
|
:ets.delete_all_objects(__MODULE__)
|
||||||
:ets.insert(__MODULE__, data)
|
:ets.insert(__MODULE__, data)
|
||||||
|
|
||||||
|
Phoenix.PubSub.broadcast(LastFm.PubSub, "feed:update", %{tracks: data})
|
||||||
end
|
end
|
||||||
|
|
||||||
def all do
|
def all do
|
||||||
:ets.tab2list(__MODULE__)
|
:ets.tab2list(__MODULE__)
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def subscribe do
|
||||||
|
Phoenix.PubSub.subscribe(LastFm.PubSub, "feed:update")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+18
-1
@@ -5,12 +5,13 @@ defmodule LastFm.Refresh do
|
|||||||
|
|
||||||
alias LastFm.Feed
|
alias LastFm.Feed
|
||||||
|
|
||||||
@refresh_interval System.convert_time_unit(30, :second, :millisecond)
|
@refresh_interval System.convert_time_unit(10, :second, :millisecond)
|
||||||
|
|
||||||
def start_link(config) do
|
def start_link(config) do
|
||||||
GenServer.start_link(__MODULE__, config, name: __MODULE__)
|
GenServer.start_link(__MODULE__, config, name: __MODULE__)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
def init(config) do
|
def init(config) do
|
||||||
if enabled?(config) do
|
if enabled?(config) do
|
||||||
{:ok, config, {:continue, :refresh}}
|
{:ok, config, {:continue, :refresh}}
|
||||||
@@ -19,6 +20,7 @@ defmodule LastFm.Refresh do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
def handle_continue(:refresh, config) do
|
def handle_continue(:refresh, config) do
|
||||||
case config.api.get_recent_tracks(config.user, config.api_key) do
|
case config.api.get_recent_tracks(config.user, config.api_key) do
|
||||||
{:ok, tracks} ->
|
{:ok, tracks} ->
|
||||||
@@ -33,6 +35,21 @@ defmodule LastFm.Refresh do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_info(:refresh, config) do
|
||||||
|
case config.api.get_recent_tracks(config.user, config.api_key) do
|
||||||
|
{:ok, tracks} ->
|
||||||
|
Feed.update(tracks)
|
||||||
|
Process.send_after(self(), :refresh, @refresh_interval)
|
||||||
|
{:noreply, config}
|
||||||
|
|
||||||
|
{:error, _reason} ->
|
||||||
|
# TODO: think about failure scenario - error is logged at the API level
|
||||||
|
Process.send_after(self(), :refresh, @refresh_interval)
|
||||||
|
{:noreply, config}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp enabled?(config) do
|
defp enabled?(config) do
|
||||||
config.api && config.api_key
|
config.api && config.api_key
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ defmodule LastFm.Supervisor do
|
|||||||
:ok = LastFm.Feed.create_table!()
|
:ok = LastFm.Feed.create_table!()
|
||||||
|
|
||||||
children = [
|
children = [
|
||||||
|
{Phoenix.PubSub, name: LastFm.PubSub},
|
||||||
{LastFm.Refresh, %{api: api(), user: "cloud8421", api_key: api_key()}}
|
{LastFm.Refresh, %{api: api(), user: "cloud8421", api_key: api_key()}}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ defmodule MusicLibraryWeb.StatsLive.Index do
|
|||||||
|
|
||||||
recent_tracks = LastFm.Feed.all()
|
recent_tracks = LastFm.Feed.all()
|
||||||
|
|
||||||
|
if connected?(socket) do
|
||||||
|
LastFm.Feed.subscribe()
|
||||||
|
end
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
socket
|
socket
|
||||||
|> assign(
|
|> assign(
|
||||||
@@ -34,6 +38,17 @@ defmodule MusicLibraryWeb.StatsLive.Index do
|
|||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_info(%{tracks: tracks}, socket) do
|
||||||
|
socket =
|
||||||
|
if socket.assigns.recent_tracks !== tracks do
|
||||||
|
assign(socket, :recent_tracks, tracks)
|
||||||
|
else
|
||||||
|
socket
|
||||||
|
end
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
# The Tailwind build step requires all needed classes to be explicitly referenced
|
# The Tailwind build step requires all needed classes to be explicitly referenced
|
||||||
# in the source code, and not dynamically generated. This implies that one cannot
|
# in the source code, and not dynamically generated. This implies that one cannot
|
||||||
# (for example) interpolate a number in a class name.
|
# (for example) interpolate a number in a class name.
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ msgid "Something went wrong!"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/components/layouts/app.html.heex:7
|
#: lib/music_library_web/components/layouts/app.html.heex:7
|
||||||
#: lib/music_library_web/live/stats_live/index.ex:26
|
#: lib/music_library_web/live/stats_live/index.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Stats"
|
msgid "Stats"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
Reference in New Issue
Block a user