2024-07-14 11:42:22 -04:00
|
|
|
# typed: true # rubocop:todo Sorbet/StrictSigil
|
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require "downloadable"
|
2024-07-16 10:18:26 -04:00
|
|
|
require "concurrent/promises"
|
2024-07-15 10:25:25 -04:00
|
|
|
require "concurrent/executors"
|
2024-07-14 11:42:22 -04:00
|
|
|
|
|
|
|
module Homebrew
|
|
|
|
class DownloadQueue
|
|
|
|
sig { returns(Concurrent::FixedThreadPool) }
|
|
|
|
attr_reader :pool
|
|
|
|
private :pool
|
|
|
|
|
|
|
|
sig { params(size: Integer).void }
|
|
|
|
def initialize(size = 1)
|
|
|
|
@pool = Concurrent::FixedThreadPool.new(size)
|
|
|
|
end
|
|
|
|
|
2024-07-16 10:18:26 -04:00
|
|
|
sig { params(downloadable: Downloadable, force: T::Boolean).returns(Concurrent::Promises::Future) }
|
|
|
|
def enqueue(downloadable, force: false)
|
|
|
|
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:)
|
2024-07-14 11:42:22 -04:00
|
|
|
end
|
2024-07-16 10:18:26 -04:00
|
|
|
# rubocop:enable Lint/ShadowingOuterLocalVariable
|
2024-07-14 11:42:22 -04:00
|
|
|
end
|
|
|
|
|
2024-09-07 14:45:30 +02:00
|
|
|
sig { void }
|
|
|
|
def cancel
|
|
|
|
# FIXME: Implement graceful cancellaction of running downloads based on
|
|
|
|
# https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Cancellation.html
|
|
|
|
# instead of killing the whole thread pool.
|
|
|
|
pool.kill
|
|
|
|
end
|
|
|
|
|
2024-07-14 11:42:22 -04:00
|
|
|
sig { void }
|
|
|
|
def shutdown
|
|
|
|
pool.shutdown
|
2024-09-07 14:45:30 +02:00
|
|
|
pool.wait_for_termination
|
2024-07-14 11:42:22 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|