node icon indicating copy to clipboard operation
node copied to clipboard

fix: Ensure `Duplex streams` are returned unwrapped in stream operators

Open KunalKumar-1 opened this issue 1 year ago • 13 comments

Updated the implementation of the readable.compose() method to ensure that it correctly returns a Duplex stream when applicable, avoiding unintended conversion to Readable streams. fixes: #55203

KunalKumar-1 avatar Oct 15 '24 14:10 KunalKumar-1

Review requested:

  • [ ] @nodejs/streams

nodejs-github-bot avatar Oct 15 '24 14:10 nodejs-github-bot

Please add a test

avivkeller avatar Oct 15 '24 16:10 avivkeller

@RedYetiDev test added

KunalKumar-1 avatar Oct 15 '24 18:10 KunalKumar-1

CI: https://ci.nodejs.org/job/node-test-pull-request/63127/

nodejs-github-bot avatar Oct 15 '24 19:10 nodejs-github-bot

Codecov Report

Attention: Patch coverage is 66.66667% with 3 lines in your changes missing coverage. Please review.

Project coverage is 88.35%. Comparing base (51d8146) to head (90ac00d). Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
lib/stream.js 66.66% 2 Missing and 1 partial :warning:
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #55394      +/-   ##
==========================================
- Coverage   88.41%   88.35%   -0.07%     
==========================================
  Files         652      652              
  Lines      186878   186897      +19     
  Branches    36061    36024      -37     
==========================================
- Hits       165226   165126     -100     
- Misses      14902    15017     +115     
- Partials     6750     6754       +4     
Files with missing lines Coverage Δ
lib/stream.js 94.37% <66.66%> (-5.63%) :arrow_down:

... and 32 files with indirect coverage changes

codecov[bot] avatar Oct 15 '24 21:10 codecov[bot]

@mcollina why the test cases are failing ?

KunalKumar-1 avatar Oct 16 '24 05:10 KunalKumar-1

@ronag I see your point regarding the stream semantics. If performance impact is minimal, then returning an explicit Readable does make sense to clarify the intended use. Could you clarify the exact changes you’d like to see here?

KunalKumar-1 avatar Oct 16 '24 07:10 KunalKumar-1

Could you clarify the exact changes you’d like to see here?

Well if consider my concern. Then we should just leave this as is? We might ned update docs/typings to clarify that if the first param (this) to compose is not writable then we return a readable instead of duplex, ditto with if the last stream is not readable, we return a writable.

ronag avatar Oct 16 '24 07:10 ronag

Alternatively returning a new Duplex with writable: false

ronag avatar Oct 16 '24 07:10 ronag

Alternatively returning a new Duplex with writable: false

After considering both options, would it be preferable to return a new Duplex with writable: false, or should we lean towards your suggestion of simply returning a Readable or Writable stream based on the first and last streams in the composition?

I’m inclined to go with whichever approach aligns best with the project’s consistency and performance considerations !

KunalKumar-1 avatar Oct 16 '24 08:10 KunalKumar-1

I'm happy with the Duplex approach. Give it a day or two for others to also voice their opinions before you spend more time on this. Otherwise, you might risk doing more work.

ronag avatar Oct 16 '24 08:10 ronag

I'm happy with the Duplex approach. Give it a day or two for others to also voice their opinions before you spend more time on this. Otherwise, you might risk doing more work.

Yeah , sure It sounds great. I Will start working on it after a day or two .... After hearing some options.

KunalKumar-1 avatar Oct 16 '24 09:10 KunalKumar-1

I'm on the fence here. The returned stream should not be written to so semantically it makes more sense to return an explicit readable. Though there is some performance costs associated with this.

readable.compose(x) should have the same behaviour as stream.compose(readable, x) imo (ie. return a read-only Duplex), given that the former is essentially just a wrapper for the latter. This also keeps things consistent if called as duplex.compose(x), which should also return a Duplex (read-only or read-write depending on the source stream).

After considering both options, would it be preferable to return a new Duplex with writable: false

It's worth mentioning that this is already what's returned by the internal compose() operator, so wouldn't need any further handling.

Indeed, if the desired behaviour of readable.compose() is that it just passes through the Duplex returned by the compose operator, then it wouldn't need to be included in streamReturningOperators at all; the operator could just be added straight onto Readable.prototype.

Renegade334 avatar Oct 17 '24 16:10 Renegade334