*ttl drivers: a dead TTL fiber cannot be restarted and wedges the queue in ENDING on the next RO switch
还没有人认领这个 Issue。
评估
调研方向
Start with queue/abstract/driver/fifottl.lua lines 164-167 and 415-427, then compare the buffered-channel behavior in utubettl. Run the reproduction in the issue and inspect queue_state handling during RO/RW switches. Done means a failed TTL iteration does not permanently disable processing or leave the queue stuck in ENDING, and start/stop remain safe.
由索引模型根据 Issue 内容生成。
描述
Environment: queue master (07fd732), Tarantool 3.8.0 (also the same code in 1.5.0). memtx.
Related: #238 asks for an API to restart the TTL fiber. This issue is about what happens today when the fiber dies: it cannot be restarted, and for fifottl/limfifottl the queue state machine gets stuck in ENDING on the next RO switch, so the queue never comes back without an instance restart.
Summary
Any error inside a TTL iteration (a user on_task_change callback raising, an MVCC conflict, a vinyl read error, the nil dereference from the TTL branch, ...) makes the fiber return 1 (fifottl.lua#L164-L167) while self.fiber keeps pointing at the dead fiber. Consequences:
method.start()is a no-op becauseself.fiberis not nil (fifottl.lua#L415-L420). TTL/TTR/delay processing for the tube is dead.- On the next RO switch the state machine calls
stop(), which doesself.sync_chan:put(true)(fifottl.lua#L427). The channel is unbuffered and the only reader is dead (same root cause as #262), so thequeue_statefiber blocks forever. The queue stays inENDING, andput/takekeep failing withqueue is in ENDING stateeven after the instance is RW again.
For utubettl (buffered fiber.channel(1)) point 2 does not hang, but point 1 still holds until an RO->RW cycle.
Repro
local fiber = require('fiber')
box.cfg{}
local queue = require('queue')
local fired = false
local tube = queue.create_tube('t', 'fifottl', {
on_task_change = function(task, stat)
if stat == 'ttl' and not fired then
fired = true
error('user callback failed once')
end
end,
})
tube:put('a', {ttl = 0.1})
fiber.sleep(0.3)
print('1. fiber after one callback error:', tube.raw.fiber:status())
local b = tube:put('b', {ttl = 0.1})
fiber.sleep(0.3)
print('2. expired task still in space:', tube.raw.space:get(b[1]) ~= nil)
tube.raw:start()
print('3. fiber after start():', tube.raw.fiber:status())
box.cfg{read_only = true}
fiber.sleep(1)
print('4. queue.state() after RO switch:', queue.state())
box.cfg{read_only = false}
fiber.sleep(1)
print('5. queue.state() after RW switch:', queue.state())
print('6. put() after RW switch:', pcall(tube.put, tube, 'c', {ttl = 0.1}))
Output on master:
1. fiber after one callback error: dead
2. expired task still in space: true
3. fiber after start(): dead
4. queue.state() after RO switch: ENDING
5. queue.state() after RW switch: ENDING
6. put() after RW switch: true nil -- put() returns nil, log: "put: queue is in ENDING state"
Expected
A failed iteration should not permanently kill TTL processing: either the fiber survives the error (log it and continue / restart with backoff), or at least self.fiber is cleared on exit so start() can create a new one, and stop() must never block on a channel nobody reads.
Suggested fix
- Clear
self.fiberin a guaranteed cleanup path when the fiber exits (checking it still points to the current fiber). - Make
stop()tolerant of a dead fiber (checkself.fiber:status()or use a buffered channel /fiber:cancel()). - Optionally restart the fiber after an error with a backoff instead of
return 1; user callback errors could be pcall-ed inabstract.luaso a user bug cannot take the driver down.
- 主要语言
- Lua
- 星标
- 244
- 派生
- 56
- 平均合并
- 6 天 8 小时
- 30 天内合并 PR
- 1
贡献指南
这个仓库没有索引到贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
tarantool/queue 的其他 Issue
-
documentation good first issue
难度 1/5 1 小时以内 新手友好度 85/100
-
难度 3/5 1-2 天 新手友好度 76/100
-
难度 4/5 3-5 天 新手友好度 55/100
-
1sp bug teamE
难度 4/5 3-5 天 新手友好度 25/100
-
bug
难度 4/5 3-5 天 新手友好度 35/100
相似的 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 68/100
LandSandBoat/server#11579 ·
-
难度 2/5 1-3 小时 新手友好度 76/100
ArchiveTeam/sinavideo-grab#7 · 3 个 reaction ·
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
mailcow/mailcow-dockerized#7480 ·
-
mapper bug
难度 2/5 1-3 小时 新手友好度 88/100
-
documentation feature-request mini.completion
难度 1/5 1 小时以内 新手友好度 88/100