Skip to content

Differential download must fail after 10 seconds #9063

@Mn4CaO5

Description

@Mn4CaO5

When useMultipleRangeRequest is true, differential download must fail after 10 seconds.

DifferentialDownloader.ts:

private async doDownloadFile(tasks: Array<Operation>, fdList: Array<OpenedFile>): Promise<any> {
    ...

    await new Promise((resolve, reject) => {
      let w: any
      if (this.options.isUseMultipleRangeRequest) {
        w = executeTasksUsingMultipleRangeRequests(this, tasks, firstStream, oldFileFd, reject)
        w(0)
        return
      }

      ...
   })
  }

multipleRangeDownloader.ts:

export function executeTasksUsingMultipleRangeRequests(
  differentialDownloader: DifferentialDownloader,
  tasks: Array<Operation>,
  out: Writable,
  oldFileFd: number,
  reject: (error: Error) => void
): (taskOffset: number) => void {
  const w = (taskOffset: number): void => {
     ...

    const nextOffset = taskOffset + 1000
    doExecuteTasks(
      differentialDownloader,
      {
        tasks,
        start: taskOffset,
        end: Math.min(tasks.length, nextOffset),
        oldFileFd,
      },
      out,
      () => w(nextOffset),
      reject
    )
  }
  return w
}

function doExecuteTasks(differentialDownloader: DifferentialDownloader, options: PartListDataTask, out: Writable, resolve: () => void, reject: (error: Error) => void): void {
  ...

  const requestOptions = differentialDownloader.createRequestOptions()
  requestOptions.headers!.Range = ranges.substring(0, ranges.length - 2)
  const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {
    if (!checkIsRangesSupported(response, reject)) {
      return
    }

    const contentType = safeGetHeader(response, "content-type")
    const m = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i.exec(contentType)
    if (m == null) {
      reject(new Error(`Content-Type "multipart/byteranges" is expected, but got "${contentType}"`))
      return
    }

    const dicer = new DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve)
    dicer.on("error", reject)
    response.pipe(dicer)

    response.on("end", () => {
      setTimeout(() => {
        request.abort()
        reject(new Error("Response ends without calling any handlers"))
      }, 10000) <-- The timer isn't canceled after data processing is completed.
    })
  })
  differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)
  request.end()
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions