-
Notifications
You must be signed in to change notification settings - Fork 40
Description
Function in question:
Lines 117 to 166 in 46db8f3
| TransportStream.prototype._writev = function _writev(chunks, callback) { | |
| if (this.logv) { | |
| const infos = chunks.filter(this._accept, this); | |
| if (!infos.length) { | |
| return callback(null); | |
| } | |
| // Remark (indexzero): from a performance perspective if Transport | |
| // implementers do choose to implement logv should we make it their | |
| // responsibility to invoke their format? | |
| return this.logv(infos, callback); | |
| } | |
| for (let i = 0; i < chunks.length; i++) { | |
| if (!this._accept(chunks[i])) continue; | |
| if (chunks[i].chunk && !this.format) { | |
| this.log(chunks[i].chunk, chunks[i].callback); | |
| continue; | |
| } | |
| let errState; | |
| let transformed; | |
| // We trap(and re-throw) any errors generated by the user-provided format, but also | |
| // guarantee that the streams callback is invoked so that we can continue flowing. | |
| try { | |
| transformed = this.format.transform( | |
| Object.assign({}, chunks[i].chunk), | |
| this.format.options | |
| ); | |
| } catch (err) { | |
| errState = err; | |
| } | |
| if (errState || !transformed) { | |
| // eslint-disable-next-line callback-return | |
| chunks[i].callback(); | |
| if (errState) { | |
| // eslint-disable-next-line callback-return | |
| callback(null); | |
| throw errState; | |
| } | |
| } else { | |
| this.log(transformed, chunks[i].callback); | |
| } | |
| } | |
| return callback(null); | |
| }; |
This implementation of _writev calls callback before all the callbacks of this.log(chunks[i]...) are called. This means that the transport stream may seem finished even if the underlying implementation hasn't finished writing out all the chunks yet.
We ran into this when we saw that during tests that when we close a winston logger, we would sometimes see a finish event be emitted from the logger before our transport finished writing its files.
We're currently working around this by implementing our own logv for our transport since that gives us control over calling the callback to _writev only when each chunk is finished.
I'm happy to try to construct a minimal example and/or provide a merge request to fix this. I just want to check here if this is something that's done by design or otherwise known.