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
Prevent concurrent builds from happening #27
Prevent concurrent builds from happening #27
Conversation
AMP noticed that multiple _initial_ builds can happen if Karma takes a long time between calls to karma-esbuild's preprocessor (in our case, we have hundreds of files having SHA hashes performed). This lead to multiple `bundle.write` calls happening. Now, our test suite is so large, esbuild takes a few seconds to run through everything. So when the second `bundle.write` happens, we're still trying to bundle the first time. This leads to 2 initial builds. Because both builds are `incremental`, they hold on to esbuild's Go process. And because we would lose our reference to the first incremental build when the second finished, we now had an undying holder on esbuild. While solving this concurrent initial build problem, I decided that we should never have 2 concurrent builds happening at the same time. Now only 1 build can be happening at a time, and if multiple write come in (either during the initial build or during a rebuild), we'll wait for the in-progress build to finish before starting the new one. Async reentrant problems are hard.
b83bb3c
to
dfc4067
Compare
Let the default equality message shine through
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fantastic! It makes so much more sense to disallow parallel builds. Love this 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDEs really need spellcheck 😄
// case, we resolve the old build with the latest result. | ||
private buildsInProgress = 0; | ||
// buildInProgress tracks the in-progress build. When a build takes too | ||
// long, a new build may have been requsted before the original completed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/requsted/requested
this.beforeProcess(); | ||
} else { | ||
// Wait for the previous build to happen before we continue. This prevents | ||
// any reentrant behavior, and guarnatees we can get an initial bundle to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: s/guarnatees/guarantees
@@ -100,7 +122,10 @@ export class Bundle { | |||
// Wait for any in-progress builds to finish. At this point, we know no | |||
// new ones will come in, we're just waiting for the current one to | |||
// finish running. | |||
if (this.buildsInProgress > 0 || this._dirty) { | |||
if (this.buildInProgress || this._dirty) { | |||
// Wait on the deffered, not the buildInProgress, because the dirty flag |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/deffered/deferred
AMP noticed that multiple initial builds can happen if Karma takes a long time between calls to karma-esbuild's preprocessor (in our case, we have hundreds of files having SHA hashes performed). This lead to multiple
bundle.write
calls happening.Now, our test suite is so large, esbuild takes a few seconds to run through everything. So when the second
bundle.write
happens, we're still trying to bundle the first time. This leads to 2 initial builds. Because both builds areincremental
, they hold on to esbuild's Go process. And because we would lose our reference to the first incremental build when the second finished, we now had an undying holder on esbuild.While solving this concurrent initial build problem, I decided that we should never have 2 concurrent builds happening at the same time. Now only 1 build can be happening at a time, and if multiple write come in (either during the initial build or during a rebuild), we'll wait for the in-progress build to finish before starting the new one. A fun challenge was ensuring that we can only have at most 1 in-progress build and 1 pending build.
Async reentrant problems are hard.