Async barcode scan batch import for 2+ new records
When barcode scan results contain at least 2 new records, enqueue individual Oban jobs instead of importing synchronously. Wishlisted/collected/not_found results still process synchronously.
This commit is contained in:
@@ -5,6 +5,7 @@ defmodule MusicLibrary.BarcodeScan do
|
||||
|
||||
alias MusicLibrary.BarcodeScan.Result
|
||||
alias MusicLibrary.Records
|
||||
alias MusicLibrary.Worker.ImportFromMusicbrainzRelease
|
||||
|
||||
@spec scan(String.t()) :: {:ok, Result.t()} | {:error, term()}
|
||||
def scan(number) do
|
||||
@@ -31,6 +32,32 @@ defmodule MusicLibrary.BarcodeScan do
|
||||
end
|
||||
end
|
||||
|
||||
@spec should_import_async?([Result.t()]) :: boolean()
|
||||
def should_import_async?(scan_results) do
|
||||
Enum.count(scan_results, &(&1.status == :new)) >= 2
|
||||
end
|
||||
|
||||
@spec import_results_async([Result.t()], DateTime.t()) ::
|
||||
{:ok, sync_errors :: [{String.t(), term()}], async_count :: non_neg_integer()}
|
||||
def import_results_async(scan_results, current_time) do
|
||||
{new_results, other_results} = Enum.split_with(scan_results, &(&1.status == :new))
|
||||
|
||||
sync_errors = import_results(other_results, current_time)
|
||||
|
||||
Enum.each(new_results, fn scan_result ->
|
||||
%{
|
||||
"release_id" => scan_result.release.id,
|
||||
"format" => MusicBrainz.ReleaseSearchResult.format(scan_result.release),
|
||||
"purchased_at" => DateTime.to_iso8601(current_time),
|
||||
"selected_release_id" => scan_result.release.id
|
||||
}
|
||||
|> ImportFromMusicbrainzRelease.new()
|
||||
|> Oban.insert!()
|
||||
end)
|
||||
|
||||
{:ok, sync_errors, length(new_results)}
|
||||
end
|
||||
|
||||
@spec import_results([Result.t()], DateTime.t()) :: [{String.t(), term()}]
|
||||
def import_results(scan_results, current_time) do
|
||||
Enum.reduce(scan_results, [], fn scan_result, errors ->
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
defmodule MusicLibrary.Worker.ImportFromMusicbrainzRelease do
|
||||
@moduledoc """
|
||||
Imports a record from a MusicBrainz release in the background.
|
||||
|
||||
Used by barcode scan batch imports when there are multiple new records to import.
|
||||
"""
|
||||
|
||||
use Oban.Worker, queue: :music_brainz, max_attempts: 3
|
||||
|
||||
@impl Oban.Worker
|
||||
def perform(%Oban.Job{args: %{"release_id" => release_id} = args}) do
|
||||
opts = [
|
||||
format: args["format"],
|
||||
purchased_at: parse_datetime(args["purchased_at"]),
|
||||
selected_release_id: args["selected_release_id"]
|
||||
]
|
||||
|
||||
case MusicLibrary.Records.import_from_musicbrainz_release(release_id, opts) do
|
||||
{:ok, _record} -> :ok
|
||||
{:error, reason} -> {:error, reason}
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_datetime(nil), do: nil
|
||||
|
||||
defp parse_datetime(str) do
|
||||
{:ok, datetime, _offset} = DateTime.from_iso8601(str)
|
||||
datetime
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user