Use futures instead of promises.

This commit is contained in:
Markus Reiter 2024-07-16 10:18:26 -04:00
parent d6ebb04ff5
commit e7c9049a3c
No known key found for this signature in database
GPG Key ID: 245293B51702655B
2 changed files with 22 additions and 19 deletions

View File

@ -240,23 +240,23 @@ module Homebrew
$stdout.print Tty.hide_cursor $stdout.print Tty.hide_cursor
$stdout.flush $stdout.flush
output_message = lambda do |downloadable, promise| output_message = lambda do |downloadable, future|
status = case promise.state status = case future.state
when :fulfilled when :fulfilled
"#{Tty.green}✔︎#{Tty.reset}" "#{Tty.green}✔︎#{Tty.reset}"
when :rejected when :rejected
"#{Tty.red}#{Tty.reset}" "#{Tty.red}#{Tty.reset}"
when :pending when :pending, :processing
"#{Tty.blue}#{spinner}#{Tty.reset}" "#{Tty.blue}#{spinner}#{Tty.reset}"
else else
raise promise.state raise future.state.to_s
end end
message = "#{downloadable.download_type.capitalize} #{downloadable.name}" message = "#{downloadable.download_type.capitalize} #{downloadable.name}"
$stdout.puts "#{status} #{message}" $stdout.puts "#{status} #{message}"
$stdout.flush $stdout.flush
if promise.rejected? && (e = promise.reason).is_a?(ChecksumMismatchError) if future.rejected? && (e = future.reason).is_a?(ChecksumMismatchError)
opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}"
Homebrew.failed = true if downloadable.is_a?(Resource::Patch) Homebrew.failed = true if downloadable.is_a?(Resource::Patch)
next 2 next 2
@ -269,24 +269,24 @@ module Homebrew
begin begin
finished_states = [:fulfilled, :rejected] finished_states = [:fulfilled, :rejected]
finished_downloads, remaining_downloads = remaining_downloads.partition do |_, promise| finished_downloads, remaining_downloads = remaining_downloads.partition do |_, future|
finished_states.include?(promise.state) finished_states.include?(future.state)
end end
finished_downloads.each do |downloadable, promise| finished_downloads.each do |downloadable, future|
previous_pending_line_count -= 1 previous_pending_line_count -= 1
print "\033[K" print "\033[K"
$stdout.flush $stdout.flush
output_message.call(downloadable, promise) output_message.call(downloadable, future)
end end
previous_pending_line_count = 0 previous_pending_line_count = 0
remaining_downloads.each do |downloadable, promise| remaining_downloads.each do |downloadable, future|
break if previous_pending_line_count >= [concurrency, (Tty.height - 1)].min break if previous_pending_line_count >= [concurrency, (Tty.height - 1)].min
print "\033[K" print "\033[K"
$stdout.flush $stdout.flush
previous_pending_line_count += output_message.call(downloadable, promise) previous_pending_line_count += output_message.call(downloadable, future)
end end
if previous_pending_line_count.positive? if previous_pending_line_count.positive?
@ -317,9 +317,7 @@ module Homebrew
end end
def fetch_downloadable(downloadable) def fetch_downloadable(downloadable)
downloadable.clear_cache if args.force? downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable), force: args.force?)
downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable))
end end
end end
end end

View File

@ -2,7 +2,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "downloadable" require "downloadable"
require "concurrent/promise" require "concurrent/promises"
require "concurrent/executors" require "concurrent/executors"
module Homebrew module Homebrew
@ -16,11 +16,16 @@ module Homebrew
@pool = Concurrent::FixedThreadPool.new(size) @pool = Concurrent::FixedThreadPool.new(size)
end end
sig { params(downloadable: Downloadable).returns(Concurrent::Promise) } sig { params(downloadable: Downloadable, force: T::Boolean).returns(Concurrent::Promises::Future) }
def enqueue(downloadable) def enqueue(downloadable, force: false)
Concurrent::Promise.execute(executor: pool) do quiet = pool.max_length > 1
downloadable.fetch(quiet: pool.max_length > 1) # Passing in arguments from outside into the future is a common `concurrent-ruby` pattern.
# rubocop:disable Lint/ShadowingOuterLocalVariable
Concurrent::Promises.future_on(pool, downloadable, force, quiet) do |downloadable, force, quiet|
downloadable.clear_cache if force
downloadable.fetch(quiet:)
end end
# rubocop:enable Lint/ShadowingOuterLocalVariable
end end
sig { void } sig { void }