-
-
Notifications
You must be signed in to change notification settings - Fork 663
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(runtime&server): support updating dependencies without restarting (
#1823) * feat(runtime): support updating dependencies without restarting * feat(server): publish conf when dep changes * change dev script * clear module cache * fix upload node_modules
- Loading branch information
Showing
11 changed files
with
280 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
import { exec } from 'child_process' | ||
import * as fs from 'fs' | ||
import Module from 'module' | ||
import path from 'path' | ||
import Config from '../config' | ||
import { logger } from './logger' | ||
import { | ||
CUSTOM_DEPENDENCY_NODE_MODULES_PATH, | ||
FunctionModule, | ||
} from './engine/module' | ||
|
||
// === override to disable cache | ||
// @ts-ignore | ||
const originModuleStat = Module._stat | ||
// @ts-ignore | ||
Module._stat = (filename: string) => { | ||
if (!filename.startsWith(CUSTOM_DEPENDENCY_NODE_MODULES_PATH)) { | ||
return originModuleStat(filename) | ||
} | ||
filename = path.toNamespacedPath(filename) | ||
|
||
let stat | ||
try { | ||
stat = fs.statSync(filename) | ||
} catch (e) { | ||
return -2 // not found | ||
} | ||
if (stat.isDirectory()) { | ||
return 1 | ||
} | ||
return 0 | ||
} | ||
|
||
// @ts-ignore | ||
const originModuleReadPackage = Module._readPackage | ||
// @ts-ignore | ||
Module._readPackage = (requestPath: string) => { | ||
const pkg = originModuleReadPackage(requestPath) | ||
if ( | ||
pkg.exists === false && | ||
pkg.pjsonPath.startsWith(CUSTOM_DEPENDENCY_NODE_MODULES_PATH) | ||
) { | ||
try { | ||
const _pkg = JSON.parse(fs.readFileSync(pkg.pjsonPath, 'utf8')) | ||
pkg.main = _pkg.main | ||
pkg.exists = true | ||
} catch {} | ||
} | ||
return pkg | ||
} | ||
// === | ||
|
||
export function clearModuleCache(moduleId: string) { | ||
let filePath: string | ||
|
||
try { | ||
filePath = FunctionModule.customRequire.resolve(moduleId) | ||
} catch {} | ||
|
||
if (!filePath) { | ||
return | ||
} | ||
|
||
// Delete itself from module parent | ||
if (require.cache[filePath] && require.cache[filePath].parent) { | ||
let i = require.cache[filePath].parent.children.length | ||
|
||
while (i--) { | ||
if (require.cache[filePath].parent.children[i].id === filePath) { | ||
require.cache[filePath].parent.children.splice(i, 1) | ||
} | ||
} | ||
} | ||
|
||
// Remove all descendants from cache as well | ||
if (require.cache[filePath]) { | ||
const children = require.cache[filePath].children.map((child) => child.id) | ||
|
||
// Delete module from cache | ||
delete require.cache[filePath] | ||
|
||
for (const id of children) { | ||
clearModuleCache(id) | ||
} | ||
} | ||
} | ||
|
||
const getPackageNameWithoutVersion = (name: string) => | ||
name.slice(0, name.indexOf('@', 1)) | ||
|
||
export function installDependency(packageName: string) { | ||
return new Promise((resolve, reject) => { | ||
logger.info(`Installing package ${packageName} ...`) | ||
exec( | ||
`cd ${ | ||
Config.CUSTOM_DEPENDENCY_BASE_PATH | ||
} && npm install ${packageName} && (sh ${process.cwd()}/upload-dependencies.sh ${ | ||
Config.CUSTOM_DEPENDENCY_BASE_PATH | ||
} > /dev/null 2>&1) &`, | ||
(error, stdout) => { | ||
if (error) { | ||
logger.error(`Error installing package ${packageName}: ${error}`) | ||
return reject(error) | ||
} | ||
// if (stderr) { | ||
// logger.error(`Error installing package ${packageName}: ${stderr}`) | ||
// return reject(new Error(stderr)) | ||
// } | ||
logger.info(`Package ${packageName} installed success`) | ||
resolve(stdout) | ||
}, | ||
) | ||
}) | ||
} | ||
|
||
export function installDependencies(packageName: string[]) { | ||
return installDependency(packageName.join(' ')) | ||
.catch(() => {}) | ||
.finally(() => { | ||
packageName.forEach((v) => { | ||
clearModuleCache(getPackageNameWithoutVersion(v)) | ||
}) | ||
}) | ||
} | ||
|
||
export function uninstallDependency(packageName: string) { | ||
return new Promise((resolve, reject) => { | ||
logger.info(`Uninstalling package ${packageName} ...`) | ||
exec( | ||
`cd ${ | ||
Config.CUSTOM_DEPENDENCY_BASE_PATH | ||
} && npm uninstall ${packageName} && (sh ${process.cwd()}/upload-dependencies.sh ${ | ||
Config.CUSTOM_DEPENDENCY_BASE_PATH | ||
} > /dev/null 2>&1) &`, | ||
(error, stdout) => { | ||
if (error) { | ||
logger.error(`Error uninstalling package ${packageName}: ${error}`) | ||
return reject(error) | ||
} | ||
// if (stderr) { | ||
// logger.error(`Error uninstalling package ${packageName}: ${stderr}`) | ||
// return reject(new Error(stderr)) | ||
// } | ||
logger.info(`Package ${packageName} uninstalled success`) | ||
resolve(stdout) | ||
}, | ||
) | ||
}) | ||
} | ||
|
||
export function uninstallDependencies(packageName: string[]) { | ||
packageName.forEach((v) => clearModuleCache(getPackageNameWithoutVersion(v))) | ||
|
||
return uninstallDependency( | ||
packageName.map((v) => getPackageNameWithoutVersion(v)).join(' '), | ||
) | ||
.catch(() => {}) | ||
.finally(() => { | ||
packageName.forEach((v) => | ||
clearModuleCache(getPackageNameWithoutVersion(v)), | ||
) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
### cache node_modules ### | ||
# if $NODE_MODULES_PUSH_URL is not empty | ||
if [ -n "$NODE_MODULES_PUSH_URL" ]; then | ||
NODE_MODULES_PATH=$1 | ||
# temporarily disable set -e | ||
set +e | ||
|
||
start_time=$(date +%s) | ||
echo $DEPENDENCIES > $NODE_MODULES_PATH/node_modules/.dependencies | ||
echo "Uploading node_modules to $NODE_MODULES_PUSH_URL" | ||
|
||
# tar `node_modules` to node_modules.tar | ||
tar -cf $NODE_MODULES_PATH/node_modules.tar $NODE_MODULES_PATH/node_modules | ||
|
||
end_time_1=$(date +%s) | ||
elapsed_time=$(expr $end_time_1 - $start_time) | ||
echo "Compressed node_modules in $elapsed_time seconds." | ||
|
||
# upload node_modules.tar to $NODE_MODULES_PUSH_URL | ||
curl -sSfL -X PUT -T $NODE_MODULES_PATH/node_modules.tar $NODE_MODULES_PUSH_URL | ||
|
||
|
||
if [ $? -ne 0 ]; then | ||
echo "Failed to upload node_modules cache." | ||
else | ||
end_time_2=$(date +%s) | ||
elapsed_time_2=$(expr $end_time_2 - $end_time) | ||
echo "Uploaded node_modules.tar in $elapsed_time_2 seconds." | ||
fi | ||
|
||
# re-enable set -e | ||
set -e | ||
fi |
Oops, something went wrong.