Skip to content

Commit

Permalink
fix(loader): Load files concurrently with a limit to avoid "too many …
Browse files Browse the repository at this point in the history
…open files" errors
  • Loading branch information
kristijanhusak committed Sep 20, 2024
1 parent a006c93 commit 1692af5
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
6 changes: 2 additions & 4 deletions lua/orgmode/files/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,14 @@ function OrgFiles:load(force)
end

self.load_state = 'loading'
local actions = vim.tbl_map(function(filename)
return Promise.map(function(filename)
return self:load_file(filename):next(function(orgfile)
if orgfile then
self.files[orgfile.filename] = orgfile
end
return orgfile
end)
end, self:_files(true))

return Promise.all(actions):next(function()
end, self:_files(true), 50):next(function()
self.load_state = 'loaded'
return self
end)
Expand Down
47 changes: 47 additions & 0 deletions lua/orgmode/utils/promise.lua
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,53 @@ function Promise.all(list)
end)
end

--- Equivalents to JavaScript's Promise.map with concurrency limit.
--- @param callback fun(value: any, index: number, array: any[]): any
--- @param list any[]: promise or non-promise values
--- @param concurrency? number: limit number of concurrent items processing
--- @return OrgPromise
function Promise.map(callback, list, concurrency)
vim.validate({
list = { list, 'table' },
callback = { callback, 'function' },
concurrency = { concurrency, 'number', true },
})

local results = {}
local processing = 0
local index = 1
concurrency = concurrency or #list

return Promise.new(function(resolve, reject)
local function processNext()
if index > #list then
if processing == 0 then
resolve(results)
end
return
end

local i = index
index = index + 1
processing = processing + 1

Promise.resolve(callback(list[i], i, list))
:next(function(...)
results[i] = ...
processing = processing - 1
processNext()
end)
:catch(function(...)
reject(...)
end)
end

for _ = 1, concurrency do
processNext()
end
end)
end

--- Equivalents to JavaScript's Promise.race.
--- @param list any[]: promise or non-promise values
--- @return OrgPromise
Expand Down

0 comments on commit 1692af5

Please sign in to comment.