From f278d3f0f38f4b62d23561dced36fefb97146309 Mon Sep 17 00:00:00 2001
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Date: Fri, 30 Mar 2018 14:33:01 +0300
Subject: [PATCH] netbox: fix a bug with ignored reconnect_after

If a remote host is unreachable on the first connection attempt,
and reconnect_after is set, then netbox state machine enters
error state, but it must enter error_reconnect. Do it.

The bug was introduced by me in
d2468dacaf6119574d705c08df6e23892b52db08.
---
 src/box/lua/net_box.lua   | 14 ++++++++++++--
 test/box/net.box.result   | 13 +++++++++++++
 test/box/net.box.test.lua |  9 +++++++++
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index f0ea38d399..8df70e578e 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -219,15 +219,24 @@ local function create_transport(host, port, user, password, callback,
 
     local function start()
         if state ~= 'initial' then return not is_final_state[state] end
-        if not connection then
+        if not connection and not callback('reconnect_timeout') then
             set_state('error', E_NO_CONNECTION)
             return
         end
         fiber.create(function()
+            local ok, err
             worker_fiber = fiber_self()
             fiber.name(string.format('%s:%s (net.box)', host, port), {truncate=true})
+            -- It is possible, if the first connection attempt had
+            -- been failed, but reconnect timeout is set. In such
+            -- a case the worker must be run, and immediately
+            -- start reconnecting.
+            if not connection then
+                set_state('error_reconnect', E_NO_CONNECTION, greeting)
+                goto do_reconnect
+            end
     ::handle_connection::
-            local ok, err = pcall(protocol_sm)
+            ok, err = pcall(protocol_sm)
             if not (ok or is_final_state[state]) then
                 set_state('error', E_UNKNOWN, err)
             end
@@ -235,6 +244,7 @@ local function create_transport(host, port, user, password, callback,
                 connection:close()
                 connection = nil
             end
+    ::do_reconnect::
             local timeout = callback('reconnect_timeout')
             while timeout and state == 'error_reconnect' do
                 fiber.sleep(timeout)
diff --git a/test/box/net.box.result b/test/box/net.box.result
index 78178ab9ef..cf7b27f0bb 100644
--- a/test/box/net.box.result
+++ b/test/box/net.box.result
@@ -2383,6 +2383,19 @@ s:drop()
 c:close()
 ---
 ...
+--
+-- Test a case, when netbox can not connect first time, but
+-- reconnect_after is set.
+--
+c = net.connect('localhost:33333', {reconnect_after = 0.1, wait_connected = false})
+---
+...
+while c.state ~= 'error_reconnect' do fiber.sleep(0.01) end
+---
+...
+c:close()
+---
+...
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 ---
 ...
diff --git a/test/box/net.box.test.lua b/test/box/net.box.test.lua
index 47948ac958..576b5cfeab 100644
--- a/test/box/net.box.test.lua
+++ b/test/box/net.box.test.lua
@@ -972,6 +972,15 @@ c:ping()
 
 s:drop()
 c:close()
+
+--
+-- Test a case, when netbox can not connect first time, but
+-- reconnect_after is set.
+--
+c = net.connect('localhost:33333', {reconnect_after = 0.1, wait_connected = false})
+while c.state ~= 'error_reconnect' do fiber.sleep(0.01) end
+c:close()
+
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 c.state
 c = nil
-- 
GitLab