diff --git a/lib/api.rb b/lib/api.rb index 9a86f2f..6ffe5be 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -11,7 +11,6 @@ class W3DHub #! === W3D Hub API === !# ENDPOINT = "https://secure.w3dhub.com".freeze - # W3DHUB_API_CONNECTION = Excon.new(ENDPOINT, persistent: true, connect_timeout: 15, tcp_nodelay: true) # Method: POST # FORMAT: JSON @@ -151,7 +150,6 @@ class W3DHub #! === Server List API === !# SERVER_LIST_ENDPOINT = "https://gsh.w3dhub.com".freeze - # SERVER_LIST_CONNECTION = Excon.new(SERVER_LIST_ENDPOINT, persistent: true, connect_timeout: 15, tcp_nodelay: true) # Method: GET # FORMAT: JSON diff --git a/lib/application_manager/task.rb b/lib/application_manager/task.rb index 38d20ee..7e27796 100644 --- a/lib/application_manager/task.rb +++ b/lib/application_manager/task.rb @@ -473,9 +473,6 @@ class W3DHub internet = Async::HTTP::Internet.instance Api.package(internet, package) do |chunk, remaining_bytes, total_bytes| - # Store progress somewhere - # Kernel.puts "#{name}-#{version}: #{(remaining_bytes.to_f / total_bytes).round}%" - block&.call(chunk, remaining_bytes, total_bytes) end end diff --git a/lib/cache.rb b/lib/cache.rb index 13dcdd1..1d57b63 100644 --- a/lib/cache.rb +++ b/lib/cache.rb @@ -46,39 +46,58 @@ class W3DHub # Download a W3D Hub package def self.fetch_package(internet, package, block) path = package_path(package.category, package.subcategory, package.name, package.version) - headers = { "Content-Type": "application/x-www-form-urlencoded" } start_from_bytes = package.custom_partially_valid_at_bytes puts " Start from bytes: #{start_from_bytes}" create_directories(path) - 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 + offset = start_from_bytes + parts = [] + chunk_size = 4_000_000 + workers = 4 + + file = File.open(path, offset.positive? ? "r+b" : "wb") + + amount_written = 0 + + while (offset < package.size) + byte_range_start = offset + byte_range_end = [offset + chunk_size, package.size].min + parts << (byte_range_start...byte_range_end) + + offset += chunk_size end - streamer = lambda do |chunk, remaining_bytes, total_bytes| - file.write(chunk) + semaphore = Async::Semaphore.new(workers) + barrier = Async::Barrier.new(parent: semaphore) - block.call(chunk, remaining_bytes, total_bytes) - puts " Remaining: #{((remaining_bytes.to_f / total_bytes) * 100.0).round}% (#{W3DHub::format_size(total_bytes - remaining_bytes)} / #{W3DHub::format_size(total_bytes)})" + while !parts.empty? + barrier.async do + part = parts.shift + + range_header = [["range", "bytes=#{part.min}-#{part.max}"]] + + body = "data=#{JSON.dump({ category: package.category, subcategory: package.subcategory, name: package.name, version: package.version })}" + response = internet.post("#{Api::ENDPOINT}/apis/launcher/1/get-package", W3DHub::Api::FORM_ENCODED_HEADERS + range_header, body) + + if response.success? + chunk = response.read + written = file.pwrite(chunk, part.min) + + amount_written += written + remaining_bytes = package.size - amount_written + total_bytes = package.size + + block.call(chunk, remaining_bytes, total_bytes) + # puts " Remaining: #{((remaining_bytes.to_f / total_bytes) * 100.0).round}% (#{W3DHub::format_size(total_bytes - remaining_bytes)} / #{W3DHub::format_size(total_bytes)})" + end + end + + barrier.wait end - - # Create a new connection due to some weirdness somewhere in Excon - response = Excon.post( - "#{Api::ENDPOINT}/apis/launcher/1/get-package", - tcp_nodelay: true, - headers: Api::DEFAULT_HEADERS.merge(headers), - body: "data=#{JSON.dump({ category: package.category, subcategory: package.subcategory, name: package.name, version: package.version })}", - chunk_size: 4_000_000, - response_block: streamer - ) - - file.close - - response.status == 200 || response.status == 206 + ensure + file&.close end end end diff --git a/w3d_hub_linux_launcher.rb b/w3d_hub_linux_launcher.rb index 5a6e777..6b14fc7 100644 --- a/w3d_hub_linux_launcher.rb +++ b/w3d_hub_linux_launcher.rb @@ -77,4 +77,6 @@ require_relative "lib/pages/download_manager" Async do W3DHub::Window.new(width: 980, height: 720, borderless: false).show + + raise Async::Stop # ensure reactor is shutdown when window is closed end