Skip to content

stream: add Transform.by utility function (updated) - #38696

Closed
safareli wants to merge 43 commits into
nodejs:masterfrom
safareli:transform-by
Closed

stream: add Transform.by utility function (updated)#38696
safareli wants to merge 43 commits into
nodejs:masterfrom
safareli:transform-by

Conversation

@safareli

Copy link
Copy Markdown

Updated #28501

David Mark Clementsand others added 26 commits December 16, 2019 12:00
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 <vsemozhetbyt@gmail.com>
Co-Authored-By: Anna Henningsen <github@addaleax.net>
Co-Authored-By: Anna Henningsen <github@addaleax.net>
Co-Authored-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Co-Authored-By: Anna Henningsen <github@addaleax.net>
Co-Authored-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Co-Authored-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Co-Authored-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Co-Authored-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
@github-actionsgithub-actionsBot added doc Issues and PRs related to the documentations. errors Issues and PRs related to JavaScript errors originated in Node.js core. needs-ci PRs that need a full CI run. stream Issues and PRs related to the stream subsystem. labels May 15, 2021
Co-authored-by: Rich Trott <rtrott@gmail.com>
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Comment threaddoc/api/stream.md
Comment threadlib/internal/streams/transform.js Outdated
Comment threadlib/internal/streams/transform.js Outdated
Comment threadlib/internal/streams/transform.js Outdated
Comment threadlib/internal/streams/transform.js Outdated
Comment threadlib/internal/streams/transform.js Outdated
Comment threadlib/internal/streams/transform.js
Comment threaddoc/api/stream.md Outdated

@aduh95aduh95 left a comment

Copy link
Copy Markdown
Contributor

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

Comment threadlib/internal/streams/transform.js Outdated
Comment threadlib/internal/streams/transform.js Outdated
safareliand others added 2 commits June 6, 2021 17:04
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>

@mcollinamcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@mcollina

Copy link
Copy Markdown
Member

May I recommend a squash and force push?

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@safareli

Copy link
Copy Markdown
Author

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=functionby(asyncGeneratorFn,options){let{ promise, resolve }=createDeferredPromise();constgen=(asyncfunction*(){while(true){const{ chunk, done, cb }=awaitpromise;process.nextTick(cb);if(done)return;yieldchunk;({ promise, resolve }=createDeferredPromise());}})();Object.assign(gen,{encoding: undefined});returnfrom(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');

Copy link
Copy Markdown
Contributor

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?

Suggested change
strictEqual(source.encoding,'ascii');
strictEqual(chunk.encoding,'ascii');

Copy link
Copy Markdown
Author

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.

Comment threadlib/internal/streams/transform.js Outdated
objectMode: true,
autoDestroy: true,
...options,
write: (chunk, encoding, cb) => resolve({ chunk, done: false, cb }),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
write: (chunk,encoding,cb)=>resolve({ chunk,done: false, cb }),
write: (chunk,encoding,cb)=>resolve({ chunk,encoding,done: false, cb }),

how about this?

Copy link
Copy Markdown
Author

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 }=awaitpromise;


const expected = ['T', 'E', 'S', 'T'];
for await (const chunk of stream) {
strictEqual(chunk, expected.shift());

Copy link
Copy Markdown
Author

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 :/

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Author

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.

Copy link
Copy Markdown
Member

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@safareli any updates?

Copy link
Copy Markdown
Author

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

@mcollinamcollina added notable-change PRs with changes that should be highlighted in changelogs. semver-minor PRs that contain new features and should be released in the next minor version. labels Jun 9, 2021

@mcollinamcollina left a comment

Copy link
Copy Markdown
Member

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.

Comment threadlib/internal/streams/transform.js Outdated
Comment threadlib/internal/streams/transform.js Outdated
Comment threadlib/internal/streams/transform.js Outdated
@safareli

safareli commented Jun 9, 2021

Copy link
Copy Markdown
Author

looks like @sounisi5011 has similar lib stream-transform-from

@sounisi5011

sounisi5011 commented Jun 9, 2021

Copy link
Copy Markdown

looks like @sounisi5011 has similar lib stream-transform-from
#38696 (comment)

Yes, I created @sounisi5011/stream-transform-from because streams.Transform.from() did not exist in Node.js. However, if this will be built into Node.js, I would welcome it.

Comment threadlib/internal/streams/transform.js
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@mcollina

Copy link
Copy Markdown
Member

Unfortunately there is a conflict now, could you update the PR?

@mcollinamcollina mentioned this pull request Jul 1, 2021
@ronag

ronag commented Jan 3, 2022

Copy link
Copy Markdown
Member

Given the lack of progress here and that we landed stream.compose and Duplex.from which basically does this already I believe we can close this.

@ronagronag closed this Jan 3, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docIssues and PRs related to the documentations.errorsIssues and PRs related to JavaScript errors originated in Node.js core.needs-ciPRs that need a full CI run.notable-changePRs with changes that should be highlighted in changelogs.semver-minorPRs that contain new features and should be released in the next minor version.streamIssues and PRs related to the stream subsystem.toolsIssues and PRs related to the tools directory.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

11 participants

@safareli@nodejs-github-bot@ronag@mcollina@sounisi5011@thefourtheye@Trott@aymen94@aduh95@RaisinTen@davidmarkclements