Added parallel downloads setting (not in gui options yet), added a thread pool for downloading multiple packages at once- quite helpful for TSR 😁, fixed download resuming (used wrong file mode...)

This commit is contained in:
2021-12-23 10:56:28 -06:00
parent 47a22311bb
commit 9707110972
5 changed files with 112 additions and 14 deletions

View File

@@ -0,0 +1,89 @@
class W3DHub
class ApplicationManager
class Pool
def initialize(workers:)
@workers = workers.times.collect { Worker.new }
@jobs = []
end
def add_job(job)
@jobs << job
end
def manage_pool
while (@jobs.size.positive? || @workers.any?(&:busy?))
feed_pool unless @jobs.size.zero?
sleep 0.1
end
end
def feed_pool
@workers.select(&:available?).each do |worker|
worker.feed(@jobs.shift)
end
end
class Worker
def initialize
@die = false
@job = nil
Thread.new do
until (@die)
@job.process if @job && @job.waiting?
@job = nil
sleep 0.1
end
end
end
def feed(job)
raise "Worker already processing a job!" if @job&.processing?
@job = job
end
def die!
@die = true
end
def available?
@job.nil?
end
def busy?
!available?
end
end
class Job
def initialize(block)
@block = block
@state = :waiting
end
def waiting?
@state == :waiting
end
def processing?
@state == :processing
end
def complete?
@state == :complete
end
def process
@state = :processing
@block.call
@state == :complete
end
end
end
end
end

View File

@@ -281,23 +281,29 @@ class W3DHub
@total_bytes_to_download = @packages_to_download.sum { |pkg| pkg.size - pkg.custom_partially_valid_at_bytes }
@bytes_downloaded = 0
pool = Pool.new(workers: Store.settings[:parallel_downloads])
@packages_to_download.each do |pkg|
package_bytes_downloaded = pkg.custom_partially_valid_at_bytes
pool.add_job Pool::Job.new( proc {
package_bytes_downloaded = pkg.custom_partially_valid_at_bytes
package_fetch(pkg) do |chunk, remaining_bytes, total_bytes|
@bytes_downloaded += chunk.to_s.length
package_bytes_downloaded += chunk.to_s.length
package_fetch(pkg) do |chunk, remaining_bytes, total_bytes|
@bytes_downloaded += chunk.to_s.length
package_bytes_downloaded += chunk.to_s.length
@status.value = "#{W3DHub.format_size(@bytes_downloaded)} / #{W3DHub.format_size(@total_bytes_to_download)}"
@status.progress = @bytes_downloaded.to_f / @total_bytes_to_download
@status.value = "#{W3DHub.format_size(@bytes_downloaded)} / #{W3DHub.format_size(@total_bytes_to_download)}"
@status.progress = @bytes_downloaded.to_f / @total_bytes_to_download
operation = @status.operations[:"#{pkg.checksum}"]
operation.value = "#{W3DHub.format_size(package_bytes_downloaded)} / #{W3DHub.format_size(pkg.size)}"
operation.progress = package_bytes_downloaded.to_f / total_bytes
operation = @status.operations[:"#{pkg.checksum}"]
operation.value = "#{W3DHub.format_size(package_bytes_downloaded)} / #{W3DHub.format_size(pkg.size)}"
operation.progress = package_bytes_downloaded.to_f / pkg.size # total_bytes
update_interface_task_status
end
update_interface_task_status
end
})
end
pool.manage_pool
else
puts "FAILED!"
pp package_details
@@ -318,6 +324,7 @@ class W3DHub
@status.progress = 0.0
packages.each do |pkg|
# FIXME: can't add a new key into hash during iteration (RuntimeError)
@status.operations[:"#{pkg.checksum}"] = Status::Operation.new(
label: pkg.name,
value: "Pending...",

View File

@@ -55,9 +55,9 @@ class W3DHub
create_directories(path)
file = File.open(path, "ab")
if (start_from_bytes > 0)
headers["Range"] = "bytes=#{start_from_bytes}-#{package.size}"
file = File.open(path, start_from_bytes.positive? ? "r+b" : "wb")
if (start_from_bytes.positive?)
headers["Range"] = "bytes=#{start_from_bytes}-"
file.pos = start_from_bytes
end

View File

@@ -5,6 +5,7 @@ class W3DHub
language: Gosu.user_languages.first.split("_").first,
app_install_dir: default_app_install_dir,
package_cache_dir: default_package_cache_dir,
parallel_downloads: 4,
wine_command: "wine",
create_wine_prefixes: true,
allow_diagnostic_reports: false,

View File

@@ -36,6 +36,7 @@ require_relative "lib/mixer"
require_relative "lib/application_manager"
require_relative "lib/application_manager/manifest"
require_relative "lib/application_manager/status"
require_relative "lib/application_manager/pool"
require_relative "lib/application_manager/task"
require_relative "lib/application_manager/tasks/installer"
require_relative "lib/application_manager/tasks/updater"