Skip to content

stream: add Transform.by utility function - #28501

Closed
davidmarkclements wants to merge 26 commits into
nodejs:masterfrom
davidmarkclements:transform-by
Closed

stream: add Transform.by utility function#28501
davidmarkclements wants to merge 26 commits into
nodejs:masterfrom
davidmarkclements:transform-by

Conversation

@davidmarkclements

@davidmarkclementsdavidmarkclements commented Jul 1, 2019

Copy link
Copy Markdown
Member

Analogous to Readable.from, Transform.by creates transform streams
from async function generators.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@nodejs-github-botnodejs-github-bot added doc Issues and PRs related to the documentations. stream Issues and PRs related to the stream subsystem. tools Issues and PRs related to the tools directory. labels Jul 1, 2019
@davidmarkclements
davidmarkclementsforce-pushed the transform-by branch 6 times, most recently from 52dc5bd to e85b78dCompareJuly 1, 2019 21:35
@davidmarkclements

davidmarkclements commented Jul 1, 2019

Copy link
Copy Markdown
MemberAuthor
edit: tests passed on a subsequent run (which was a docs fix), guessing its infrastructure failure the two failing JS tests seem to be failing due to being run against a binary that doesn't have the compiled changes in... maybe it's a caching thing?

Comment threadlib/_stream_transform.js Outdated
Comment threadlib/internal/streams/async_iterator.js Outdated
Comment threadtools/doc/type-parser.js Outdated
@mcollina

Copy link
Copy Markdown
Member

Should we ship this as experimental to start?

Comment threaddoc/api/stream.md Outdated
Comment threaddoc/api/stream.md Outdated
Comment threadtools/doc/type-parser.js Outdated
Comment threaddoc/api/stream.md Outdated
Comment threaddoc/api/stream.md Outdated
@addaleaxaddaleax added semver-minor PRs that contain new features and should be released in the next minor version. and removed doc Issues and PRs related to the documentations. tools Issues and PRs related to the tools directory. labels Jul 2, 2019
Comment threaddoc/api/stream.md Outdated
Comment threaddoc/api/stream.md Outdated
Comment threadlib/_stream_transform.js Outdated
Comment threadlib/_stream_transform.js Outdated
Comment threadlib/_stream_transform.js Outdated
Comment threadlib/_stream_transform.js Outdated
Comment threadlib/_stream_transform.js Outdated
Comment threadlib/_stream_transform.js Outdated
Comment threadlib/_stream_transform.js Outdated
@devsnek

Copy link
Copy Markdown
Member

given that https://github.com/tc39/proposal-iterator-helpers is likely to hit stage 2 at the end of this month, and would allow something looking like this:

someReadable[Symbol.asyncIterator]().map(async(x)=>{whatever}).forEach((item)=>writable.push(item));

perhaps instead of adding this api we should just wait for the iterator methods to mature?

@mcollina

Copy link
Copy Markdown
Member

@devsnek I think the two requirements are orthogonal. This PR is all about enabling async iterators and async functions to "play decently" with the Stream ecosystem of modules. In other term, it enables to "use await safely in a transform stream".

The added support for the iterator helpers are needed to improve the language overall, but they won't help in improving the Stream ecosystem.


given that https://github.com/tc39/proposal-iterator-helpers is likely to hit stage 2 at the end of this month, and would allow something looking like this:

As a side note, I don't see anything specific to asyncIterator in that repo, and it's not clear to me how we would avoid a file descriptor leak in case the the "map" step blows up.

@devsnek

devsnek commented Jul 4, 2019

Copy link
Copy Markdown
Member

@mcollina if that is the case this should probably accept any function. (stream) => stream[Symbol.asyncIterator]().map().filter().etc() should be a valid input.

(also, all the methods being added for sync iterables are also being added for async iterables, and they propogate errors to the end of the chain)

@ronag

ronag commented Dec 16, 2019

Copy link
Copy Markdown
Member

@davidmarkclements: When I try to run this locally the test never finishes:

out/Release/node test/parallel/test-transform-by.js

@ronag

Copy link
Copy Markdown
Member

This probably got broken by f8018f2

This was referenced Dec 16, 2019

@ronagronag 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.

I believe this can be implemented in just a few lines using Readble.from, e.g. nxtedition#12. Passes all tests expect for a few ones I'm not sure are needed (e.g. invalid arg type checks should probably be moved into from).

constfrom=require('internal/streams/from');Transform.by=functionby(asyncGeneratorFn,opts){let_resolve;let_promise=newPromise((resolve)=>_resolve=resolve);returnfrom(Duplex,asyncGeneratorFn(asyncfunction*(){while(true){const{ chunk, done, cb }=await_promise;if(done)returncb();yieldchunk;_promise=newPromise((resolve)=>_resolve=resolve);cb();}}()),{objectMode: true,autoDestroy: true,
...opts,write: (chunk,encoding,cb)=>_resolve({ chunk,done: false, cb }),final: (cb)=>_resolve({done: true, cb })});};

@ronag

Copy link
Copy Markdown
Member

Any reason why this is not simply called Transform.from similar to Readable.from?

@davidmarkclements

Copy link
Copy Markdown
MemberAuthor

Any reason why this is not simply called Transform.from similar to Readable.from?

The from to me is more analogous to libraries like from2 - as in we're creating a source stream. So Transform.by is analogous to through2 - it's creating a through stream. We could do Transform.through, but the API symmetry I'm going for is:

  • Readable.from
  • Transform.by
  • Writable.to

@davidmarkclements

davidmarkclements commented Dec 17, 2019

Copy link
Copy Markdown
MemberAuthor

I believe this can be implemented in just a few lines using Readable.from

very cool - I noticed some tests were commented out. I think the one for encoding in particular needs to be supported. Can you speak more to why the others are commented out?

The checks for whether an async function generator is being passed were added at the request of prior reviews, I'd rather honour those initial requests than vacillate on that.

Also, I'd be interested in the performance impact of each approach.

@ronag

ronag commented Dec 17, 2019

Copy link
Copy Markdown
Member

think the one for encoding in particular needs to be supported.

I need to better understand this one. I'll follow up with your comment on the PR.

The checks for whether an async function generator is being passed were added at the request of prior reviews, I'd rather honour those initial requests than vacillate on that.

I agree with them. But I think they should be consistent with and live in Readable.from? Possibly a separate PR? i.e. it's not that we should not have these type checks, just that I think they should live somewhere else.

Also, I'd be interested in the performance impact of each approach.

Maybe a benchmark under /benchmark then?

@ronag

ronag commented Dec 17, 2019

Copy link
Copy Markdown
Member

Also, I'd be interested in the performance impact of each approach.

I made a benchmark but it doesn't work with the version in this PR for some reason? nxtedition@9fbb8d4

@ronag

Copy link
Copy Markdown
Member

I'm not sure what the best course of action here is. @davidmarkclements would you be interested in cherry-picking my proposed changes into this PR?

@ronag

ronag commented Feb 9, 2020

Copy link
Copy Markdown
Member

@mcollina: Is this something we still want considering the recent added functionality in pipeline regarding generators?

@mcollina

Copy link
Copy Markdown
Member

I would say so, IMHO it serves a different purpose.

@ronag

ronag commented Feb 9, 2020

Copy link
Copy Markdown
Member

@davidmarkclements are you still interested in continuing work on this PR or would you mind if I took over?

@BridgeAR
BridgeARforce-pushed the master branch 2 times, most recently from 8ae28ff to 2935f72CompareMay 31, 2020 12:19
@jasnell

Copy link
Copy Markdown
Member

Ping @davidmarkclements ... still want to do this?

@jasnelljasnell added the stalled Issues and PRs that are stalled. label Jul 7, 2020
@davidmarkclements

Copy link
Copy Markdown
MemberAuthor

@jasnell I've just remembered I was doing this, can we get it in before v14 goes to Active?

@mcollina

Copy link
Copy Markdown
Member

Yes we can!

@aduh95aduh95 removed the stalled Issues and PRs that are stalled. label Oct 19, 2020
@aduh95
aduh95 marked this pull request as draft October 19, 2020 17:38
@safareli

Copy link
Copy Markdown

Hi, this looks super nice!

Is there any plans to get this merged at some point?

@mcollina

Copy link
Copy Markdown
Member

@safareli would you like to work on it? I think it just requires somebody willing to update this and do a fresh PR. I don't think @davidmarkclements will work on this.

@safareli

Copy link
Copy Markdown

@mcollina I've open #38696

@ronag

ronag commented Jul 8, 2021

Copy link
Copy Markdown
Member

Closing in favor of #38696

@ronagronag closed this Jul 8, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver-minorPRs that contain new features and should be released in the next minor version.streamIssues and PRs related to the stream subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

12 participants

@davidmarkclements@mcollina@devsnek@vsemozhetbyt@nodejs-github-bot@ronag@jasnell@safareli@sam-github@addaleax@targos@aduh95