diff options
author | Chocobozzz <me@florianbigard.com> | 2021-12-03 09:52:03 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-12-03 10:14:17 +0100 |
commit | ca87d95bcbfec9241e5840267862bace8b0197fa (patch) | |
tree | 8cc01322ac3140e0ab191770cae0e03b84ab2bb9 | |
parent | 8406a9e8eec261e563d99c92f8a18b6bd3e46e0f (diff) | |
download | PeerTube-ca87d95bcbfec9241e5840267862bace8b0197fa.tar.gz PeerTube-ca87d95bcbfec9241e5840267862bace8b0197fa.tar.zst PeerTube-ca87d95bcbfec9241e5840267862bace8b0197fa.zip |
Fix plugin upgrade
Correctly decache all plugin paths
-rw-r--r-- | config/test.yaml | 1 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | server/helpers/decache.ts | 78 | ||||
-rw-r--r-- | server/initializers/config.ts | 4 | ||||
-rw-r--r-- | server/lib/plugins/plugin-manager.ts | 8 | ||||
-rw-r--r-- | yarn.lock | 12 |
6 files changed, 85 insertions, 19 deletions
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: | |||
155 | federation: | 155 | federation: |
156 | videos: | 156 | videos: |
157 | federate_unlisted: true | 157 | federate_unlisted: true |
158 | cleanup_remote_interactions: false | ||
158 | 159 | ||
159 | views: | 160 | views: |
160 | videos: | 161 | videos: |
diff --git a/package.json b/package.json index 6cc00d1ae..b03f5dcdb 100644 --- a/package.json +++ b/package.json | |||
@@ -90,7 +90,6 @@ | |||
90 | "cookie-parser": "^1.4.3", | 90 | "cookie-parser": "^1.4.3", |
91 | "cors": "^2.8.1", | 91 | "cors": "^2.8.1", |
92 | "create-torrent": "^5.0.0", | 92 | "create-torrent": "^5.0.0", |
93 | "decache": "^4.6.0", | ||
94 | "deep-object-diff": "^1.1.0", | 93 | "deep-object-diff": "^1.1.0", |
95 | "email-templates": "^8.0.3", | 94 | "email-templates": "^8.0.3", |
96 | "execa": "^5.1.1", | 95 | "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 @@ | |||
1 | // Thanks: https://github.com/dwyl/decache | ||
2 | // We reuse this file to also uncache plugin base path | ||
3 | |||
4 | import { extname } from 'path' | ||
5 | |||
6 | function decachePlugin (pluginPath: string, libraryPath: string) { | ||
7 | const moduleName = find(libraryPath) | ||
8 | |||
9 | if (!moduleName) return | ||
10 | |||
11 | searchCache(moduleName, function (mod) { | ||
12 | delete require.cache[mod.id] | ||
13 | }) | ||
14 | |||
15 | removeCachedPath(pluginPath) | ||
16 | } | ||
17 | |||
18 | function decacheModule (name: string) { | ||
19 | const moduleName = find(name) | ||
20 | |||
21 | if (!moduleName) return | ||
22 | |||
23 | searchCache(moduleName, function (mod) { | ||
24 | delete require.cache[mod.id] | ||
25 | }) | ||
26 | |||
27 | removeCachedPath(moduleName) | ||
28 | } | ||
29 | |||
30 | // --------------------------------------------------------------------------- | ||
31 | |||
32 | export { | ||
33 | decacheModule, | ||
34 | decachePlugin | ||
35 | } | ||
36 | |||
37 | // --------------------------------------------------------------------------- | ||
38 | |||
39 | function find (moduleName: string) { | ||
40 | try { | ||
41 | return require.resolve(moduleName) | ||
42 | } catch { | ||
43 | return '' | ||
44 | } | ||
45 | } | ||
46 | |||
47 | function searchCache (moduleName: string, callback: (current: NodeModule) => void) { | ||
48 | const resolvedModule = require.resolve(moduleName) | ||
49 | let mod: NodeModule | ||
50 | const visited = {} | ||
51 | |||
52 | if (resolvedModule && ((mod = require.cache[resolvedModule]) !== undefined)) { | ||
53 | // Recursively go over the results | ||
54 | (function run (current) { | ||
55 | visited[current.id] = true | ||
56 | |||
57 | current.children.forEach(function (child) { | ||
58 | if (extname(child.filename) !== '.node' && !visited[child.id]) { | ||
59 | run(child) | ||
60 | } | ||
61 | }) | ||
62 | |||
63 | // Call the specified callback providing the | ||
64 | // found module | ||
65 | callback(current) | ||
66 | })(mod) | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | function removeCachedPath (pluginPath: string) { | ||
71 | const pathCache = (module.constructor as any)._pathCache | ||
72 | |||
73 | Object.keys(pathCache).forEach(function (cacheKey) { | ||
74 | if (cacheKey.includes(pluginPath)) { | ||
75 | delete pathCache[cacheKey] | ||
76 | } | ||
77 | }) | ||
78 | } | ||
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 @@ | |||
1 | import bytes from 'bytes' | 1 | import bytes from 'bytes' |
2 | import { IConfig } from 'config' | 2 | import { IConfig } from 'config' |
3 | import decache from 'decache' | ||
4 | import { dirname, join } from 'path' | 3 | import { dirname, join } from 'path' |
4 | import { decacheModule } from '@server/helpers/decache' | ||
5 | import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' | 5 | import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' |
6 | import { BroadcastMessageLevel } from '@shared/models/server' | 6 | import { BroadcastMessageLevel } from '@shared/models/server' |
7 | import { VideosRedundancyStrategy } from '../../shared/models' | 7 | import { VideosRedundancyStrategy } from '../../shared/models' |
@@ -497,7 +497,7 @@ export function reloadConfig () { | |||
497 | delete require.cache[fileName] | 497 | delete require.cache[fileName] |
498 | } | 498 | } |
499 | 499 | ||
500 | decache('config') | 500 | decacheModule('config') |
501 | } | 501 | } |
502 | 502 | ||
503 | purge() | 503 | 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 @@ | |||
1 | import decache from 'decache' | ||
2 | import express from 'express' | 1 | import express from 'express' |
3 | import { createReadStream, createWriteStream } from 'fs' | 2 | import { createReadStream, createWriteStream } from 'fs' |
4 | import { ensureDir, outputFile, readJSON } from 'fs-extra' | 3 | import { ensureDir, outputFile, readJSON } from 'fs-extra' |
5 | import { basename, join } from 'path' | 4 | import { basename, join } from 'path' |
5 | import { decachePlugin } from '@server/helpers/decache' | ||
6 | import { MOAuthTokenUser, MUser } from '@server/types/models' | 6 | import { MOAuthTokenUser, MUser } from '@server/types/models' |
7 | import { getCompleteLocale } from '@shared/core-utils' | 7 | import { getCompleteLocale } from '@shared/core-utils' |
8 | import { ClientScript, PluginPackageJson, PluginTranslation, PluginTranslationPaths, RegisterServerHookOptions } from '@shared/models' | 8 | import { ClientScript, PluginPackageJson, PluginTranslation, PluginTranslationPaths, RegisterServerHookOptions } from '@shared/models' |
@@ -312,12 +312,12 @@ export class PluginManager implements ServerHook { | |||
312 | logger.error('Cannot install plugin %s, removing it...', toInstall, { err: rootErr }) | 312 | logger.error('Cannot install plugin %s, removing it...', toInstall, { err: rootErr }) |
313 | 313 | ||
314 | try { | 314 | try { |
315 | await this.uninstall(npmName) | 315 | // await this.uninstall(npmName) |
316 | } catch (err) { | 316 | } catch (err) { |
317 | logger.error('Cannot uninstall plugin %s after failed installation.', toInstall, { err }) | 317 | logger.error('Cannot uninstall plugin %s after failed installation.', toInstall, { err }) |
318 | 318 | ||
319 | try { | 319 | try { |
320 | await removeNpmPlugin(npmName) | 320 | // await removeNpmPlugin(npmName) |
321 | } catch (err) { | 321 | } catch (err) { |
322 | logger.error('Cannot remove plugin %s after failed installation.', toInstall, { err }) | 322 | logger.error('Cannot remove plugin %s after failed installation.', toInstall, { err }) |
323 | } | 323 | } |
@@ -420,7 +420,7 @@ export class PluginManager implements ServerHook { | |||
420 | 420 | ||
421 | // Delete cache if needed | 421 | // Delete cache if needed |
422 | const modulePath = join(pluginPath, packageJSON.library) | 422 | const modulePath = join(pluginPath, packageJSON.library) |
423 | decache(modulePath) | 423 | decachePlugin(pluginPath, modulePath) |
424 | const library: PluginLibrary = require(modulePath) | 424 | const library: PluginLibrary = require(modulePath) |
425 | 425 | ||
426 | if (!isLibraryCodeValid(library)) { | 426 | if (!isLibraryCodeValid(library)) { |
@@ -2613,11 +2613,6 @@ call-me-maybe@^1.0.1: | |||
2613 | resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" | 2613 | resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" |
2614 | integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= | 2614 | integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= |
2615 | 2615 | ||
2616 | callsite@^1.0.0: | ||
2617 | version "1.0.0" | ||
2618 | resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" | ||
2619 | integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= | ||
2620 | |||
2621 | callsites@^3.0.0: | 2616 | callsites@^3.0.0: |
2622 | version "3.1.0" | 2617 | version "3.1.0" |
2623 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" | 2618 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" |
@@ -3229,13 +3224,6 @@ debuglog@^1.0.0: | |||
3229 | resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" | 3224 | resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" |
3230 | integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= | 3225 | integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= |
3231 | 3226 | ||
3232 | decache@^4.6.0: | ||
3233 | version "4.6.0" | ||
3234 | resolved "https://registry.yarnpkg.com/decache/-/decache-4.6.0.tgz#87026bc6e696759e82d57a3841c4e251a30356e8" | ||
3235 | integrity sha512-PppOuLiz+DFeaUvFXEYZjLxAkKiMYH/do/b/MxpDe/8AgKBi5GhZxridoVIbBq72GDbL36e4p0Ce2jTGUwwU+w== | ||
3236 | dependencies: | ||
3237 | callsite "^1.0.0" | ||
3238 | |||
3239 | decamelize@^1.2.0: | 3227 | decamelize@^1.2.0: |
3240 | version "1.2.0" | 3228 | version "1.2.0" |
3241 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" | 3229 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" |