Skip to content
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 #28501

Closed
wants to merge 26 commits into from

Conversation

davidmarkclements
Copy link
Member

@davidmarkclements davidmarkclements commented Jul 1, 2019

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-bot nodejs-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 davidmarkclements force-pushed the transform-by branch 6 times, most recently from 52dc5bd to e85b78d Compare July 1, 2019 21:35
@davidmarkclements
Copy link
Member Author

davidmarkclements commented Jul 1, 2019

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?

@mcollina
Copy link
Member

mcollina commented Jul 2, 2019

Should we ship this as experimental to start?

doc/api/stream.md Outdated Show resolved Hide resolved
doc/api/stream.md Outdated Show resolved Hide resolved
doc/api/stream.md Outdated Show resolved Hide resolved
doc/api/stream.md Outdated Show resolved Hide resolved
@addaleax addaleax 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
doc/api/stream.md Outdated Show resolved Hide resolved
doc/api/stream.md Show resolved Hide resolved
lib/_stream_transform.js Outdated Show resolved Hide resolved
lib/_stream_transform.js Outdated Show resolved Hide resolved
lib/_stream_transform.js Outdated Show resolved Hide resolved
lib/_stream_transform.js Outdated Show resolved Hide resolved
lib/_stream_transform.js Outdated Show resolved Hide resolved
@devsnek
Copy link
Member

devsnek commented Jul 3, 2019

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
Member

mcollina commented Jul 4, 2019

@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
Copy link
Member

devsnek commented Jul 4, 2019

@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
Copy link
Member

ronag commented Dec 16, 2019

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

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

@ronag
Copy link
Member

ronag commented Dec 16, 2019

This probably got broken by f8018f2

Copy link
Member

@ronag ronag left a comment

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).

const from = require('internal/streams/from');
Transform.by = function by(asyncGeneratorFn, opts) {
  let _resolve;
  let _promise = new Promise((resolve) => _resolve = resolve);
  return from(Duplex, asyncGeneratorFn(async function*() {
    while (true) {
      const { chunk, done, cb } = await _promise;
      if (done) return cb();
      yield chunk;
      _promise = new Promise((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
Member

ronag commented Dec 17, 2019

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

@davidmarkclements
Copy link
Member Author

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
Copy link
Member Author

davidmarkclements commented Dec 17, 2019

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
Copy link
Member

ronag commented Dec 17, 2019

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
Copy link
Member

ronag commented Dec 17, 2019

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
Member

ronag commented Dec 17, 2019

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
Copy link
Member

ronag commented Feb 9, 2020

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

@mcollina
Copy link
Member

mcollina commented Feb 9, 2020

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

@ronag
Copy link
Member

ronag commented Feb 9, 2020

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

@BridgeAR BridgeAR force-pushed the master branch 2 times, most recently from 8ae28ff to 2935f72 Compare May 31, 2020 12:19
@jasnell
Copy link
Member

jasnell commented Jul 7, 2020

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

@jasnell jasnell added the stalled Issues and PRs that are stalled. label Jul 7, 2020
@davidmarkclements
Copy link
Member Author

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

@mcollina
Copy link
Member

Yes we can!

@aduh95 aduh95 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

safareli commented May 6, 2021

Hi, this looks super nice!

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

@mcollina
Copy link
Member

mcollina commented May 6, 2021

@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

@mcollina I've open #38696

@ronag
Copy link
Member

ronag commented Jul 8, 2021

Closing in favor of #38696

@ronag ronag closed this Jul 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver-minor PRs that contain new features and should be released in the next minor version. stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.