-
Notifications
You must be signed in to change notification settings - Fork 373
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
feat: MPU for transfer manager #2192
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very exciting! Just had some initial thoughts/questions...
}); | ||
for await (const curChunk of readStream) { | ||
if (promises.length >= maxQueueSize) { | ||
await Promise.all(promises); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does this do? Execute all the parts? Should this get returned to the caller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is similar to the changes I made for deleteFiles
. p-limit
only constrains the number of running promises, not the number of promises being held in memory. I added a queue here such that if a user is uploading a large file we aren't attempting to hold all those chunks in memory at once. By default we will only hold the same number of chunks in memory as the number of executing promises.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Maybe add a comment to make it more clear?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment to explain the logic.
src/transfer-manager.ts
Outdated
); | ||
} | ||
await Promise.all(promises); | ||
await mpuHelper.completeUpload(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the return statement here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return is of type Promise<void>
in the success case there is no return value to the user. If something goes wrong we throw an exception with the error, uploadId, and mapping of completed parts that were uploaded. This allows the user to call again supplying the uploadId and parts so that we may resume from where the failure occurred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see. Is there no value in returning the response from complete upload?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will change it to return the full response just to be inline with the raw API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now returns Promise<GaxiosResponse | undefined>
. The GaxiosResponse is the full API response.
* @private | ||
* @experimental | ||
*/ | ||
class XMLMultiPartUploadHelper implements MultiPartUploadHelper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this go in a separate file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can move this to a separate file the only problem is I will have to export it which means a user can potentially come along and import it and use it directly. I was attempting to avoid that situation. Depends what people think and whether or not we are ok with saying "don't use this directly".
* | ||
* @returns {Promise<TestResult>} A promise that resolves containing information about the test results. | ||
*/ | ||
async function performDownloadFileInChunksTest(): Promise<TestResult> { | ||
async function performChunkUploadDownloadTest(): Promise<TestResult[]> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whats the reasoning for combining these? Simplicity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Workload 8 is supposed to be upload and download test so I combined them.
import {CRC32C} from './crc32c'; | ||
import {GoogleAuth} from 'google-auth-library'; | ||
import {XMLParser, XMLBuilder} from 'fast-xml-parser'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add to package JSON? It would be interesting to see the level of effort for adding this to one of our shared libs (gaxios?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added it: /~https://github.com/googleapis/nodejs-storage/pull/2192/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519R62. I'm sure we could write something ourselves. I figured since this was a one off usage of the XML API it probably wasn't worth doing ourselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good. One question on returning the response of complete upload
}); | ||
for await (const curChunk of readStream) { | ||
if (promises.length >= maxQueueSize) { | ||
await Promise.all(promises); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Maybe add a comment to make it more clear?
src/transfer-manager.ts
Outdated
); | ||
} | ||
await Promise.all(promises); | ||
await mpuHelper.completeUpload(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see. Is there no value in returning the response from complete upload?
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
Fixes #<issue_number_goes_here> 🦕