Skip to content

Commit 2c94e6a

Browse files
committed
api: fix INIT state stuck
Sometimes, instance could enter the queue initialization while still in the orphan mode. This resulted in "lazy start". But Tarantool does not call `box.cfg {}` after leaving orphan mode, so queue was stuck in the `INIT` state. Now we wait in the background for all orphan instances. It is similar to lazy init for read-only instances. Note that this fix works only for Tarantool versions >= 2.10.0. This is because of using watchers. Closes #226
1 parent 5f2b145 commit 2c94e6a

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Fixed
11+
12+
- Stuck in `INIT` state if instance failed to leave `orphan` mode in time (#226).
13+
This fix works only for Tarantool versions >= 2.10.0.
14+
815
## [1.3.3] - 2023-09-13
916

1017
### Fixed

queue/init.lua

+29-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
local fiber = require('fiber')
2+
13
local abstract = require('queue.abstract')
24
local queue_state = require('queue.abstract.queue_state')
5+
local qc = require('queue.compat')
36
local queue = nil
47

58
-- load all core drivers
@@ -11,6 +14,10 @@ local core_drivers = {
1114
limfifottl = require('queue.abstract.driver.limfifottl')
1215
}
1316

17+
-- since:
18+
-- https://github.com/locker/tarantool/commit/8cf5151cb4f05cee3fd0ea831add2b3187a01fe4
19+
local watchers_supported = qc.check_version({2, 10, 0})
20+
1421
local function register_driver(driver_name, tube_ctr)
1522
if type(tube_ctr.create_space) ~= 'function' or
1623
type(tube_ctr.new) ~= 'function' then
@@ -62,6 +69,19 @@ local orig_call = nil
6269

6370
local wrapper_impl
6471

72+
local function orphan_waiter()
73+
local wait_cond = fiber.cond()
74+
local w = box.watch('box.status', function(_, new_status)
75+
fiber.yield()
76+
if new_status.status ~= 'orphan' then
77+
wait_cond:signal()
78+
end
79+
end)
80+
wait_cond:wait()
81+
w:unregister()
82+
return wrapper_impl()
83+
end
84+
6585
local function cfg_wrapper(...)
6686
box.cfg = orig_cfg
6787
return wrapper_impl(...)
@@ -79,10 +99,15 @@ local function wrap_box_cfg()
7999
orig_cfg = box.cfg
80100
box.cfg = cfg_wrapper
81101
elseif type(box.cfg) == 'table' then
82-
-- box.cfg after the first box.cfg call
83-
local cfg_mt = getmetatable(box.cfg)
84-
orig_call = cfg_mt.__call
85-
cfg_mt.__call = cfg_call_wrapper
102+
if watchers_supported and box.info.ro_reason == 'orphan' then
103+
-- Wait for the orphan instance.
104+
fiber.new(orphan_waiter)
105+
else
106+
-- box.cfg after the first box.cfg call
107+
local cfg_mt = getmetatable(box.cfg)
108+
orig_call = cfg_mt.__call
109+
cfg_mt.__call = cfg_call_wrapper
110+
end
86111
else
87112
error('The box.cfg type is unexpected: ' .. type(box.cfg))
88113
end

0 commit comments

Comments
 (0)