Files
pinchflat/lib/pinchflat/tasks/source_tasks.ex
T
2024-03-02 19:19:10 -08:00

103 lines
3.1 KiB
Elixir

defmodule Pinchflat.Tasks.SourceTasks do
@moduledoc """
This module contains methods used by or used to control tasks (aka workers)
related to sources.
"""
alias Pinchflat.Media
alias Pinchflat.Tasks
alias Pinchflat.Sources
alias Pinchflat.Sources.Source
alias Pinchflat.MediaClient.SourceDetails
alias Pinchflat.Workers.MediaIndexingWorker
alias Pinchflat.Workers.VideoDownloadWorker
@doc """
Starts tasks for indexing a source's media regardless of the source's indexing
frequency. It's assumed the caller will check for that.
Returns {:ok, %Task{}}.
"""
def kickoff_indexing_task(%Source{} = source) do
Tasks.delete_pending_tasks_for(source, "MediaIndexingWorker")
source
|> Map.take([:id])
# Schedule this one immediately, but future ones will be on an interval
|> MediaIndexingWorker.new()
|> Tasks.create_job_with_task(source)
|> case do
# This should never return {:error, :duplicate_job} since we just deleted
# any pending tasks. I'm being assertive about it so it's obvious if I'm wrong
{:ok, task} -> {:ok, task}
end
end
@doc """
Given a media source, creates (indexes) the media by creating media_items for each
media ID in the source.
Returns [%MediaItem{}, ...] | [%Ecto.Changeset{}, ...]
"""
def index_media_items(%Source{} = source) do
{:ok, media_attributes} = SourceDetails.get_media_attributes(source.original_url)
Sources.update_source(source, %{last_indexed_at: DateTime.utc_now()})
media_attributes
|> Enum.map(fn media_attrs ->
attrs = %{
source_id: source.id,
title: media_attrs["title"],
media_id: media_attrs["id"],
original_url: media_attrs["original_url"],
livestream: media_attrs["was_live"],
description: media_attrs["description"]
}
case Media.create_media_item(attrs) do
{:ok, media_item} -> media_item
{:error, changeset} -> changeset
end
end)
end
@doc """
Starts tasks for downloading videos for any of a sources _pending_ media items.
Jobs are not enqueued if the source is set to not download media. This will return :ok.
NOTE: this starts a download for each media item that is pending,
not just the ones that were indexed in this job run. This should ensure
that any stragglers are caught if, for some reason, they weren't enqueued
or somehow got de-queued.
I'm not sure of a case where this would happen, but it's cheap insurance.
Returns :ok
"""
def enqueue_pending_media_tasks(%Source{download_media: true} = source) do
source
|> Media.list_pending_media_items_for()
|> Enum.each(fn media_item ->
media_item
|> Map.take([:id])
|> VideoDownloadWorker.new()
|> Tasks.create_job_with_task(media_item)
end)
end
def enqueue_pending_media_tasks(%Source{download_media: false} = _source) do
:ok
end
@doc """
Deletes ALL pending tasks for a source's media items.
Returns :ok
"""
def dequeue_pending_media_tasks(%Source{} = source) do
source
|> Media.list_pending_media_items_for()
|> Enum.each(&Tasks.delete_pending_tasks_for/1)
end
end