Ecto helpers to find_or_create(_by) and upsert(_by)

Hmm, that’s a good point… :thinking:

This will more likely than not cause potential race conditions for the find_or_create(_by) since it’d pass a struct to an insert which could then lead to duplicates. Any ideas on how to handle this?

Regarding the upsert(_by), that took inspiration from the example given for Ecto.Repo#insert_or_update/2 by passing a changeset to the insert_or_update. Looking at it again, I’m curious whether the insert_or_update knows how to gracefully handle race conditions since it similarly breaks apart the find and upsert into discrete steps. @michalmuskala, any insight here?

result =
  case MyRepo.get(Post, id) do
    nil  -> %Post{id: id} # Post not found, we build one
    post -> post          # Post exists, let's use it
  end
  |> Post.changeset(changes)
  |> MyRepo.insert_or_update

case result do
  {:ok, struct}       -> # Inserted or updated with success
  {:error, changeset} -> # Something went wrong
end

source: Ecto docs

Thanks @pragdave for bringing this up!

1 Like