]> Entropealabs - cluster_kv.git/commitdiff
adds lock for upsert and update_if
authorChristopher <chris@entropealabs.com>
Thu, 2 Apr 2020 21:11:34 +0000 (16:11 -0500)
committerChristopher <chris@entropealabs.com>
Thu, 2 Apr 2020 21:11:34 +0000 (16:11 -0500)
lib/cluster_kv/db.ex

index ad7d9727ab7714bc20ba3b78cd69f9e12df9a778..a73c1561f086dbc9e3bc90dabccae96222281c2d 100644 (file)
@@ -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