diff --git a/lib/pinchflat/tasks.ex b/lib/pinchflat/tasks.ex new file mode 100644 index 0000000..2b1b81d --- /dev/null +++ b/lib/pinchflat/tasks.ex @@ -0,0 +1,47 @@ +defmodule Pinchflat.Tasks do + @moduledoc """ + The Tasks context. + """ + + import Ecto.Query, warn: false + alias Pinchflat.Repo + + alias Pinchflat.Tasks.Task + + @doc """ + Returns the list of tasks. Returns [%Task{}, ...] + """ + def list_tasks do + Repo.all(Task) + end + + @doc """ + Gets a single task. + + Returns %Task{}. Raises `Ecto.NoResultsError` if the Task does not exist. + """ + def get_task!(id), do: Repo.get!(Task, id) + + @doc """ + Creates a task. Returns {:ok, %Task{}} | {:error, %Ecto.Changeset{}}. + """ + def create_task(attrs \\ %{}) do + %Task{} + |> Task.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Deletes a task. Returns {:ok, %Task{}} | {:error, %Ecto.Changeset{}}. + """ + def delete_task(%Task{} = task) do + Repo.delete(task) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking task changes. + """ + def change_task(%Task{} = task, attrs \\ %{}) do + Task.changeset(task, attrs) + end +end diff --git a/lib/pinchflat/tasks/task.ex b/lib/pinchflat/tasks/task.ex new file mode 100644 index 0000000..4184ee8 --- /dev/null +++ b/lib/pinchflat/tasks/task.ex @@ -0,0 +1,24 @@ +defmodule Pinchflat.Tasks.Task do + @moduledoc """ + The Task schema. + """ + + use Ecto.Schema + import Ecto.Changeset + + alias Pinchflat.MediaSource.Channel + + schema "tasks" do + belongs_to :job, Oban.Job + belongs_to :channel, Channel + + timestamps(type: :utc_datetime) + end + + @doc false + def changeset(task, attrs) do + task + |> cast(attrs, [:job_id, :channel_id]) + |> validate_required([:job_id]) + end +end diff --git a/priv/repo/migrations/20240125212753_create_tasks.exs b/priv/repo/migrations/20240125212753_create_tasks.exs new file mode 100644 index 0000000..79b63ab --- /dev/null +++ b/priv/repo/migrations/20240125212753_create_tasks.exs @@ -0,0 +1,15 @@ +defmodule Pinchflat.Repo.Migrations.CreateTasks do + use Ecto.Migration + + def change do + create table(:tasks) do + add :job_id, references(:oban_jobs, on_delete: :delete_all), null: false + add :channel_id, references(:channels, on_delete: :delete_all), null: true + + timestamps(type: :utc_datetime) + end + + create index(:tasks, [:job_id]) + create index(:tasks, [:channel_id]) + end +end diff --git a/test/pinchflat/tasks_test.exs b/test/pinchflat/tasks_test.exs new file mode 100644 index 0000000..7635528 --- /dev/null +++ b/test/pinchflat/tasks_test.exs @@ -0,0 +1,51 @@ +defmodule Pinchflat.TasksTest do + use Pinchflat.DataCase + import Pinchflat.JobFixtures + import Pinchflat.TasksFixtures + + alias Pinchflat.Tasks + alias Pinchflat.Tasks.Task + + @invalid_attrs %{job_id: nil} + + describe "list_tasks/0" do + test "it returns all tasks" do + task = task_fixture() + assert Tasks.list_tasks() == [task] + end + end + + describe "get_task!/1" do + test "it returns the task with given id" do + task = task_fixture() + assert Tasks.get_task!(task.id) == task + end + end + + describe "create_task/1" do + test "creation with valid data creates a task" do + valid_attrs = %{job_id: job_fixture().id} + + assert {:ok, %Task{} = _task} = Tasks.create_task(valid_attrs) + end + + test "creation with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Tasks.create_task(@invalid_attrs) + end + end + + describe "delete_task/1" do + test "deletion deletes the task" do + task = task_fixture() + assert {:ok, %Task{}} = Tasks.delete_task(task) + assert_raise Ecto.NoResultsError, fn -> Tasks.get_task!(task.id) end + end + end + + describe "change_task/1" do + test "it returns a task changeset" do + task = task_fixture() + assert %Ecto.Changeset{} = Tasks.change_task(task) + end + end +end diff --git a/test/support/fixtures/job_fixtures.ex b/test/support/fixtures/job_fixtures.ex new file mode 100644 index 0000000..4aab0dd --- /dev/null +++ b/test/support/fixtures/job_fixtures.ex @@ -0,0 +1,19 @@ +defmodule Pinchflat.JobFixtures do + @moduledoc false + + defmodule TestJobWorker do + @moduledoc false + use Oban.Worker, queue: :default + + @impl Oban.Worker + def perform(%Oban.Job{}) do + :ok + end + end + + def job_fixture() do + {:ok, job} = Oban.insert(TestJobWorker.new(%{})) + + job + end +end diff --git a/test/support/fixtures/tasks_fixtures.ex b/test/support/fixtures/tasks_fixtures.ex new file mode 100644 index 0000000..c310ea6 --- /dev/null +++ b/test/support/fixtures/tasks_fixtures.ex @@ -0,0 +1,24 @@ +defmodule Pinchflat.TasksFixtures do + @moduledoc """ + This module defines test helpers for creating + entities via the `Pinchflat.Tasks` context. + """ + + alias Pinchflat.JobFixtures + alias Pinchflat.MediaSourceFixtures + + @doc """ + Generate a task. + """ + def task_fixture(attrs \\ %{}) do + {:ok, task} = + attrs + |> Enum.into(%{ + channel_id: MediaSourceFixtures.channel_fixture().id, + job_id: JobFixtures.job_fixture().id + }) + |> Pinchflat.Tasks.create_task() + + task + end +end