You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Elixir version (elixir -v): Elixir 1.7.4 (compiled with Erlang/OTP 21)
Nebulex version (mix deps): 1.0.0
Operating system: Debian Stretch
Expected behavior
Operations wrapped in a transaction should occur once.
test "check cache set and get in transaction" do
value = ["old value"]
Cache.set(:test, value)
Cache.transaction(
fn ->
old_value = Cache.get(:test)
assert old_value == value
Cache.set(:test, ["new value" | old_value])
end,
keys: [:test]
)
assert Cache.get(:test) == ["new_value", "old_value"]
end
Actual behavior
1) test check cache set and get in transaction (Cache.MultilevelTest)
test/cache/multilevel_test.exs:14
Assertion with == failed
code: assert old_value == value
left: ["new value", "old value"]
right: ["old value"]
stacktrace:
test/cache/multilevel_test.exs:23: anonymous fn/0 in Cache.MultilevelTest."test check cache set and get in transaction"/1
(nebulex_redis_adapter) lib/nebulex_redis_adapter.ex:118: NebulexRedisAdapter.do_transaction/5
(nebulex) lib/nebulex/adapters/multilevel.ex:366: anonymous fn/4 in Nebulex.Adapters.Multilevel.eval/3
(elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
(db) lib/cache.ex:2: Cache.with_hooks/3
test/cache/multilevel_test.exs:19: (test)
More information
## Transaction
@impl true
def transaction(cache, fun, opts) do
eval(cache, :transaction, [fun, opts], [])
end
## Helpers
defp eval(ml_cache, fun, args, opts) do
eval(levels(opts, ml_cache), fun, args)
end
defp eval([l1 | next], fun, args) do
Enum.reduce(next, apply(l1.__adapter__, fun, [l1 | args]), fn cache, acc ->
^acc = apply(cache.__adapter__, fun, [cache | args])
end)
end
The above code seems to try to run the transaction operation for all cache layers, but since each other operation (:get, :set, etc) also goes through this code path, all the changes will have occurred for all layers after running the function inside the transaction once. It looks like the transaction lock should be acquired for all layers, then the wrapped function should run once, then the transaction lock should be released for all layers.
The text was updated successfully, but these errors were encountered:
I've added a fix for this transactions issue, it was like an overall improvement for all built-in adapters (especially for the multilevel one). So please try it out again and let me know if it works for you. I stay tuned for your feedback!
Environment
Elixir version (elixir -v): Elixir 1.7.4 (compiled with Erlang/OTP 21)
Nebulex version (mix deps): 1.0.0
Operating system: Debian Stretch
Expected behavior
Operations wrapped in a transaction should occur once.
Actual behavior
More information
The above code seems to try to run the transaction operation for all cache layers, but since each other operation (:get, :set, etc) also goes through this code path, all the changes will have occurred for all layers after running the function inside the transaction once. It looks like the transaction lock should be acquired for all layers, then the wrapped function should run once, then the transaction lock should be released for all layers.
The text was updated successfully, but these errors were encountered: