Skip to content

Commit

Permalink
fix(scheduler): make sure to sleep more than enough to trigger the task
Browse files Browse the repository at this point in the history
  • Loading branch information
pysan3 committed Mar 15, 2024
1 parent 165e6e6 commit 3a65f03
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
6 changes: 5 additions & 1 deletion lua/pathlib/git.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ M.gitScheduler = Scheduler(function(items, key)
M.fill_git_state_in_root(items, require("pathlib").new(key))
return true
end, function(elapsed_ms, item_len)
return item_len * 10 <= elapsed_ms or item_len >= 190
if item_len >= 190 then
return -1
end
return item_len * 10 - elapsed_ms
end, 10)

---Find closest directory that contains `.git` directory, meaning that it's a root of a git repository
Expand Down Expand Up @@ -325,6 +328,7 @@ function M.request_git_status_update(path, args)
path.git_state.is_ready = nil
local future = M.gitScheduler:add(path.git_state.git_root:tostring(), path)
path.git_state.is_ready = future
return future
end

return M
30 changes: 25 additions & 5 deletions lua/pathlib/utils/scheduler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ local nio = require("nio")
---@field future nio.control.Future
---@field start integer

---@alias PathlibScheduler.monitor fun(elapsed_ms: integer, item_len: integer, key: string): boolean # A function to decide whether to trigger the debounce_fn.
---@alias PathlibScheduler.monitor fun(elapsed_ms: integer, item_len: integer, key: string): integer # A function to decide whether to trigger the debounce_fn. Triggers if value is negative.
---@alias PathlibScheduler.executor fun(items: PathlibPath[], key: string): (boolean, string|nil) # Executed when should_run_fn returns true. Return values are (success, error_msg?).

---@class PathlibScheduler
Expand Down Expand Up @@ -44,7 +44,7 @@ function _Scheduler:add(key, item)
self.storage[key] = {
items = { item },
future = nio.control.future(),
start = os.clock(),
start = vim.loop.hrtime(),
}
else
table.insert(self.storage[key].items, item)
Expand All @@ -63,17 +63,34 @@ end
function _Scheduler:check_and_trigger(key)
return nio.run(function()
local info = self.storage[key]
local elapsed = os.clock() - info.start
if elapsed >= self.minimum_debounce_ms and self.monitor(elapsed, #info.items, key) then
self:trigger(key)
if not info then
return
end
nio.sleep(self.minimum_debounce_ms)
local start, iter = info.start, 0
while true do
info = self.storage[key]
if not info or info.start ~= start then
return -- some other process triggered the task
end
local wait_ms = self.monitor((vim.loop.hrtime() - start) / 1000 / 1000, #info.items, key)
if wait_ms <= 0 then
break
end
nio.sleep(math.min(self.minimum_debounce_ms, wait_ms + iter))
iter = iter + self.minimum_debounce_ms
end
self:trigger(key)
end)
end

---Triggers `self.executor` for key.
---@param key string
function _Scheduler:trigger(key)
local info = self.storage[key]
if not info then
return
end
self.storage[key] = nil
nio.run(function()
local suc, err = self.executor(info.items, key)
Expand All @@ -89,6 +106,9 @@ end
---@param key string
function _Scheduler:clear(key)
local info = self.storage[key]
if not info then
return
end
self.storage[key] = nil
nio.run(function()
info.future.set_error(debug.traceback("Manually Cleared"))
Expand Down

0 comments on commit 3a65f03

Please sign in to comment.