-
Notifications
You must be signed in to change notification settings - Fork 30.2k
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
fs: readFile function adds the chunkSize option #41647
base: main
Are you sure you want to change the base?
Conversation
doc/api/fs.md
Outdated
@@ -3205,11 +3205,15 @@ changes: | |||
* `encoding` {string|null} **Default:** `null` | |||
* `flag` {string} See [support of file system `flags`][]. **Default:** `'r'`. | |||
* `signal` {AbortSignal} allows aborting an in-progress readFile | |||
* `kPerRead` {integer} The number of kb per read, -1 means no limit. |
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 options are in alphabetical order. Let's keep them that way by moving this up one line.
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.
* `kPerRead` {integer} The number of kb per read, -1 means no limit. | |
* `kPerRead` {integer} The number of KB per read. Use `-1` for no limit. |
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.
Is there a reason why we're using kilobytes instead of just bytes? Using the latter is more sensible and more flexible IMO.
Also, I think a name like chunkSize
or similar would be a better name, especially since the /^k[A-Z]/
prefix is used internally in code for private/internal field/symbol names.
This will need tests. |
lib/internal/fs/utils.js
Outdated
|
||
if (defaultOptions.kPerRead) { | ||
if (options.kPerRead === undefined) { | ||
options.kPerRead = defaultOptions.kPerRead; |
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.
Isn't this mutating the end user's options
object?
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 I mean by this is that I believe options
is the object passed in by the user. We shouldn't overwrite/set values on the object they pass in. AFAICT the only time options
is not an end user's object is when they don't supply one.
Co-authored-by: Mohammed Keyvanzadeh <[email protected]>
I've solved the alphabetical order problem @Trott
I didn't catch your meaning maybe I need an example |
I think using bytes would make it more consistent with other storage-based input values used in node core. For example: If someone wants to use something less than 1KB, they have to use awkward fractional values and even then because of the floating point representation they might not be able to get the exact value they want.
The value currently being used ( |
Okay, I'll change it to byte later |
It looks like the absence of a period would cause the |
doc/api/fs.md
Outdated
@@ -3202,6 +3202,8 @@ changes: | |||
|
|||
* `path` {string|Buffer|URL|integer} filename or file descriptor | |||
* `options` {Object|string} | |||
* `bPerRead` {integer} The number of bytes per read. Use `-1` for no limit. |
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.
s/bPerRead/chunkSize
@mawaregetsuka are you still interested to implement this? Can you address the comments above regarding the name of the option please? Lines 3315 to 3320 in 80bfb9b
|
Sure,I'll finish it as soon as possible |
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 think we would need a test for this new option.
Also, could you please rebase to avoid the merge commit? Merge commits tend to break our tooling unfortunately. Let me know if you need help for that.
@aduh95 |
To be clear, it doesn't have to be every time, it's only need when fixing a git conflict.
I'm sure we do :) if we add a feature with no tests, we cannot guarantee it will still be working next time we change something in the source code (which happens often in a project the size of Node.js). Let us know if you need help writing the tests of course. |
This is my first time writing tests for nodejs and I'd love to get some suggestions. |
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.
A few suggestions to improve the testing. Should we add a similar option to fs.promises.readFile
?
test/parallel/test-fs-readfile.js
Outdated
for (const e of fileInfo) { | ||
fs.readFile(e.name, { chunkSize: e.chunkSize }, | ||
common.mustCall((err, buf) => { | ||
assert.deepStrictEqual(buf, e.contents); | ||
})); | ||
} |
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.
First I think we want to make sure invalid values are not silently ignored, but is raising a useful error. Then we want to make sure the file is read as expected for valid values of chunkSize
:
for (const e of fileInfo) { | |
fs.readFile(e.name, { chunkSize: e.chunkSize }, | |
common.mustCall((err, buf) => { | |
assert.deepStrictEqual(buf, e.contents); | |
})); | |
} | |
['', Symbol(), () => {}, 1n, true, false, [], {}].forEach((chunkSize) => { | |
assert.throws( | |
() => fs.readFile(fileInfo[0].name, { chunkSize }, common.mustNotCall()), | |
{ code: 'ERR_INVALID_ARG_TYPE' } | |
); | |
}); | |
[-1, 0, -Infinity, Infinity, NaN].forEach((chunkSize) => { | |
assert.throws( | |
() => fs.readFile(fileInfo[0].name, { chunkSize }, common.mustNotCall()), | |
{ code: 'ERR_INVALID_RANGE' } | |
); | |
}); | |
[null, undefined, 1, 64, Number.MAX_SAFE_INTEGER].forEach((chunkSize) => { | |
fs.readFile(fileInfo[0].name, { chunkSize: e.chunkSize }, | |
common.mustSucceed((buf) => { | |
assert.deepStrictEqual(buf, fileInfo[0].contents); | |
})); | |
}); |
test/parallel/test-fs-readfile.js
Outdated
{ name: path.join(tmpdir.path, `${prefix}-1K.txt`), | ||
len: 1024 }, | ||
len: 1024, chunkSize: 64 }, | ||
{ name: path.join(tmpdir.path, `${prefix}-64K.txt`), | ||
len: 64 * 1024 }, | ||
len: 64 * 1024, chunkSize: -64 }, | ||
{ name: path.join(tmpdir.path, `${prefix}-64KLessOne.txt`), | ||
len: (64 * 1024) - 1 }, | ||
len: (64 * 1024) - 1, chunkSize: 'string' }, | ||
{ name: path.join(tmpdir.path, `${prefix}-1M.txt`), | ||
len: 1 * 1024 * 1024 }, | ||
len: 1 * 1024 * 1024, chunkSize: 0 }, | ||
{ name: path.join(tmpdir.path, `${prefix}-1MPlusOne.txt`), | ||
len: (1 * 1024 * 1024) + 1 }, | ||
len: (1 * 1024 * 1024) + 1, chunkSize: -1 }, |
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 suggest reverting those changes.
I've improved the tests but there are still a few problems |
@nodejs/fs |
According to the discussion in pr 41436 adding a configurable parameter is probably the best solution