Skip to content

Commit 454dcb0

Browse files
committed
fix: improve daemon readiness tracking and terminal robustness
Track daemon readiness with a flag and queue callbacks that arrive before the health-check poll succeeds. Fix stale PID cleanup to only clear the pidfile after the kill signal succeeds. Always run the readiness poll regardless of whether a callback is provided. Validate the terminal jobstart return value before assigning state.
1 parent 0d50cc2 commit 454dcb0

2 files changed

Lines changed: 52 additions & 29 deletions

File tree

lua/rustmail/init.lua

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ local M = {}
22

33
local pid = require("rustmail.pid")
44
local daemon_job = nil
5+
local daemon_ready = false
6+
local pending_callbacks = {}
57
local prev_keymap = nil
68
local augroup = vim.api.nvim_create_augroup("rustmail", { clear = true })
79

@@ -20,7 +22,7 @@ function M.setup(opts)
2022
prev_keymap = cfg.toggle_keymap
2123
vim.keymap.set("n", cfg.toggle_keymap, function()
2224
M.toggle()
23-
end, { desc = "Toggle Rustmail TUI" })
25+
end, { desc = "Toggle RustMail TUI" })
2426
end
2527

2628
vim.api.nvim_create_autocmd("VimLeavePre", {
@@ -57,19 +59,23 @@ end
5759
function M.ensure_daemon(on_ready)
5860
if daemon_job then
5961
if on_ready then
60-
on_ready()
62+
if daemon_ready then
63+
on_ready()
64+
else
65+
table.insert(pending_callbacks, on_ready)
66+
end
6167
end
6268
return
6369
end
6470

6571
local stale_pid = pid.read()
6672
if stale_pid then
6773
if pid.is_rustmail(stale_pid) then
68-
pid.clear()
6974
vim.fn.jobstart({ "kill", tostring(stale_pid) }, {
7075
on_exit = function(_, code)
7176
vim.schedule(function()
7277
if code == 0 then
78+
pid.clear()
7379
M.ensure_daemon(on_ready)
7480
else
7581
vim.notify("[rustmail] failed to kill stale daemon (pid " .. stale_pid .. ")", vim.log.levels.WARN)
@@ -115,6 +121,8 @@ function M.ensure_daemon(on_ready)
115121
detach = true,
116122
on_exit = function()
117123
daemon_job = nil
124+
daemon_ready = false
125+
pending_callbacks = {}
118126
pid.clear()
119127
end,
120128
})
@@ -123,32 +131,38 @@ function M.ensure_daemon(on_ready)
123131
pid.write(vim.fn.jobpid(daemon_job))
124132
vim.notify("[rustmail] started daemon on :" .. cfg.port, vim.log.levels.INFO)
125133
if on_ready then
126-
local attempts = 0
127-
local max_attempts = 20
128-
local function poll()
129-
attempts = attempts + 1
130-
vim.fn.jobstart({
131-
"curl",
132-
"-sf",
133-
"--max-time",
134-
"1",
135-
"http://" .. cfg.host .. ":" .. cfg.port .. "/api/v1/messages?limit=1",
136-
}, {
137-
on_exit = function(_, poll_code)
138-
vim.schedule(function()
139-
if poll_code == 0 then
140-
on_ready()
141-
elseif attempts < max_attempts then
142-
vim.defer_fn(poll, 250)
143-
else
144-
vim.notify("[rustmail] daemon failed to become ready", vim.log.levels.WARN)
134+
table.insert(pending_callbacks, on_ready)
135+
end
136+
local attempts = 0
137+
local max_attempts = 20
138+
local function poll()
139+
attempts = attempts + 1
140+
vim.fn.jobstart({
141+
"curl",
142+
"-sf",
143+
"--max-time",
144+
"1",
145+
"http://" .. cfg.host .. ":" .. cfg.port .. "/api/v1/messages?limit=1",
146+
}, {
147+
on_exit = function(_, poll_code)
148+
vim.schedule(function()
149+
if poll_code == 0 then
150+
daemon_ready = true
151+
local cbs = pending_callbacks
152+
pending_callbacks = {}
153+
for _, cb in ipairs(cbs) do
154+
cb()
145155
end
146-
end)
147-
end,
148-
})
149-
end
150-
vim.defer_fn(poll, 250)
156+
elseif attempts < max_attempts then
157+
vim.defer_fn(poll, 250)
158+
else
159+
vim.notify("[rustmail] daemon failed to become ready", vim.log.levels.WARN)
160+
end
161+
end)
162+
end,
163+
})
151164
end
165+
vim.defer_fn(poll, 250)
152166
else
153167
vim.notify("[rustmail] failed to start daemon", vim.log.levels.ERROR)
154168
end
@@ -165,6 +179,8 @@ function M.stop_daemon()
165179
if daemon_job then
166180
vim.fn.jobstop(daemon_job)
167181
daemon_job = nil
182+
daemon_ready = false
183+
pending_callbacks = {}
168184
pid.clear()
169185
vim.notify("[rustmail] daemon stopped", vim.log.levels.INFO)
170186
return

lua/rustmail/terminal.lua

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ local function start_terminal()
4646
return
4747
end
4848

49-
state.chan = vim.fn.jobstart(build_cmd(), {
49+
local chan = vim.fn.jobstart(build_cmd(), {
5050
term = true,
5151
on_exit = function()
5252
state.chan = nil
@@ -62,6 +62,13 @@ local function start_terminal()
6262
end)
6363
end,
6464
})
65+
66+
if chan <= 0 then
67+
vim.notify("[rustmail] failed to start TUI process", vim.log.levels.ERROR)
68+
return
69+
end
70+
71+
state.chan = chan
6572
end
6673

6774
function M._float_dims()
@@ -103,7 +110,7 @@ function M.open_float(buf)
103110
row = dims.row,
104111
style = "minimal",
105112
border = cfg.border,
106-
title = " Rustmail ",
113+
title = " RustMail ",
107114
title_pos = "center",
108115
})
109116

0 commit comments

Comments
 (0)