update
This commit is contained in:
59
phoenix/deps/ecto_sql/integration_test/sql/lock.exs
Normal file
59
phoenix/deps/ecto_sql/integration_test/sql/lock.exs
Normal file
@@ -0,0 +1,59 @@
|
||||
defmodule Ecto.Integration.LockTest do
|
||||
# We can keep this test async as long as it
|
||||
# is the only one accessing the lock_test table.
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
import Ecto.Query
|
||||
alias Ecto.Integration.PoolRepo
|
||||
|
||||
defmodule LockCounter do
|
||||
use Ecto.Schema
|
||||
|
||||
schema "lock_counters" do
|
||||
field :count, :integer
|
||||
end
|
||||
end
|
||||
|
||||
setup do
|
||||
PoolRepo.delete_all(LockCounter)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "lock for update" do
|
||||
%{id: id} = PoolRepo.insert!(%LockCounter{count: 1})
|
||||
pid = self()
|
||||
|
||||
lock_for_update =
|
||||
Application.get_env(:ecto_sql, :lock_for_update) ||
|
||||
raise ":lock_for_update not set in :ecto application"
|
||||
|
||||
# Here we are manually inserting the lock in the query
|
||||
# to test multiple adapters. Never do this in actual
|
||||
# application code: it is not safe and not public.
|
||||
query = from(lc in LockCounter, where: lc.id == ^id)
|
||||
query = %{query | lock: lock_for_update}
|
||||
|
||||
{:ok, new_pid} =
|
||||
Task.start_link fn ->
|
||||
assert_receive :select_for_update, 5000
|
||||
|
||||
PoolRepo.transaction(fn ->
|
||||
[post] = PoolRepo.all(query) # this should block until the other trans. commit
|
||||
post |> Ecto.Changeset.change(count: post.count + 1) |> PoolRepo.update!
|
||||
end)
|
||||
|
||||
send pid, :updated
|
||||
end
|
||||
|
||||
PoolRepo.transaction(fn ->
|
||||
[post] = PoolRepo.all(query) # select and lock the row
|
||||
send new_pid, :select_for_update # signal second process to begin a transaction
|
||||
post |> Ecto.Changeset.change(count: post.count + 1) |> PoolRepo.update!
|
||||
end)
|
||||
|
||||
assert_receive :updated, 5000
|
||||
|
||||
# Final count will be 3 if SELECT ... FOR UPDATE worked and 2 otherwise
|
||||
assert [%LockCounter{count: 3}] = PoolRepo.all(LockCounter)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user