From d731a6b005fd239e85e555bd57362382f6c1e461 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Tue, 16 Jul 2024 16:50:31 +0200 Subject: [PATCH] feat(git): added git network throttle to limit network related git ops per interval. Closes #1635 --- lua/lazy/core/config.lua | 7 +++++++ lua/lazy/manage/task/git.lua | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lua/lazy/core/config.lua b/lua/lazy/core/config.lua index 1206305f..3ec89c61 100644 --- a/lua/lazy/core/config.lua +++ b/lua/lazy/core/config.lua @@ -34,6 +34,13 @@ M.defaults = { -- then set the below to false. This should work, but is NOT supported and will -- increase downloads a lot. filter = true, + -- rate of network related git operations (clone, fetch, checkout) + throttle = { + enabled = false, -- not enabled by default + -- max 2 ops every 5 seconds + rate = 2, + duration = 5 * 1000, -- in ms + }, }, pkg = { enabled = true, diff --git a/lua/lazy/manage/task/git.lua b/lua/lazy/manage/task/git.lua index 9425fec0..bd7ee38e 100644 --- a/lua/lazy/manage/task/git.lua +++ b/lua/lazy/manage/task/git.lua @@ -1,8 +1,45 @@ +local Async = require("lazy.async") local Config = require("lazy.core.config") local Git = require("lazy.manage.git") local Lock = require("lazy.manage.lock") local Util = require("lazy.util") +local throttle = {} +throttle.running = 0 +throttle.waiting = {} ---@type Async[] +throttle.timer = vim.uv.new_timer() + +function throttle.next() + throttle.running = 0 + while #throttle.waiting > 0 and throttle.running < Config.options.git.throttle.rate do + ---@type Async + local task = table.remove(throttle.waiting, 1) + task:resume() + throttle.running = throttle.running + 1 + end + if throttle.running == 0 then + throttle.timer:stop() + end +end + +function throttle.wait() + if not Config.options.git.throttle.enabled then + return + end + if not throttle.timer:is_active() then + throttle.timer:start(0, Config.options.git.throttle.duration, vim.schedule_wrap(throttle.next)) + end + local running = Async.running() + if throttle.running < Config.options.git.throttle.rate then + throttle.running = throttle.running + 1 + else + table.insert(throttle.waiting, running) + coroutine.yield("waiting") + running:suspend() + coroutine.yield("") + end +end + ---@type table local M = {} @@ -84,6 +121,7 @@ M.clone = { end, ---@async run = function(self) + throttle.wait() local args = { "clone", self.plugin.url, @@ -233,6 +271,7 @@ M.fetch = { ---@async run = function(self) + throttle.wait() local args = { "fetch", "--recurse-submodules", @@ -262,6 +301,7 @@ M.checkout = { ---@async ---@param opts {lockfile?:boolean} run = function(self, opts) + throttle.wait() local info = assert(Git.info(self.plugin.dir)) local target = assert(Git.get_target(self.plugin))