From 7f5d82c752218b14676e089af85c3478b9e3d823 Mon Sep 17 00:00:00 2001 From: DerekBum Date: Thu, 4 Apr 2024 16:41:40 +0300 Subject: [PATCH] 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 for all orphan instances on the init stage of the queue. Closes #226 --- CHANGELOG.md | 6 ++++++ queue/init.lua | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae8bf024..a2d7a4ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/queue/init.lua b/queue/init.lua index 40b9268c..e960940f 100644 --- a/queue/init.lua +++ b/queue/init.lua @@ -73,7 +73,26 @@ local function cfg_call_wrapper(cfg, ...) return wrapper_impl(...) end +local function orphan_waiter() + local fiber = require('fiber') + local wait_for_orphan = fiber.new(function() + while true do + if box.info.status ~= 'orphan' then + break + end + fiber.sleep(0.1) + end + end) + wait_for_orphan:set_joinable(true) + wait_for_orphan:join() +end + local function wrap_box_cfg() + if box.info.ro_reason == 'orphan' then + -- Wait for the orphan instance. + orphan_waiter() + end + if type(box.cfg) == 'function' then -- box.cfg before the first box.cfg call orig_cfg = box.cfg @@ -121,6 +140,10 @@ end -- configured with read_only = false. Otherwise, a start is -- delayed until the instance will be configured with read_only = false. local function queue_init() + if rawget(box, 'space') ~= nil and box.info.ro_reason == 'orphan' then + -- Wait for the orphan instance. + orphan_waiter() + end if rawget(box, 'space') ~= nil and box.info.ro == false then -- The box was configured with read_only = false queue = require('queue.abstract')