fix(async): make asyncs abortable

This commit is contained in:
Folke Lemaitre 2024-06-30 13:35:11 +02:00
parent c882227f1f
commit 1fad61712b
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
7 changed files with 29 additions and 8 deletions

View File

@ -79,7 +79,7 @@ end
function Async:suspend(yield)
self._suspended = true
if coroutine.running() == self._co and yield ~= false then
coroutine.yield()
M.yield()
end
end
@ -132,12 +132,25 @@ function Async:step()
return self:running()
end
function M.abort()
for _, async in ipairs(M._active) do
coroutine.resume(async._co, "abort")
end
end
function M.yield()
if coroutine.yield() == "abort" then
error("aborted", 2)
end
end
function M.step()
local start = vim.uv.hrtime()
for _ = 1, #M._active do
if vim.uv.hrtime() - start > M.BUDGET * 1e6 then
if Util.exiting() or vim.uv.hrtime() - start > M.BUDGET * 1e6 then
break
end
local state = table.remove(M._active, 1)
if state:step() then
if state._suspended then
@ -153,7 +166,7 @@ function M.step()
end
-- M.debug()
if #M._active == 0 then
if #M._active == 0 or Util.exiting() then
return M._executor:stop()
end
end
@ -183,7 +196,7 @@ function M.add(async)
end
function M._run()
if not M._executor:is_active() then
if not Util.exiting() and not M._executor:is_active() then
M._executor:start(vim.schedule_wrap(M.step))
end
end

View File

@ -29,6 +29,10 @@ function M.track(data, time)
end
end
function M.exiting()
return vim.v.exiting ~= vim.NIL
end
---@generic T
---@param list T[]
---@param fn fun(v: T):boolean?

View File

@ -93,7 +93,7 @@ function Process:_run()
end)
self:suspend()
while not (self.handle:is_closing() and stdout:is_closing() and stderr:is_closing()) do
coroutine.yield()
Async.yield()
end
else
self.data = "Failed to spawn process " .. self.cmd .. " " .. vim.inspect(self.opts)

View File

@ -295,6 +295,7 @@ function M:close(opts)
vim.diagnostic.reset(Config.ns, buf)
vim.api.nvim_buf_delete(buf, { force = true })
end
vim.cmd.redraw()
end)
end

View File

@ -83,6 +83,7 @@ function M.create()
vim.keymap.set("n", ViewConfig.keys.abort, function()
require("lazy.manage.process").abort()
require("lazy.async").abort()
return ViewConfig.keys.abort
end, { silent = true, buffer = self.buf, expr = true })

View File

@ -1,3 +1,4 @@
local Async = require("lazy.async")
local Runner = require("lazy.manage.runner")
describe("runner", function()
@ -33,7 +34,7 @@ describe("runner", function()
---@async
---@param task LazyTask
run = function(task)
coroutine.yield()
Async.yield()
table.insert(runs, { plugin = task.plugin.name, task = task.name })
end,
}

View File

@ -1,4 +1,5 @@
--# selene:allow(incorrect_standard_library_use)
local Async = require("lazy.async")
local Task = require("lazy.manage.task")
describe("task", function()
@ -42,7 +43,7 @@ describe("task", function()
local running = true
---@async
local task = Task.new(plugin, "test", function()
coroutine.yield()
Async.yield()
running = false
end, opts)
assert(task:running())