Hello,
I’ve been trying to implement Ecto.Changeset.optimistic_lock in a Phoenix application but I’m stuck with the generated controller’s update action.
In iex I have success rising an Ecto.StaleEntryError when I try to update a stale record, (as shown in the documentation):
iex> post = Repo.insert!(%Post{title: "foo"})
%Post{id: 1, title: "foo", lock_version: 1}
iex> valid_change = Post.changeset(:update, post, %{title: "bar"})
iex> stale_change = Post.changeset(:update, post, %{title: "baz"})
iex> Repo.update!(valid_change)
%Post{id: 1, title: "bar", lock_version: 2}
iex> Repo.update!(stale_change)
** (Ecto.StaleEntryError) attempted to update a stale entry
here the two changeset are being generated from the same post struct, and Repo.update raise the expected error.
On the other hand, when the update is performed concurrently in two browser windows, -my understanding is that- the controller’s update action performs a new get_post!(id) and then uses that struct to make the update’s changeset, with the form params; therefore the latest update is always overwriting the first occurring, thus making optimistic_lock useless in this context.
I couldn’t find much help on this issue, and it make me think I’m getting all this wrong… Thank’s for any help.
That’s an interesting question. Disclaimer: I’ve never used optimistic_lock.
Since lock_version is just a regular field, one idea would be to pass, alongside with the ID, the version of the object in the update method and using that version before you apply any changes.
Since lock_version is just a regular field, one idea would be to pass, alongside with the ID, the version of the object in the update method and using that version before you apply any changes […]
post =
id
|> Posts.get_post!()
|> Map.put(:lock_version, lock_version)
Oh , right, that easy
Replacing the validly-updated new :lock_version with the stale one afterget_post!(id)… I’m going to try this now, sure it is going to work!
I’ve been stubbornly poking around with attempts to pass the post struct assigned in edit, from the form to the update action, with no success, and I couldn’t think simple again. Thank you for your help!
Hello @patrickdm! I was wondering if you could share your approach to managing the Ecto.StaleEntryError exception within a controller or a live view?
I came across a similar issue discussed in another thread during my research, but unfortunately, it didn’t have any responses. Your insights would be greatly appreciated.