class Google::Apis::Core::DownloadCommand

@private Streaming/resumable media download support

Public Instance Methods

execute_once_with_response(client, &block) click to toggle source

Returns a two-element array containing:

* The `result` that is the usual return type of #execute_once.
* The `http_resp`.
# File lib/google/cloud/storage/service.rb, line 873
def execute_once_with_response(client, &block)
  request_header = header.dup
  apply_request_options(request_header)
  download_offset = nil

  if @offset > 0
    logger.debug { sprintf('Resuming download from offset %d', @offset) }
    request_header[RANGE_HEADER] = sprintf('bytes=%d-', @offset)
  end

  http_res = client.get(url.to_s,
             query: query,
             header: request_header,
             follow_redirect: true) do |res, chunk|
    status = res.http_header.status_code.to_i
    next unless OK_STATUS.include?(status)

    download_offset ||= (status == 206 ? @offset : 0)
    download_offset  += chunk.bytesize

    if download_offset - chunk.bytesize == @offset
      next_chunk = chunk
    else
      # Oh no! Requested a chunk, but received the entire content
      chunk_index = @offset - (download_offset - chunk.bytesize)
      next_chunk = chunk.byteslice(chunk_index..-1)
      next if next_chunk.nil?
    end
    # logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
    @download_io.write(next_chunk)

    @offset += next_chunk.bytesize
  end

  @download_io.flush

  if @close_io_on_finish
    result = nil
  else
    result = @download_io
  end
  check_status(http_res.status.to_i, http_res.header, http_res.body)
  success([result, http_res], &block)
rescue => e
  @download_io.flush
  error(e, rethrow: true, &block)
end
execute_with_response(client) { |result, nil| ... } click to toggle source

Returns a two-element array containing:

* The `result` that is the usual return type of #execute.
* The `http_resp` from #execute_once.
# File lib/google/cloud/storage/service.rb, line 838
def execute_with_response(client)
  prepare!
  begin
    Retriable.retriable tries: options.retries + 1,
                        base_interval: 1,
                        multiplier: 2,
                        on: RETRIABLE_ERRORS do |try|
      # This 2nd level retriable only catches auth errors, and supports 1 retry, which allows
      # auth to be re-attempted without having to retry all sorts of other failures like
      # NotFound, etc
      auth_tries = (try == 1 && authorization_refreshable? ? 2 : 1)
      Retriable.retriable tries: auth_tries,
                          on: [Google::Apis::AuthorizationError, Signet::AuthorizationError],
                          on_retry: proc { |*| refresh_authorization } do
        execute_once_with_response(client).tap do |result|
          if block_given?
            yield result, nil
          end
        end
      end
    end
  rescue => e
    if block_given?
      yield nil, e
    else
      raise e
    end
  end
ensure
  release!
end