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 (updated) #38696

Closed
wants to merge 43 commits into from

Conversation

safareli
Copy link

Updated #28501

David Mark Clements and 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 <[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]>
@github-actions github-actions bot 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
@nodejs-github-bot
Copy link
Collaborator

doc/api/stream.md Show resolved Hide resolved
lib/internal/streams/transform.js Outdated Show resolved Hide resolved
lib/internal/streams/transform.js Outdated Show resolved Hide resolved
lib/internal/streams/transform.js Outdated Show resolved Hide resolved
lib/internal/streams/transform.js Outdated Show resolved Hide resolved
lib/internal/streams/transform.js Outdated Show resolved Hide resolved
lib/internal/streams/transform.js Show resolved Hide resolved
doc/api/stream.md Outdated Show resolved Hide resolved
Copy link
Contributor

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

lib/internal/streams/transform.js Outdated Show resolved Hide resolved
lib/internal/streams/transform.js Outdated Show resolved Hide resolved
safareli and others added 2 commits June 6, 2021 17:04
Co-authored-by: Antoine du Hamel <[email protected]>
Co-authored-by: Antoine du Hamel <[email protected]>
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@mcollina
Copy link
Member

mcollina commented Jun 8, 2021

May I recommend a squash and force push?

@nodejs-github-bot
Copy link
Collaborator

@safareli
Copy link
Author

safareli commented Jun 8, 2021

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');
Copy link
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
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.

objectMode: true,
autoDestroy: true,
...options,
write: (chunk, encoding, cb) => resolve({ chunk, done: false, cb }),
Copy link
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
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 } = await promise;


const expected = ['T', 'E', 'S', 'T'];
for await (const chunk of stream) {
strictEqual(chunk, expected.shift());
Copy link
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
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
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
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
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
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

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

@mcollina mcollina left a 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.

lib/internal/streams/transform.js Outdated Show resolved Hide resolved
lib/internal/streams/transform.js Outdated Show resolved Hide resolved
lib/internal/streams/transform.js Outdated Show resolved Hide resolved
@safareli
Copy link
Author

safareli commented Jun 9, 2021

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

@sounisi5011
Copy link

sounisi5011 commented Jun 9, 2021

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.

@nodejs-github-bot
Copy link
Collaborator

@mcollina
Copy link
Member

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

@mcollina mcollina mentioned this pull request Jul 1, 2021
@ronag
Copy link
Member

ronag commented Jan 3, 2022

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.

@ronag ronag closed this Jan 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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. 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. stream Issues and PRs related to the stream subsystem. tools Issues and PRs related to the tools directory.
Projects
None yet
Development

Successfully merging this pull request may close these issues.