Skip to content

Commit

Permalink
Add an endpoint to restart a compiler by name (#11)
Browse files Browse the repository at this point in the history
This endpoint has a 'soft' and a 'hard' restart. The former kicks off what is effectively a partial recompilation by invalidating the state of the compiler. It's pretty fast, but isn't good at things like busting caches. A 'hard' restart literally closes and restarts the compiler, showing the overlay and all that.

Co-authored-by: shilal <shilal@etsy.com>
  • Loading branch information
salemhilal and shilal authored Apr 14, 2021
1 parent 110132d commit 9c7e2ed
Showing 2 changed files with 66 additions and 4 deletions.
8 changes: 5 additions & 3 deletions lib/CompilerManager.js
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ const { logError } = require("./logger");

class CompilerManager {
/**
* @param {bool} $0.useFrequency - if true, use frequency instead of frecency
* @param {boolean} $0.useFrequency - if true, use frequency instead of frecency
* to determine compiler eviction.
*/
constructor({ useFrequency = false } = {}) {
@@ -38,7 +38,7 @@ class CompilerManager {

/**
* @param {string} name - compiler's name
* @returns {bool}
* @returns {boolean}
*/
isCompilerActive(name) {
return !!this.activeCompilers[name];
@@ -214,16 +214,18 @@ class CompilerManager {
* Calls invalidate on the compiler's Watching instance, without
* stopping the watch process.
* @param {string} name compiler's name
* @return {boolean} true if we found a compiler and invalidated it, false otherwise.
*/
invalidateCompiler(name) {
if (!this.isCompilerActive(name)) {
logError(
`Tried to invalidate compiler ${name}, but it's not being managed`
);
return;
return false;
}
const compiler = this.activeCompilers[name];
compiler.invalidate();
return true;
}

/**
62 changes: 61 additions & 1 deletion lib/middleware.js
Original file line number Diff line number Diff line change
@@ -116,7 +116,9 @@ class Kevin {
buildConfig(configName) {
const config = this.configs.find((config) => config.name === configName);
if (!config) {
logError(`Trying to build config: ${configName}, but it can't be found.`);
const msg = `Trying to build config: ${configName}, but it can't be found.`;
logError(msg);
return Promise.reject(msg);
}

// determine if there's a compiler already
@@ -324,6 +326,7 @@ class Kevin {

// ========================================
// Is it one of our internal API endpoints?
// TODO: This should probably use a Router
// ========================================
if (reqPath === `${this.kevinApiPrefix}/build-status`) {
// this endpoint shows the state of each compiler. the overlay
@@ -347,6 +350,63 @@ class Kevin {
return;
}

if (
req.method === "POST" &&
reqPath === `${this.kevinApiPrefix}/restart-compiler`
) {
// This endpoint restarts compilers. It accepts two query params:
// `compiler` (required), which is the name of the compiler, and
// `hard` (optional) which, if true, fully shuts down and restarts the compiler,
// rather than just invalidating it and forcing a partial recompilation.
if (
!req.query.compiler ||
!manager.isCompilerActive(req.query.compiler)
) {
return res
.status(400)
.send(
`Kevin couldn't find a compiler named ${req.query.compiler}.`
);
}
// If hard is set to anything that looks like "true", let's force restart the compiler.
if (req.query.hard && req.query.hard.toLowerCase() === "true") {
manager
.closeCompiler(req.query.compiler)
.then((name) => {
if (!name) {
return res
.status(400)
.send(
`Kevin couldn't find a compiler named ${req.query.compiler}.`
);
}
return this.buildConfig(name).then(() =>
res.sendStatus(200)
);
})
.catch((err) => {
logError(err);
res.status(500).send(
`Something went wrong trying to restart ${req.query.compiler}. Check the logs for details.`
);
});

return;
} else if (manager.invalidateCompiler(req.query.compiler)) {
logInfo(`Soft-restarted compiler: ${req.query.compiler}`);
res.sendStatus(200);
return;
} else {
logInfo(
`Could not restart this compiler (does it exist?): ${req.query.compiler}`
);
res.status(400).send(
"Kevin couldn't find a compiler with that name"
);
return;
}
}

// Mangle the url to get asset name
const assetName = this.getAssetName(reqPath, req, res);
// Select appropriate config for given asset

0 comments on commit 9c7e2ed

Please sign in to comment.