Hmm, that’s a good point…
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!