-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
stream: add Transform.by utility function (updated) #38696
Conversation
Analogous to Readable.from, Transform.by creates transform streams from async function generators
instead of allocating a new function for the Promise constructor per call to next (e.g. via for await) allocate once on init and reuse
Co-Authored-By: Vse Mozhet Byt <[email protected]>
Co-Authored-By: Anna Henningsen <[email protected]>
Co-Authored-By: Anna Henningsen <[email protected]>
Co-Authored-By: Vse Mozhet Byt <[email protected]>
Co-Authored-By: Anna Henningsen <[email protected]>
Co-Authored-By: Vse Mozhet Byt <[email protected]>
Co-Authored-By: Vse Mozhet Byt <[email protected]>
Co-Authored-By: Vse Mozhet Byt <[email protected]>
Co-Authored-By: Vse Mozhet Byt <[email protected]>
Co-authored-by: Rich Trott <[email protected]>
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.
To fix the linter errors
Co-authored-by: Antoine du Hamel <[email protected]>
Co-authored-by: Antoine du Hamel <[email protected]>
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.
lgtm
May I recommend a squash and force push? |
Sure, will do squash and push. Tho there is test failure here We can either remove the test if supporting it is not important, or if we want to support it I guess something like this will do the trick: Transform.by = function by(asyncGeneratorFn, options) {
let { promise, resolve } = createDeferredPromise();
const gen = (async function* () {
while (true) {
const { chunk, done, cb } = await promise;
process.nextTick(cb);
if (done) return;
yield chunk;
({ promise, resolve } = createDeferredPromise());
}
})();
Object.assign(gen, { encoding: undefined });
return from(Duplex, asyncGeneratorFn(gen), {
objectMode: true,
autoDestroy: true,
...options,
write: (chunk, encoding, cb) => {
Object.assign(gen, { encoding });
resolve({ chunk, done: false, cb });
},
final: (cb) => resolve({ done: true, cb }),
});
}; What's your thought? |
const readable = Readable.from('test'); | ||
async function * mapper(source) { | ||
for await (const chunk of source) { | ||
strictEqual(source.encoding, 'ascii'); |
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.
Would that fix the test failure?
strictEqual(source.encoding, 'ascii'); | |
strictEqual(chunk.encoding, 'ascii'); |
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 guess point of the test is to make encoding
of previous source stream available to the transformer, without transformer having to keep reference in some other ways. If we were to apply this change we might as well just remove the test.
lib/internal/streams/transform.js
Outdated
objectMode: true, | ||
autoDestroy: true, | ||
...options, | ||
write: (chunk, encoding, cb) => resolve({ chunk, done: false, cb }), |
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.
write: (chunk, encoding, cb) => resolve({ chunk, done: false, cb }), | |
write: (chunk, encoding, cb) => resolve({ chunk, encoding, done: false, cb }), |
how about this?
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 would just make encoding available here:
const { chunk, done, cb } = await promise;
|
||
const expected = ['T', 'E', 'S', 'T']; | ||
for await (const chunk of stream) { | ||
strictEqual(chunk, expected.shift()); |
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 this is failing:
python tools/test.py test/parallel/test-stream-transform-by.js
=== release test-stream-transform-by ===
Path: parallel/test-stream-transform-by
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
'TEST' !== 'T'
at Duplex.<anonymous> (/Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js:130:5)
at Duplex.emit (node:events:365:28)
at addChunk (node:internal/streams/readable:314:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Duplex.Readable.push (node:internal/streams/readable:228:10)
at next (node:internal/streams/from:98:31)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
generatedMessage: true,
code: 'ERR_ASSERTION',
actual: 'TEST',
expected: 'T',
operator: 'strictEqual'
}
Command: out/Release/node /Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js
[00:00|% 100|+ 0|- 1]: Done
I suspect this was working with the original implementation.
I'm really not sure that's the issue :/
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 test is wrong. If you want multiple chunks here you'd need to move from Readable.from('test')
to use an array or split it yourself in multiplie chunks.
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.
It's not just this but other tests are doing similar things. transformBy
, transformByFuncReturnsObjectWithSymbolAsyncIterator
to name a few (there are total 7 tests like this). And this tests are from the previous PR and I suspect It was passing there.
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.
We changed the behavior of Readable.from()
lately so that strings are not split char-by-char. This test must be changed.
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.
@safareli any updates?
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.
In the recent commit I've fixed some of the test errors but I'm still getting this which not sure how to fix and I gave up:
python tools/test.py test/parallel/test-stream-transform-by.js
[00:00|% 0|+ 0|- 0]: release test-stream-trans === release test-stream-transform-by ===
Path: parallel/test-stream-transform-by
Mismatched noop function calls. Expected exactly 1, actual 0.
at mustCall (/Users/safareli/dev/deepchannel/node/test/common/index.js:350:10)
at transformBySourceIteratorCompletes (/Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js:64:21)
at Object.<anonymous> (/Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js:240:3)
at Module._compile (node:internal/modules/cjs/loader:1109:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
at Module.load (node:internal/modules/cjs/loader:989:32)
at Function.Module._load (node:internal/modules/cjs/loader:829:14)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
at node:internal/main/run_main_module:17:47
Mismatched <anonymous> function calls. Expected exactly 1, actual 0.
at mustCall (/Users/safareli/dev/deepchannel/node/test/common/index.js:350:10)
at transformByOnErrorAndTryCatchAndDestroyed (/Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js:206:24)
at Object.<anonymous> (/Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js:247:3)
at Module._compile (node:internal/modules/cjs/loader:1109:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
at Module.load (node:internal/modules/cjs/loader:989:32)
at Function.Module._load (node:internal/modules/cjs/loader:829:14)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
at node:internal/main/run_main_module:17:47
Mismatched <anonymous> function calls. Expected exactly 1, actual 0.
at mustCall (/Users/safareli/dev/deepchannel/node/test/common/index.js:350:10)
at transformByThrowPriorToForAwait (/Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js:229:22)
at Object.<anonymous> (/Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js:248:3)
at Module._compile (node:internal/modules/cjs/loader:1109:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
at Module.load (node:internal/modules/cjs/loader:989:32)
at Function.Module._load (node:internal/modules/cjs/loader:829:14)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
at node:internal/main/run_main_module:17:47
Mismatched noop function calls. Expected exactly 1, actual 0.
at mustCall (/Users/safareli/dev/deepchannel/node/test/common/index.js:350:10)
at Object.<anonymous> (/Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js:249:9)
at Module._compile (node:internal/modules/cjs/loader:1109:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
at Module.load (node:internal/modules/cjs/loader:989:32)
at Function.Module._load (node:internal/modules/cjs/loader:829:14)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
at node:internal/main/run_main_module:17:47
Command: out/Release/node /Users/safareli/dev/deepchannel/node/test/parallel/test-stream-transform-by.js
[00:00|% 100|+ 0|- 1]: Done
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.
Assigning the encoding to the generator is not correct as the encoding could potentially change mid-way via setEncoding()
. The encoding needs to stay within each chunk. I hope my suggestions are enough to fix this issue.
looks like @sounisi5011 has similar lib stream-transform-from |
Yes, I created |
Unfortunately there is a conflict now, could you update the PR? |
Given the lack of progress here and that we landed |
Updated #28501