From ca87d95bcbfec9241e5840267862bace8b0197fa Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 3 Dec 2021 09:52:03 +0100 Subject: Fix plugin upgrade Correctly decache all plugin paths --- config/test.yaml | 1 + package.json | 1 - server/helpers/decache.ts | 78 ++++++++++++++++++++++++++++++++++++ server/initializers/config.ts | 4 +- server/lib/plugins/plugin-manager.ts | 8 ++-- yarn.lock | 12 ------ 6 files changed, 85 insertions(+), 19 deletions(-) create mode 100644 server/helpers/decache.ts diff --git a/config/test.yaml b/config/test.yaml index 2e7f982d3..461e1b4ba 100644 --- a/config/test.yaml +++ b/config/test.yaml @@ -155,6 +155,7 @@ search: federation: videos: federate_unlisted: true + cleanup_remote_interactions: false views: videos: diff --git a/package.json b/package.json index 6cc00d1ae..b03f5dcdb 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,6 @@ "cookie-parser": "^1.4.3", "cors": "^2.8.1", "create-torrent": "^5.0.0", - "decache": "^4.6.0", "deep-object-diff": "^1.1.0", "email-templates": "^8.0.3", "execa": "^5.1.1", diff --git a/server/helpers/decache.ts b/server/helpers/decache.ts new file mode 100644 index 000000000..e31973b7a --- /dev/null +++ b/server/helpers/decache.ts @@ -0,0 +1,78 @@ +// Thanks: https://github.com/dwyl/decache +// We reuse this file to also uncache plugin base path + +import { extname } from 'path' + +function decachePlugin (pluginPath: string, libraryPath: string) { + const moduleName = find(libraryPath) + + if (!moduleName) return + + searchCache(moduleName, function (mod) { + delete require.cache[mod.id] + }) + + removeCachedPath(pluginPath) +} + +function decacheModule (name: string) { + const moduleName = find(name) + + if (!moduleName) return + + searchCache(moduleName, function (mod) { + delete require.cache[mod.id] + }) + + removeCachedPath(moduleName) +} + +// --------------------------------------------------------------------------- + +export { + decacheModule, + decachePlugin +} + +// --------------------------------------------------------------------------- + +function find (moduleName: string) { + try { + return require.resolve(moduleName) + } catch { + return '' + } +} + +function searchCache (moduleName: string, callback: (current: NodeModule) => void) { + const resolvedModule = require.resolve(moduleName) + let mod: NodeModule + const visited = {} + + if (resolvedModule && ((mod = require.cache[resolvedModule]) !== undefined)) { + // Recursively go over the results + (function run (current) { + visited[current.id] = true + + current.children.forEach(function (child) { + if (extname(child.filename) !== '.node' && !visited[child.id]) { + run(child) + } + }) + + // Call the specified callback providing the + // found module + callback(current) + })(mod) + } +}; + +function removeCachedPath (pluginPath: string) { + const pathCache = (module.constructor as any)._pathCache + + Object.keys(pathCache).forEach(function (cacheKey) { + if (cacheKey.includes(pluginPath)) { + delete pathCache[cacheKey] + } + }) +} diff --git a/server/initializers/config.ts b/server/initializers/config.ts index dadda2a77..f3a7c6b6b 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts @@ -1,7 +1,7 @@ import bytes from 'bytes' import { IConfig } from 'config' -import decache from 'decache' import { dirname, join } from 'path' +import { decacheModule } from '@server/helpers/decache' import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' import { BroadcastMessageLevel } from '@shared/models/server' import { VideosRedundancyStrategy } from '../../shared/models' @@ -497,7 +497,7 @@ export function reloadConfig () { delete require.cache[fileName] } - decache('config') + decacheModule('config') } purge() diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index d4d2a7edc..8add72a85 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts @@ -1,8 +1,8 @@ -import decache from 'decache' import express from 'express' import { createReadStream, createWriteStream } from 'fs' import { ensureDir, outputFile, readJSON } from 'fs-extra' import { basename, join } from 'path' +import { decachePlugin } from '@server/helpers/decache' import { MOAuthTokenUser, MUser } from '@server/types/models' import { getCompleteLocale } from '@shared/core-utils' import { ClientScript, PluginPackageJson, PluginTranslation, PluginTranslationPaths, RegisterServerHookOptions } from '@shared/models' @@ -312,12 +312,12 @@ export class PluginManager implements ServerHook { logger.error('Cannot install plugin %s, removing it...', toInstall, { err: rootErr }) try { - await this.uninstall(npmName) + // await this.uninstall(npmName) } catch (err) { logger.error('Cannot uninstall plugin %s after failed installation.', toInstall, { err }) try { - await removeNpmPlugin(npmName) + // await removeNpmPlugin(npmName) } catch (err) { logger.error('Cannot remove plugin %s after failed installation.', toInstall, { err }) } @@ -420,7 +420,7 @@ export class PluginManager implements ServerHook { // Delete cache if needed const modulePath = join(pluginPath, packageJSON.library) - decache(modulePath) + decachePlugin(pluginPath, modulePath) const library: PluginLibrary = require(modulePath) if (!isLibraryCodeValid(library)) { diff --git a/yarn.lock b/yarn.lock index ee35c5c7e..62c95cfff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2613,11 +2613,6 @@ call-me-maybe@^1.0.1: resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= -callsite@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" - integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -3229,13 +3224,6 @@ debuglog@^1.0.0: resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= -decache@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/decache/-/decache-4.6.0.tgz#87026bc6e696759e82d57a3841c4e251a30356e8" - integrity sha512-PppOuLiz+DFeaUvFXEYZjLxAkKiMYH/do/b/MxpDe/8AgKBi5GhZxridoVIbBq72GDbL36e4p0Ce2jTGUwwU+w== - dependencies: - callsite "^1.0.0" - decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" -- cgit v1.2.3