From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: tarantool-patches@dev.tarantool.org Subject: [Tarantool-patches] [PATCH 1/1] netbox: don't fire on_connect() at schema update Date: Tue, 29 Oct 2019 22:43:30 +0100 [thread overview] Message-ID: <0706877cdc0598bb77489636dd22e852b7a50682.1572385348.git.v.shpilevoy@tarantool.org> (raw) There was a bug that netbox at any schema update called on_connect() triggers. This was due to overcomplicated logic of handling of changes in the netbox state machine. On_connect() was fired each time the machine entered 'active' state, even if its previous states were 'active' and then 'fetch_schema'. The latter state can be entered many times without reconnects. Another bug was about on_disconnect() - it could be fired even if the connection never entered active state. For example, if its first 'fetch_schema' has failed. Now there is an explicit flag showing the machine connect state. The triggers are fired only when it is changed, on 'active' and on any error states. Intermediate states (fetch_schema, auth) do not matter anymore. Thanks @mtrempoltsev for the initial investigation and a draft fix. Closes #4593 --- Branch: https://github.com/tarantool/tarantool/tree/gerold103/gh-4593-netbox-on_connect Issue: https://github.com/tarantool/tarantool/issues/4593 src/box/lua/net_box.lua | 20 +++++--- test/box/net.box.result | 100 ++++++++++++++++++++++++++++++++++++++ test/box/net.box.test.lua | 50 +++++++++++++++++++ 3 files changed, 162 insertions(+), 8 deletions(-) diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua index 31a8c16b7..696b30fd9 100644 --- a/src/box/lua/net_box.lua +++ b/src/box/lua/net_box.lua @@ -927,14 +927,17 @@ local function new_sm(host, port, opts, connection, greeting) local function callback(what, ...) if what == 'state_changed' then local state, errno, err = ... - if (remote.state == 'active' or remote.state == 'fetch_schema') and - (state == 'error' or state == 'closed' or - state == 'error_reconnect') then - remote._on_disconnect:run(remote) - end - if remote.state ~= 'error' and remote.state ~= 'error_reconnect' and - state == 'active' then - remote._on_connect:run(remote) + local was_connected = remote._is_connected + if state == 'active' then + if not was_connected then + remote._is_connected = true + remote._on_connect:run(remote) + end + elseif errno ~= nil then + if was_connected then + remote._is_connected = false + remote._on_disconnect:run(remote) + end end remote.state, remote.error = state, err if state == 'error_reconnect' then @@ -989,6 +992,7 @@ local function new_sm(host, port, opts, connection, greeting) remote._on_schema_reload = trigger.new("on_schema_reload") remote._on_disconnect = trigger.new("on_disconnect") remote._on_connect = trigger.new("on_connect") + remote._is_connected = false remote._transport = create_transport(host, port, user, password, callback, connection, greeting) remote._transport.start() diff --git a/test/box/net.box.result b/test/box/net.box.result index e3dabf7d9..010bb2b1c 100644 --- a/test/box/net.box.result +++ b/test/box/net.box.result @@ -3930,3 +3930,103 @@ test_run:grep_log('default', '00000040:.*') box.cfg{log_level=log_level} --- ... +-- +-- gh-4593: net.box on_connect() and on_disconnect() were called +-- not in time. +-- +-- +-- on_disconnect() trigger should not be called if a connection +-- was refused even before it managed to become active. +-- +disconnected_count = 0 +--- +... +connected_count = 0 +--- +... +box.schema.user.disable('guest') +--- +... +function on_connect() \ + connected_count = connected_count + 1 \ +end +--- +... +function on_disconnect() \ + disconnected_count = disconnected_count + 1 \ +end +--- +... +c = remote.connect(box.cfg.listen, {wait_connected = false}) \ +c:on_disconnect(on_disconnect) \ +c:on_connect(on_connect) +--- +... +c:wait_connected() +--- +- false +... +connected_count +--- +- 0 +... +disconnected_count +--- +- 0 +... +c:close() +--- +... +connected_count +--- +- 0 +... +disconnected_count +--- +- 0 +... +box.schema.user.enable('guest') +--- +... +-- +-- on_connect() should not be called on schema update. +-- +box.schema.user.grant('guest', 'read,write,execute,create', 'universe') +--- +... +c = remote.connect(box.cfg.listen, {wait_connected = false}) \ +c:on_disconnect(on_disconnect) \ +c:on_connect(on_connect) +--- +... +function create_space() box.schema.create_space('test') end +--- +... +c:call('create_space') +--- +... +connected_count +--- +- 1 +... +disconnected_count +--- +- 0 +... +c:close() +--- +... +connected_count +--- +- 1 +... +disconnected_count +--- +- 1 +... +box.space.test:drop() +--- +... +box.schema.user.revoke('guest', 'read,write,execute,create', 'universe') +--- +... diff --git a/test/box/net.box.test.lua b/test/box/net.box.test.lua index 8e65ff470..36a7bcb70 100644 --- a/test/box/net.box.test.lua +++ b/test/box/net.box.test.lua @@ -1583,3 +1583,53 @@ test_run:wait_log('default', '00000030:.*', nil, 10) test_run:grep_log('default', '00000040:.*') box.cfg{log_level=log_level} + +-- +-- gh-4593: net.box on_connect() and on_disconnect() were called +-- not in time. +-- +-- +-- on_disconnect() trigger should not be called if a connection +-- was refused even before it managed to become active. +-- +disconnected_count = 0 +connected_count = 0 +box.schema.user.disable('guest') + +function on_connect() \ + connected_count = connected_count + 1 \ +end +function on_disconnect() \ + disconnected_count = disconnected_count + 1 \ +end + +c = remote.connect(box.cfg.listen, {wait_connected = false}) \ +c:on_disconnect(on_disconnect) \ +c:on_connect(on_connect) +c:wait_connected() + +connected_count +disconnected_count +c:close() +connected_count +disconnected_count +box.schema.user.enable('guest') + +-- +-- on_connect() should not be called on schema update. +-- +box.schema.user.grant('guest', 'read,write,execute,create', 'universe') +c = remote.connect(box.cfg.listen, {wait_connected = false}) \ +c:on_disconnect(on_disconnect) \ +c:on_connect(on_connect) +function create_space() box.schema.create_space('test') end +c:call('create_space') +connected_count +disconnected_count + +c:close() +connected_count +disconnected_count + +box.space.test:drop() +box.schema.user.revoke('guest', 'read,write,execute,create', 'universe') -- 2.21.0 (Apple Git-122)
next reply other threads:[~2019-10-29 21:38 UTC|newest] Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-10-29 21:43 Vladislav Shpilevoy [this message] 2019-10-29 22:03 ` Cyrill Gorcunov 2019-10-29 23:51 ` Vladislav Shpilevoy 2019-11-05 13:12 ` Alexander Turenko 2019-11-05 14:12 ` Vladislav Shpilevoy 2019-11-05 15:00 ` Alexander Turenko 2019-11-05 16:34 ` Kirill Yukhin 2019-11-06 0:56 ` Alexander Turenko 2019-11-06 13:44 ` Kirill Yukhin
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=0706877cdc0598bb77489636dd22e852b7a50682.1572385348.git.v.shpilevoy@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=tarantool-patches@dev.tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH 1/1] netbox: don'\''t fire on_connect() at schema update' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox