[Tarantool-patches] [PATCH vshard 3/5] storage: manual enable/disable

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Fri Dec 17 03:25:29 MSK 2021


The patch introduces functions vshard.storage.enable()/disable().

They allow to control manually whether the instance can accept
requests.

It solves the following problems which were not covered by
previous patches:

- Even if box.cfg() is done, status is 'running', and
  vshard.storage.cfg() is finished, still user's application can
  be not ready to accept requests. For instance, it needs to
  create more functions and users on top of vshard. Then it wants
  to disable public requests until all preliminary work is done.

- After all is enabled, fine, and dandy, still the instance might
  want to disable self in case of an emergency. Such as its config
  got broken or too outdated, desynced with a centric storage.

vshard.storage.enable()/disable() can be called any time, before,
during, and after vshard.storage.cfg() to solve these issues.

Part of #298
---
 test/storage/storage.result   | 27 +++++++++++++++++++++++++++
 test/storage/storage.test.lua | 12 ++++++++++++
 vshard/storage/init.lua       | 28 ++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+)

diff --git a/test/storage/storage.result b/test/storage/storage.result
index e83b34f..e1b0d5d 100644
--- a/test/storage/storage.result
+++ b/test/storage/storage.result
@@ -1052,6 +1052,33 @@ assert(ok and res == 100)
 ---
 - true
 ...
+--
+-- Manual enable/disable.
+--
+vshard.storage.disable()
+---
+...
+ok, err = pcall(vshard.storage.call, 1, 'read', 'echo', {100})
+---
+...
+assert(not ok and err.code == vshard.error.code.STORAGE_IS_DISABLED)
+---
+- true
+...
+assert(err.message:match('storage is disabled explicitly') ~= nil)
+---
+- true
+...
+vshard.storage.enable()
+---
+...
+ok, res = vshard.storage.call(1, 'read', 'echo', {100})
+---
+...
+assert(ok and res == 100)
+---
+- true
+...
 _ = test_run:switch("default")
 ---
 ...
diff --git a/test/storage/storage.test.lua b/test/storage/storage.test.lua
index ff39f2f..e1127d3 100644
--- a/test/storage/storage.test.lua
+++ b/test/storage/storage.test.lua
@@ -342,6 +342,18 @@ f:join()
 ok, res = vshard.storage.call(1, 'read', 'echo', {100})
 assert(ok and res == 100)
 
+--
+-- Manual enable/disable.
+--
+vshard.storage.disable()
+ok, err = pcall(vshard.storage.call, 1, 'read', 'echo', {100})
+assert(not ok and err.code == vshard.error.code.STORAGE_IS_DISABLED)
+assert(err.message:match('storage is disabled explicitly') ~= nil)
+
+vshard.storage.enable()
+ok, res = vshard.storage.call(1, 'read', 'echo', {100})
+assert(ok and res == 100)
+
 _ = test_run:switch("default")
 test_run:drop_cluster(REPLICASET_2)
 test_run:drop_cluster(REPLICASET_1)
diff --git a/vshard/storage/init.lua b/vshard/storage/init.lua
index d3c4e2a..94e0c16 100644
--- a/vshard/storage/init.lua
+++ b/vshard/storage/init.lua
@@ -139,6 +139,9 @@ if not M then
         -- Flag whether box.info.status is acceptable. For instance, 'loading'
         -- is not.
         is_loaded = false,
+        -- Flag whether the instance is enabled manually. It is true by default
+        -- for backward compatibility with old vshard.
+        is_enabled = true,
         -- Reference to the function-proxy to most of the public functions. It
         -- allows to avoid 'if's in each function by adding expensive
         -- conditional checks in one rarely used version of the wrapper and no
@@ -201,6 +204,11 @@ if not M then
     }
 else
     bucket_ref_new = ffi.typeof("struct bucket_ref")
+
+    -- It is not set when reloaded from an old vshard version.
+    if M.is_enabled == nil then
+        M.is_enabled = true
+    end
 end
 
 --
@@ -2973,6 +2981,10 @@ local function storage_api_call_unsafe(func, arg1, arg2, arg3, arg4)
         local msg = 'storage is not configured'
         return error(lerror.vshard(lerror.code.STORAGE_IS_DISABLED, msg))
     end
+    if not M.is_enabled then
+        local msg = 'storage is disabled explicitly'
+        return error(lerror.vshard(lerror.code.STORAGE_IS_DISABLED, msg))
+    end
     M.api_call_cache = storage_api_call_safe
     return func(arg1, arg2, arg3, arg4)
 end
@@ -2985,6 +2997,20 @@ local function storage_make_api(func)
     end
 end
 
+local function storage_enable()
+    M.is_enabled = true
+end
+
+--
+-- Disable can be used in case the storage entered a critical state in which
+-- requests are not allowed. For instance, its config got broken or too old
+-- compared to a centric config somewhere.
+--
+local function storage_disable()
+    M.is_enabled = false
+    M.api_call_cache = storage_api_call_unsafe
+end
+
 --------------------------------------------------------------------------------
 -- Module definition
 --------------------------------------------------------------------------------
@@ -3153,5 +3179,7 @@ return {
     cfg = function(cfg, uuid) return storage_cfg(cfg, uuid, false) end,
     on_master_enable = storage_make_api(on_master_enable),
     on_master_disable = storage_make_api(on_master_disable),
+    enable = storage_enable,
+    disable = storage_disable,
     internal = M,
 }
-- 
2.24.3 (Apple Git-128)



More information about the Tarantool-patches mailing list