Skip to content

feat: parallel chunkedUpload in web and node #1146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

ChiragAgg5k
Copy link
Member

@ChiragAgg5k ChiragAgg5k commented Aug 10, 2025

What does this PR do?

upgrade the chunkedUpload method to do parallel chunking

Test Plan

duration:
image

throughput:
image

Related PRs and Issues

Have you read the Contributing Guidelines on issues?

yes.

@ChiragAgg5k ChiragAgg5k requested a review from Copilot August 10, 2025 12:38
Copilot

This comment was marked as outdated.

@ChiragAgg5k ChiragAgg5k requested a review from Copilot August 10, 2025 13:11
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR upgrades the chunked upload functionality to support parallel chunk uploads instead of sequential uploads, improving performance for large file uploads in both web and Node.js environments.

Key changes:

  • Introduces parallel chunk processing with configurable concurrency (MAX_CONCURRENCY = 6)
  • Replaces sequential while loop with batch processing using Promise.all
  • Adds proper error handling and progress tracking for parallel uploads

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
templates/web/src/client.ts.twig Implements parallel chunked upload with batch processing and error handling for web client
templates/node/src/client.ts.twig Implements identical parallel chunked upload functionality for Node.js client

@@ -296,6 +296,7 @@ class {{spec.title | caseUcfirst}}Exception extends Error {
*/
class Client {
static CHUNK_SIZE = 1024 * 1024 * 5;
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MAX_CONCURRENCY constant lacks documentation explaining why 6 was chosen as the default value and how it affects performance or server load.

Suggested change
static CHUNK_SIZE = 1024 * 1024 * 5;
static CHUNK_SIZE = 1024 * 1024 * 5;
/**
* The maximum number of concurrent requests allowed.
*
* The default value of 6 is chosen as a balance between maximizing throughput
* and minimizing server load or rate-limiting issues. Increasing this value
* may improve performance for high-bandwidth clients or servers, but can
* also lead to higher resource usage and potential throttling by the server.
* Decreasing it can reduce load but may slow down operations that require
* multiple concurrent requests (such as multipart uploads).
*/

Copilot uses AI. Check for mistakes.

const firstResponse = await this.call(method, url, firstChunkHeaders, firstPayload);

if (!firstResponse?.$id) {
throw new Error('First chunk upload failed - no ID returned');
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message 'First chunk upload failed - no ID returned' could be more helpful by including the actual response or HTTP status code to aid debugging.

Suggested change
throw new Error('First chunk upload failed - no ID returned');
throw new Error(
`First chunk upload failed - no ID returned. Response: ${JSON.stringify(firstResponse)}`
);

Copilot uses AI. Check for mistakes.

});
const failures = batchResults.filter(result => !result.success);
if (failures.length > 0) {
const errorMessages = failures.map(f => `Chunk ${f.chunkInfo.index}: ${f.error}`);
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error object is being directly concatenated to a string, which may not provide meaningful error information. Consider using f.error.message || f.error.toString() for better error reporting.

Suggested change
const errorMessages = failures.map(f => `Chunk ${f.chunkInfo.index}: ${f.error}`);
const errorMessages = failures.map(f => `Chunk ${f.chunkInfo.index}: ${f.error && (f.error.message || f.error.toString())}`);

Copilot uses AI. Check for mistakes.

@@ -67,6 +67,7 @@ function getUserAgent() {

class Client {
static CHUNK_SIZE = 1024 * 1024 * 5;
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MAX_CONCURRENCY constant lacks documentation explaining why 6 was chosen as the default value and how it affects performance or server load.

Suggested change
static CHUNK_SIZE = 1024 * 1024 * 5;
static CHUNK_SIZE = 1024 * 1024 * 5;
/**
* The maximum number of concurrent upload or network operations.
*
* The default value of 6 is chosen as a conservative balance between
* maximizing throughput and avoiding excessive server or client resource usage.
* Increasing this value may improve performance on high-bandwidth or high-CPU environments,
* but can also increase server load and risk rate limiting or throttling.
* Adjust as needed based on your application's requirements and server capabilities.
*/

Copilot uses AI. Check for mistakes.

const firstResponse = await this.call(method, url, firstChunkHeaders, firstPayload);

if (!firstResponse?.$id) {
throw new Error('First chunk upload failed - no ID returned');
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message 'First chunk upload failed - no ID returned' could be more helpful by including the actual response or HTTP status code to aid debugging.

Suggested change
throw new Error('First chunk upload failed - no ID returned');
throw new Error(
`First chunk upload failed - no ID returned. Response: ${JSON.stringify(firstResponse)}`
);

Copilot uses AI. Check for mistakes.


const failures = batchResults.filter(result => !result.success);
if (failures.length > 0) {
const errorMessages = failures.map(f => `Chunk ${f.chunkInfo.index}: ${f.error}`);
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error object is being directly concatenated to a string, which may not provide meaningful error information. Consider using f.error.message || f.error.toString() for better error reporting.

Suggested change
const errorMessages = failures.map(f => `Chunk ${f.chunkInfo.index}: ${f.error}`);
const errorMessages = failures.map(f => `Chunk ${f.chunkInfo.index}: ${f.error?.message || f.error?.toString()}`);

Copilot uses AI. Check for mistakes.

@ChiragAgg5k ChiragAgg5k marked this pull request as draft August 11, 2025 05:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant