Ensure ffmpeg temp files are always fully written #78
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR fixes audiosprite generation failures on congested hard drives where the individual ffmpeg write streams may not have finished before the sprite is generated.
Some background:
I've already done a fix to this package regarding a similar issue almost two years ago: #73
Since then we've upgraded our build system and are running much more concurrent builds than before on a single machine. Recently we've seen a lot of these builds fail randomly due to audiosprite generation, where we validate that the individual samples in the generated sprites actually have a length greater than zero.
It took me quite a while to pinpoint the problem but it turns out to be caused by hard drive congestion which slows the disk I/O enough to bring up this particular race condition. I managed to isolate the problem by simulating a really slow hard disk according to this great blog post: https://planet.jboss.org/post/debugging_tip_how_to_simulate_a_slow_hardisk
So when I created a network drive and slowed it down to 1 Mb/s read and write speed I managed to get the audiosprite package's own tests to fail around 20% of the time - tests which were working 100% of the time with a regular speed hard drive. The failed tests sometimes had sprites of length 0 and sometimes even more scarier lengths, where the samples had some data clipped from the end. These are scarier since we do not catch in our build system and thus they could result in corrupted audio in our production builds.
Needless to say that with this fix the tests work 100% even with the slow hard drive.
The implementation:
The write stream didn't have any listener so even though my earlier fix ensured that the ffmpeg's stdout stream had closed there was no guarantee that the write stream had finished flushing everything to disk. So I added a 'close' event listener for that stream and then used Lodash
after
to postpone the callback until both the process has exited and the write stream has finished. The code would have been much cleaner if we only listened to the write stream but we do need the process listener as well to catch error codes and I didn't really want to break existing functionality there.I've tested this on Windows with Node v10.17.0 and in Linux with Node v13.5.0. I don't see any reason why it wouldn't work with older versions of Node or other platforms as well.