diff --git a/lib/frenzy/item.ex b/lib/frenzy/item.ex index 4a9f381..29edf21 100644 --- a/lib/frenzy/item.ex +++ b/lib/frenzy/item.ex @@ -82,9 +82,20 @@ defmodule Frenzy.Item do @doc false def changeset(item, attrs) do item - |> cast(attrs, [:guid, :title, :url, :creator, :date, :content, :read, :read_date, :tombstone]) - |> validate_required([:guid, :url, :date, :content, :feed]) - |> unique_constraint(:items_feed_guid_index) + |> cast(attrs, [ + :guid, + :title, + :url, + :creator, + :date, + :content, + :read, + :read_date, + :tombstone, + :feed_id + ]) + |> validate_required([:guid, :url, :date, :content, :feed_id]) + |> unique_constraint([:feed_id, :guid], name: :items_feed_guid_index) end def exists?(feed_id, guid) do diff --git a/lib/frenzy/task/create_item.ex b/lib/frenzy/task/create_item.ex index 6d9b1bc..017fae1 100644 --- a/lib/frenzy/task/create_item.ex +++ b/lib/frenzy/task/create_item.ex @@ -1,7 +1,7 @@ defmodule Frenzy.Task.CreateItem do require Logger use Task - alias Frenzy.Repo + alias Frenzy.{Repo, Item} @spec start_link(Frenzy.Feed.t(), FeedParser.Item.t()) :: {:ok, pid()} def start_link(feed, entry) do @@ -29,7 +29,8 @@ defmodule Frenzy.Task.CreateItem do end item_params = %{ - guid: entry.guid, + # fallback to url if guid isn't present + guid: entry.guid || url, title: entry.title, url: url, date: date, @@ -61,36 +62,41 @@ defmodule Frenzy.Task.CreateItem do {:ok, item_params} end - case result do - {:error, error} -> - Logger.error(error) + changeset = + case result do + {:error, error} -> + Logger.error(error) + :error - {:ok, item_params} -> - changeset = Ecto.build_assoc(feed, :items, item_params) + {:ok, item_params} -> + item_params = Map.put(item_params, :feed_id, feed.id) + Item.changeset(%Item{}, item_params) - case Repo.insert(changeset) do - {:ok, item} -> - item - - {:error, changeset} -> - Logger.error("Error inserting item #{entry.guid}") - Logger.error(changeset) - end - - :tombstone -> - changeset = - Ecto.build_assoc(feed, :items, %{ + :tombstone -> + Item.changeset(%Item{}, %{ guid: item_params.guid, tombstone: true }) + end + case changeset do + nil -> + nil + + changeset -> case Repo.insert(changeset) do {:ok, item} -> item {:error, changeset} -> - Logger.error("Error inserting tombstone for #{entry.guid}") - Logger.error(changeset) + with [feed_id: {_, list}] <- changeset.errors, + true <- {:constraint_name, "items_feed_guid_index"} in list do + Logger.warn("Did not insert duplicate item for #{item_params.guid}") + else + _ -> + Logger.error("Error inserting item #{item_params.guid}") + Logger.error(changeset.errors) + end end end