When importing a record, stream all its releases

This commit is contained in:
Claudio Ortolina
2025-02-05 15:31:08 +00:00
parent f29dd1f0ab
commit 6ad28f1271
6 changed files with 40 additions and 15 deletions
+2 -1
View File
@@ -1,10 +1,11 @@
defmodule MusicBrainz.APIBehaviour do
@type musicbrainz_id :: String.t()
@type config :: MusicBrainz.Config.t()
@type limit :: pos_integer()
@callback get_release_group(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()}
@callback get_releases(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()}
@callback get_releases(musicbrainz_id, limit, config) :: {:ok, map()} | {:error, String.t()}
@callback get_release(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()}
+11 -2
View File
@@ -7,6 +7,7 @@ defmodule MusicBrainz.APIImpl do
"""
@behaviour MusicBrainz.APIBehaviour
@base_url "https://musicbrainz.org/ws/2"
require Logger
@@ -288,9 +289,17 @@ defmodule MusicBrainz.APIImpl do
end
@impl true
def get_releases(release_group_id, config) do
def get_releases(release_group_id, opts, config) do
Keyword.validate!(opts, [:limit, :offset])
opts =
Keyword.merge(opts,
fmt: "json",
"release-group": release_group_id
)
url =
"https://musicbrainz.org/ws/2/release?fmt=json&limit=100&release-group=#{release_group_id}"
@base_url <> "/release?" <> URI.encode_query(opts)
json_get(url, config)
end
+22 -7
View File
@@ -226,14 +226,29 @@ defmodule MusicLibrary.Records do
end
end
# TODO: paginate and merge as needed
defp merge_releases(musicbrainz_id, musicbrainz_data) do
with {:ok, data} <-
music_brainz_config().api.get_releases(
musicbrainz_id,
music_brainz_config()
) do
{:ok, Map.put(musicbrainz_data, "releases", data["releases"])}
with {:ok, releases} <- stream_releases(musicbrainz_id) do
{:ok, Map.put(musicbrainz_data, "releases", releases)}
end
end
defp stream_releases(musicbrainz_id) do
do_stream_releases(musicbrainz_id, [], 0)
end
defp do_stream_releases(musicbrainz_id, releases, offset) do
limit = 100
opts = [limit: limit, offset: offset]
case music_brainz_config().api.get_releases(musicbrainz_id, opts, music_brainz_config()) do
{:ok, data} ->
%{"releases" => new_releases} = data
if Enum.count(new_releases) < limit do
{:ok, releases ++ new_releases}
else
do_stream_releases(musicbrainz_id, releases ++ new_releases, offset + 100)
end
end
end
+3 -3
View File
@@ -66,7 +66,7 @@ defmodule MusicLibrary.RecordsTest do
{:ok, release_group(:lockdown_trilogy)}
end)
expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _config ->
expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _opts, _config ->
{:ok, %{"releases" => release_group(:lockdown_trilogy)["releases"]}}
end)
@@ -207,7 +207,7 @@ defmodule MusicLibrary.RecordsTest do
{:ok, release_group}
end)
expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _config ->
expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _opts, _config ->
{:ok, %{"releases" => release_group["releases"]}}
end)
@@ -264,7 +264,7 @@ defmodule MusicLibrary.RecordsTest do
{:ok, release_group}
end)
expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _config ->
expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _opts, _config ->
{:ok, %{"releases" => release_group["releases"]}}
end)
@@ -271,7 +271,7 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
{:ok, release_group}
end)
expect(APIBehaviourMock, :get_releases, fn ^first_result_id, _config ->
expect(APIBehaviourMock, :get_releases, fn ^first_result_id, _opts, _config ->
{:ok, %{"releases" => release_group["releases"]}}
end)
@@ -193,7 +193,7 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do
{:ok, release_group}
end)
expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _config ->
expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _opts, _config ->
{:ok, %{"releases" => release_group["releases"]}}
end)