-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
writing-a-plugin "Call the callback function only when the current file (stream/buffer) is completely consumed" #2380
Comments
Can you post the full plugin code? |
@craigphicks I agree with @contra - there might be some weirdness here that we can only determine by seeing all the code. |
This is part of a repo for a javascript pre-processor reversible-preproc. Part of that project is a Node Transform Stream, with Note: the currently published npm version (1,x,x) of reversible-preproc is a much older version which I plan to update shortly The following code is part of a dependent repo gulp-reversible-preproc with the aim of providing a gulp transform adapter. The argument It's written as a general gulp interface in order to provide a clean interface within the
Main Issue:Making the callback Secondary issueAs recommended is some gulp instructionals, the code is using CaveatThe code as is works now for the case of a single file opened with Except from gulp man page showing immedaite callback
|
I concur; I have observed the exact behavior described by @craigphicks . I didn't realize that this conflicted with the instructions, but my notes show that I am seeing the same issue:
|
Per @craigphicks caveat:
I too can write one file successfully, but when I write two files only one writes correctly in some circumstances. Behavior noted below is consistent given the test data I'm using, but it may well be dependent upon timing and other factors, such as the size of the data being moved, etc.
|
@donpedro - Your project is very interesting. I have a question about
When does this function (pass as argument) get called and what entity receives the data? |
@craigphicks that's just an empty transformFunction; I could have just left the function out completely, as I'm not actually doing any transformation; I'm really just using newStream as a passthrough so I can use it for newFile. More here: https://www.npmjs.com/package/through2#transformfunction Thanks for the good word! Be aware that gulp-api-adapter is very much under construction; it's being developed to work with our gulp-etl project, but hopefully it'll have some utility in the wider gulp world. Hopefully it'll be usable and stable later this week... |
I might have a smaller example for when the vinyl stream becomes empty (even though I'm not that experienced with streams, so there might be a user error in the following example).
The output file of the above task is empty, expected was a content of 'a'. |
@jonatanlinden You're ending the stream before you piped it anywhere - you probably want to do this: import { pipeline } from 'stream'
// later on in your code
const stream = source('bogusname');
pipeline(
stream,
size(),
dest('.'),
cb
)
stream.write('a');
stream.end(); |
Have you actually tried your code, and gotten another result? When I run my take of it (wrapping it in a function with cb as a parameter), I get the same behaviour as with my example: with (I believe The point was that
Where the function I guess it could be possible to construct an even smaller example exposing the behaviour, using gulp-size as a starting point. |
I was having a very similar issue with a plugin that invokes import {spawn} from 'node:child_process';
import process from 'node:process';
import gulp from 'gulp';
import PluginError from 'plugin-error';
import through from 'through2';
function generateSources() {
const nodeExecutable = process.argv[0];
return through.obj((file, encoding, callback) => {
if (file.isNull()) {
callback(null, file);
return;
}
// stdin and stdout are pipes, and stderr is inherited from this process.
const child = spawn(nodeExecutable, ['dist/tools/code-gen.js'], {
stdio: ['pipe', 'pipe', 'inherit'],
});
if (file.isStream()) {
console.log('Is stream.');
// file.contents is a ReadableStream
file.contents.pipe(child.stdin);
} else if (file.isBuffer()) {
console.log('Is buffer.');
// file.contents is a Buffer
child.stdin.write(file.contents);
child.stdin.end();
}
// Now file.contents is a ReadableStream from the child process's stdout.
file.contents = child.stdout;
// The filename should end in .ts.
file.extname = '.ts';
// If the child fails, this pipe fails.
child.on('error', (error) => {
console.log('On error.', error);
callback(error, null);
});
// Wait for the child to complete.
// Note that 'exit' fires before the pipes close, so we use 'close' to make
// sure we have all the data.
child.on('close', (code) => {
console.log('On close.', code);
if (code == 0) {
// Exit code zero, this pipe succeeds.
callback(null, file);
} else {
// Exit code non-zero, this pipe fails.
const error = new PluginError(
'GenerateSources', `Failed with exit code ${code}`);
callback(error, null);
}
});
});
} All my logs would occur after the task "finished" "successfully", even if I deliberately broke the command to trigger I finally found the cause. It was my task: gulp.task('generate-sources', gulp.series('build-tools', async () => {
return gulp.src('src/gen/*.yaml')
.pipe(generateSources())
.pipe(gulp.dest('generated/gen/'));
})); The problem was gulp.task('generate-sources', gulp.series('build-tools', () => {
return gulp.src('src/gen/*.yaml')
.pipe(generateSources())
.pipe(gulp.dest('generated/gen/'));
})); |
What were you expecting to happen?
Following the verbal guidance here -
then in case of
file.IsStream()
I expected to need to wait for the 'end' event from the inner transform before calling thecallback()
.What actually happened?
As shown in the code example on that man page, it only works if
callback()
is called immediately.Please post a sample of your gulpfile (preferably reduced to just the bit that's not working)
Actually implementing the above code (instead of calling the
callback
immediately), resulted in an empty file being written, although the inner transform had dutifully pushed all the data.What version of gulp are you using?
gulp 4
What versions of npm and node are you using?
npm 6.9.0
gulp 4.0.2
I am unable to convince myself that
could mean anything other than the
end
event has been emitted. Furthermore, the wording seems perfect from a design point of view, and fits with all the usage ofcallback
s that I know.How to reconcile the words and the actual design?
The text was updated successfully, but these errors were encountered: