Skip to content

Commit

Permalink
api: fix INIT state stuck
Browse files Browse the repository at this point in the history
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.

Closes #226
  • Loading branch information
DerekBum committed Apr 9, 2024
1 parent 5f2b145 commit a930362
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

- Stuck in `INIT` state if instance failed to leave `orphan` mode in time (#226).

## [1.3.3] - 2023-09-13

### Fixed
Expand Down
28 changes: 24 additions & 4 deletions queue/init.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
local fiber = require('fiber')

local abstract = require('queue.abstract')
local queue_state = require('queue.abstract.queue_state')
local queue = nil
Expand Down Expand Up @@ -62,6 +64,19 @@ local orig_call = nil

local wrapper_impl

local function orphan_waiter()
local wait_cond = fiber.cond()
local w = box.watch('box.status', function(_, new_status)
fiber.yield()
if new_status.status ~= 'orphan' then
wait_cond:signal()
end
end)
wait_cond:wait()
w:unregister()
return wrapper_impl()
end

local function cfg_wrapper(...)
box.cfg = orig_cfg
return wrapper_impl(...)
Expand All @@ -79,10 +94,15 @@ local function wrap_box_cfg()
orig_cfg = box.cfg
box.cfg = cfg_wrapper
elseif type(box.cfg) == 'table' then
-- box.cfg after the first box.cfg call
local cfg_mt = getmetatable(box.cfg)
orig_call = cfg_mt.__call
cfg_mt.__call = cfg_call_wrapper
if box.info.ro_reason == 'orphan' then
-- Wait for the orphan instance.
fiber.new(orphan_waiter)
else
-- box.cfg after the first box.cfg call
local cfg_mt = getmetatable(box.cfg)
orig_call = cfg_mt.__call
cfg_mt.__call = cfg_call_wrapper
end
else
error('The box.cfg type is unexpected: ' .. type(box.cfg))
end
Expand Down

0 comments on commit a930362

Please sign in to comment.