From afff49680c84dabdd9a5713238da70854f518beb Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Apr 2020 16:11:34 -0500 Subject: [PATCH] adds lock for upsert and update_if --- lib/cluster_kv/db.ex | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/cluster_kv/db.ex b/lib/cluster_kv/db.ex index ad7d972..a73c156 100644 --- a/lib/cluster_kv/db.ex +++ b/lib/cluster_kv/db.ex @@ -158,6 +158,8 @@ defmodule ClusterKV.DB do @spec do_upsert(db :: module(), key :: String.t(), value :: any(), fun :: fun()) :: true defp do_upsert(db, key, value, fun) do + get_lock(db, key) + case :ets.lookup(db, key) do [] -> v = @@ -175,11 +177,15 @@ defmodule ClusterKV.DB do [_] -> :ets.insert(db, {key, [value]}) end + + release_lock(db, key) end @spec do_update_if(db :: module(), key :: String.t(), value :: any(), fun :: fun()) :: :updated | :noop defp do_update_if(db, key, value, fun) do + get_lock(db, key) + case :ets.lookup(db, key) do [] -> v = @@ -189,20 +195,24 @@ defmodule ClusterKV.DB do end :ets.insert(db, {key, v}) + release_lock(db, key) :updated [{_, val} = old] when is_list(val) -> case fun.(old, value) do {:update, new} -> :ets.insert(db, new) + release_lock(db, key) :updated _ -> + release_lock(db, key) :noop end [_] -> :ets.insert(db, {key, [value]}) + release_lock(db, key) :updated end end @@ -234,4 +244,20 @@ defmodule ClusterKV.DB do do_get(db, key) end) end + + defp release_lock(db, key) do + :ets.delete(db, "#{key}:lock") + end + + defp get_lock(db, key) do + key = "#{key}:lock" + do_get_lock(db, key) + end + + defp do_get_lock(db, key) do + case :ets.insert_new(db, {key, true}) do + false -> do_get_lock(db, key) + true -> true + end + end end -- 2.45.3