Skip to content

Commit c25ed8f

Browse files
committed
Cleanup Download Queue
- cleanup various cases conditional on the download queue to always use it, now it's default and has been for a while - ensure that both casks and formulae are fetched at the same time when possible to maximise concurrency - generally DRY up the relevant download queue code
1 parent fc785ec commit c25ed8f

File tree

15 files changed

+536
-229
lines changed

15 files changed

+536
-229
lines changed

Library/Homebrew/api.rb

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
require "api/formula_struct"
99
require "api/cask_struct"
1010
require "base64"
11+
require "download_queue"
1112
require "utils/output"
1213

1314
module Homebrew
@@ -53,11 +54,13 @@ def self.skip_download?(target:, stale_seconds:)
5354
endpoint: String,
5455
target: Pathname,
5556
stale_seconds: T.nilable(Integer),
56-
download_queue: T.nilable(DownloadQueue),
57+
download_queue: DownloadQueue,
58+
enqueue: T::Boolean,
5759
).returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
5860
}
5961
def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint,
60-
stale_seconds: nil, download_queue: nil)
62+
stale_seconds: nil, download_queue: Homebrew.default_download_queue,
63+
enqueue: false)
6164
# Lazy-load dependency.
6265
require "development_tools"
6366

@@ -80,7 +83,7 @@ def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint,
8083
DevelopmentTools.curl_substitution_required?
8184
skip_download = skip_download?(target:, stale_seconds:)
8285

83-
if download_queue
86+
if enqueue
8487
unless skip_download
8588
require "api/json_download"
8689
download = Homebrew::API::JSONDownload.new(endpoint, target:, stale_seconds:)
@@ -167,10 +170,7 @@ def self.merge_variations(json, bottle_tag: T.unsafe(nil))
167170

168171
sig { void }
169172
def self.fetch_api_files!
170-
download_queue = if Homebrew::EnvConfig.download_concurrency > 1
171-
require "download_queue"
172-
Homebrew::DownloadQueue.new
173-
end
173+
download_queue = Homebrew::DownloadQueue.new
174174

175175
stale_seconds = if ENV["HOMEBREW_API_UPDATED"].present? ||
176176
(Homebrew::EnvConfig.no_auto_update? && !Homebrew::EnvConfig.force_api_auto_update?)
@@ -182,19 +182,19 @@ def self.fetch_api_files!
182182
end
183183

184184
if Homebrew::EnvConfig.use_internal_api?
185-
Homebrew::API::Internal.fetch_formula_api!(download_queue:, stale_seconds:)
186-
Homebrew::API::Internal.fetch_cask_api!(download_queue:, stale_seconds:)
185+
Homebrew::API::Internal.fetch_formula_api!(download_queue:, stale_seconds:, enqueue: true)
186+
Homebrew::API::Internal.fetch_cask_api!(download_queue:, stale_seconds:, enqueue: true)
187187
else
188-
Homebrew::API::Formula.fetch_api!(download_queue:, stale_seconds:)
189-
Homebrew::API::Formula.fetch_tap_migrations!(download_queue:, stale_seconds: DEFAULT_API_STALE_SECONDS)
190-
Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:)
191-
Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds: DEFAULT_API_STALE_SECONDS)
188+
Homebrew::API::Formula.fetch_api!(download_queue:, stale_seconds:, enqueue: true)
189+
Homebrew::API::Formula.fetch_tap_migrations!(download_queue:, stale_seconds: DEFAULT_API_STALE_SECONDS,
190+
enqueue: true)
191+
Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:, enqueue: true)
192+
Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds: DEFAULT_API_STALE_SECONDS,
193+
enqueue: true)
192194
end
193195

194196
ENV["HOMEBREW_API_UPDATED"] = "1"
195197

196-
return unless download_queue
197-
198198
begin
199199
download_queue.fetch
200200
ensure

Library/Homebrew/api/cask.rb

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,25 @@ def self.cask_json(name)
2323
cache.fetch("cask_json").fetch(name)
2424
end
2525

26-
sig { params(name: String, download_queue: T.nilable(DownloadQueue)).void }
27-
def self.fetch_cask_json!(name, download_queue: nil)
26+
sig { params(name: String).void }
27+
def self.fetch_cask_json!(name)
2828
endpoint = "cask/#{name}.json"
29-
json_cask, updated = Homebrew::API.fetch_json_api_file endpoint, download_queue: download_queue
30-
return if download_queue
29+
json_cask, updated = Homebrew::API.fetch_json_api_file endpoint
3130

3231
json_cask = JSON.parse((HOMEBREW_CACHE_API/endpoint).read) unless updated
3332

3433
cache["cask_json"] ||= {}
3534
cache["cask_json"][name] = json_cask
3635
end
3736

38-
sig { params(cask: ::Cask::Cask, download_queue: T.nilable(Homebrew::DownloadQueue)).returns(Homebrew::API::SourceDownload) }
39-
def self.source_download(cask, download_queue: nil)
37+
sig {
38+
params(
39+
cask: ::Cask::Cask,
40+
download_queue: Homebrew::DownloadQueue,
41+
enqueue: T::Boolean,
42+
).returns(Homebrew::API::SourceDownload)
43+
}
44+
def self.source_download(cask, download_queue: Homebrew.default_download_queue, enqueue: false)
4045
path = cask.ruby_source_path.to_s
4146
sha256 = cask.ruby_source_checksum[:sha256]
4247
checksum = Checksum.new(sha256) if sha256
@@ -52,7 +57,7 @@ def self.source_download(cask, download_queue: nil)
5257
cache: HOMEBREW_CACHE_API_SOURCE/"#{tap}/#{git_head}/Cask",
5358
)
5459

55-
if download_queue
60+
if enqueue
5661
download_queue.enqueue(download)
5762
elsif !download.symlink_location.exist?
5863
download.fetch
@@ -75,19 +80,20 @@ def self.cached_json_file_path
7580
end
7681

7782
sig {
78-
params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
83+
params(download_queue: ::Homebrew::DownloadQueue, stale_seconds: T.nilable(Integer), enqueue: T::Boolean)
7984
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
8085
}
81-
def self.fetch_api!(download_queue: nil, stale_seconds: nil)
82-
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:
86+
def self.fetch_api!(download_queue: Homebrew.default_download_queue, stale_seconds: nil, enqueue: false)
87+
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:, enqueue:
8388
end
8489

8590
sig {
86-
params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
91+
params(download_queue: ::Homebrew::DownloadQueue, stale_seconds: T.nilable(Integer), enqueue: T::Boolean)
8792
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
8893
}
89-
def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: nil)
90-
Homebrew::API.fetch_json_api_file "cask_tap_migrations.jws.json", stale_seconds:, download_queue:
94+
def self.fetch_tap_migrations!(download_queue: Homebrew.default_download_queue, stale_seconds: nil,
95+
enqueue: false)
96+
Homebrew::API.fetch_json_api_file "cask_tap_migrations.jws.json", stale_seconds:, download_queue:, enqueue:
9197
end
9298

9399
sig { returns(T::Boolean) }

Library/Homebrew/api/formula.rb

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,25 @@ def self.formula_json(name)
2525
cache.fetch("formula_json").fetch(name)
2626
end
2727

28-
sig { params(name: String, download_queue: T.nilable(DownloadQueue)).void }
29-
def self.fetch_formula_json!(name, download_queue: nil)
28+
sig { params(name: String).void }
29+
def self.fetch_formula_json!(name)
3030
endpoint = "formula/#{name}.json"
31-
json_formula, updated = Homebrew::API.fetch_json_api_file endpoint, download_queue: download_queue
32-
return if download_queue
31+
json_formula, updated = Homebrew::API.fetch_json_api_file endpoint
3332

3433
json_formula = JSON.parse((HOMEBREW_CACHE_API/endpoint).read) unless updated
3534

3635
cache["formula_json"] ||= {}
3736
cache["formula_json"][name] = json_formula
3837
end
3938

40-
sig { params(formula: ::Formula, download_queue: T.nilable(Homebrew::DownloadQueue)).returns(Homebrew::API::SourceDownload) }
41-
def self.source_download(formula, download_queue: nil)
39+
sig {
40+
params(
41+
formula: ::Formula,
42+
download_queue: Homebrew::DownloadQueue,
43+
enqueue: T::Boolean,
44+
).returns(Homebrew::API::SourceDownload)
45+
}
46+
def self.source_download(formula, download_queue: Homebrew.default_download_queue, enqueue: false)
4247
path = formula.ruby_source_path || "Formula/#{formula.name}.rb"
4348
git_head = formula.tap_git_head || "HEAD"
4449
tap = formula.tap&.full_name || "Homebrew/homebrew-core"
@@ -49,7 +54,7 @@ def self.source_download(formula, download_queue: nil)
4954
cache: HOMEBREW_CACHE_API_SOURCE/"#{tap}/#{git_head}/Formula",
5055
)
5156

52-
if download_queue
57+
if enqueue
5358
download_queue.enqueue(download)
5459
elsif !download.symlink_location.exist?
5560
download.fetch
@@ -76,19 +81,20 @@ def self.cached_json_file_path
7681
end
7782

7883
sig {
79-
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
84+
params(download_queue: Homebrew::DownloadQueue, stale_seconds: T.nilable(Integer), enqueue: T::Boolean)
8085
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
8186
}
82-
def self.fetch_api!(download_queue: nil, stale_seconds: nil)
83-
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:
87+
def self.fetch_api!(download_queue: Homebrew.default_download_queue, stale_seconds: nil, enqueue: false)
88+
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:, enqueue:
8489
end
8590

8691
sig {
87-
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
92+
params(download_queue: Homebrew::DownloadQueue, stale_seconds: T.nilable(Integer), enqueue: T::Boolean)
8893
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
8994
}
90-
def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: nil)
91-
Homebrew::API.fetch_json_api_file "formula_tap_migrations.jws.json", stale_seconds:, download_queue:
95+
def self.fetch_tap_migrations!(download_queue: Homebrew.default_download_queue, stale_seconds: nil,
96+
enqueue: false)
97+
Homebrew::API.fetch_json_api_file "formula_tap_migrations.jws.json", stale_seconds:, download_queue:, enqueue:
9298
end
9399

94100
sig { returns(T::Boolean) }

Library/Homebrew/api/internal.rb

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,24 @@ def self.cached_cask_json_file_path
5050
end
5151

5252
sig {
53-
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
53+
params(download_queue: Homebrew::DownloadQueue, stale_seconds: T.nilable(Integer), enqueue: T::Boolean)
5454
.returns([T::Hash[String, T.untyped], T::Boolean])
5555
}
56-
def self.fetch_formula_api!(download_queue: nil, stale_seconds: nil)
57-
json_contents, updated = Homebrew::API.fetch_json_api_file(formula_endpoint, stale_seconds:, download_queue:)
56+
def self.fetch_formula_api!(download_queue: Homebrew.default_download_queue, stale_seconds: nil,
57+
enqueue: false)
58+
json_contents, updated = Homebrew::API.fetch_json_api_file(formula_endpoint, stale_seconds:, download_queue:,
59+
enqueue:)
5860
[T.cast(json_contents, T::Hash[String, T.untyped]), updated]
5961
end
6062

6163
sig {
62-
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
64+
params(download_queue: Homebrew::DownloadQueue, stale_seconds: T.nilable(Integer), enqueue: T::Boolean)
6365
.returns([T::Hash[String, T.untyped], T::Boolean])
6466
}
65-
def self.fetch_cask_api!(download_queue: nil, stale_seconds: nil)
66-
json_contents, updated = Homebrew::API.fetch_json_api_file(cask_endpoint, stale_seconds:, download_queue:)
67+
def self.fetch_cask_api!(download_queue: Homebrew.default_download_queue, stale_seconds: nil,
68+
enqueue: false)
69+
json_contents, updated = Homebrew::API.fetch_json_api_file(cask_endpoint, stale_seconds:, download_queue:,
70+
enqueue:)
6771
[T.cast(json_contents, T::Hash[String, T.untyped]), updated]
6872
end
6973

Library/Homebrew/brew.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
cmd_class = Homebrew::AbstractCommand.command(cmd)
9191
Homebrew.running_command = cmd
9292
if cmd_class
93-
if !Homebrew::EnvConfig.no_install_from_api? && Homebrew::EnvConfig.download_concurrency > 1
93+
unless Homebrew::EnvConfig.no_install_from_api?
9494
require "api"
9595
Homebrew::API.fetch_api_files!
9696
end

Library/Homebrew/cask/installer.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@ class Installer
2525
skip_cask_deps: T::Boolean, binaries: T::Boolean, verbose: T::Boolean, zap: T::Boolean,
2626
require_sha: T::Boolean, upgrade: T::Boolean, reinstall: T::Boolean, installed_as_dependency: T::Boolean,
2727
installed_on_request: T::Boolean, quarantine: T::Boolean, verify_download_integrity: T::Boolean,
28-
quiet: T::Boolean, download_queue: T.nilable(Homebrew::DownloadQueue)
28+
quiet: T::Boolean, download_queue: Homebrew::DownloadQueue, defer_fetch: T::Boolean
2929
).void
3030
}
3131
def initialize(cask, command: SystemCommand, force: false, adopt: false,
3232
skip_cask_deps: false, binaries: true, verbose: false,
3333
zap: false, require_sha: false, upgrade: false, reinstall: false,
3434
installed_as_dependency: false, installed_on_request: true,
35-
quarantine: true, verify_download_integrity: true, quiet: false, download_queue: nil)
35+
quarantine: true, verify_download_integrity: true, quiet: false,
36+
download_queue: Homebrew.default_download_queue, defer_fetch: false)
3637
@cask = cask
3738
@command = command
3839
@force = force
@@ -50,6 +51,7 @@ def initialize(cask, command: SystemCommand, force: false, adopt: false,
5051
@verify_download_integrity = verify_download_integrity
5152
@quiet = quiet
5253
@download_queue = download_queue
54+
@defer_fetch = T.let(defer_fetch, T::Boolean)
5355
@ran_prelude = T.let(false, T::Boolean)
5456
end
5557

@@ -118,7 +120,7 @@ def fetch(quiet: nil, timeout: nil)
118120
forbidden_cask_and_formula_check
119121
forbidden_cask_artifacts_check
120122

121-
download(quiet:, timeout:) if @download_queue.nil?
123+
download(quiet:, timeout:) unless @defer_fetch
122124

123125
satisfy_cask_and_formula_dependencies
124126
end
@@ -853,15 +855,14 @@ def prelude
853855
sig { void }
854856
def enqueue_downloads
855857
download_queue = @download_queue
856-
return if download_queue.nil?
857858

858859
# FIXME: We need to load Cask source before enqueuing to support
859860
# language-specific URLs, but this will block the main process.
860861
if cask_from_source_api?
861862
if @cask.languages.any?
862863
load_cask_from_source_api!
863864
else
864-
Homebrew::API::Cask.source_download(@cask, download_queue:)
865+
Homebrew::API::Cask.source_download(@cask, download_queue:, enqueue: true)
865866
end
866867
end
867868

Library/Homebrew/cask/reinstall.rb

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ class Reinstall
1010
sig {
1111
params(
1212
casks: ::Cask::Cask, verbose: T::Boolean, force: T::Boolean, skip_cask_deps: T::Boolean, binaries: T::Boolean,
13-
require_sha: T::Boolean, quarantine: T::Boolean, zap: T::Boolean
13+
require_sha: T::Boolean, quarantine: T::Boolean, zap: T::Boolean, skip_prefetch: T::Boolean,
14+
download_queue: T.nilable(Homebrew::DownloadQueue)
1415
).void
1516
}
1617
def self.reinstall_casks(
@@ -21,25 +22,51 @@ def self.reinstall_casks(
2122
binaries: false,
2223
require_sha: false,
2324
quarantine: false,
24-
zap: false
25+
zap: false,
26+
skip_prefetch: false,
27+
download_queue: nil
2528
)
2629
require "cask/installer"
2730

2831
quarantine = true if quarantine.nil?
29-
30-
download_queue = Homebrew::DownloadQueue.new_if_concurrency_enabled(pour: true)
31-
cask_installers = casks.map do |cask|
32-
Installer.new(cask, binaries:, verbose:, force:, skip_cask_deps:, require_sha:, reinstall: true,
33-
quarantine:, zap:, download_queue:)
32+
created_download_queue = T.let(false, T::Boolean)
33+
if download_queue.nil?
34+
if skip_prefetch
35+
download_queue = Homebrew.default_download_queue
36+
else
37+
download_queue = Homebrew::DownloadQueue.new(pour: true)
38+
created_download_queue = true
39+
end
3440
end
3541

36-
if download_queue
37-
cask_installers.each(&:prelude)
42+
cask_installers = T.let([], T::Array[Installer])
43+
begin
44+
cask_installers = casks.map do |cask|
45+
Installer.new(
46+
cask,
47+
binaries:,
48+
verbose:,
49+
force:,
50+
skip_cask_deps:,
51+
require_sha:,
52+
reinstall: true,
53+
quarantine:,
54+
zap:,
55+
download_queue:,
56+
defer_fetch: true,
57+
)
58+
end
59+
60+
unless skip_prefetch
61+
cask_installers.each(&:prelude)
3862

39-
oh1 "Fetching downloads for: #{casks.map { |cask| Formatter.identifier(cask.full_name) }.to_sentence}",
40-
truncate: false
41-
cask_installers.each(&:enqueue_downloads)
42-
download_queue.fetch
63+
oh1 "Fetching downloads for: #{casks.map { |cask| Formatter.identifier(cask.full_name) }.to_sentence}",
64+
truncate: false
65+
cask_installers.each(&:enqueue_downloads)
66+
download_queue.fetch
67+
end
68+
ensure
69+
download_queue.shutdown if created_download_queue
4370
end
4471

4572
exit 1 if Homebrew.failed?

0 commit comments

Comments
 (0)