diff options
-rw-r--r-- | server.ts | 2 | ||||
-rw-r--r-- | server/controllers/api/plugins.ts | 6 | ||||
-rw-r--r-- | server/helpers/requests.ts | 15 | ||||
-rw-r--r-- | server/initializers/constants.ts | 1 | ||||
-rw-r--r-- | server/lib/plugins/plugin-index.ts | 15 | ||||
-rw-r--r-- | server/lib/schedulers/plugins-check-scheduler.ts | 30 |
6 files changed, 51 insertions, 18 deletions
@@ -113,6 +113,7 @@ import { RemoveOldHistoryScheduler } from './server/lib/schedulers/remove-old-hi | |||
113 | import { isHTTPSignatureDigestValid } from './server/helpers/peertube-crypto' | 113 | import { isHTTPSignatureDigestValid } from './server/helpers/peertube-crypto' |
114 | import { PeerTubeSocket } from './server/lib/peertube-socket' | 114 | import { PeerTubeSocket } from './server/lib/peertube-socket' |
115 | import { updateStreamingPlaylistsInfohashesIfNeeded } from './server/lib/hls' | 115 | import { updateStreamingPlaylistsInfohashesIfNeeded } from './server/lib/hls' |
116 | import { PluginsCheckScheduler } from './server/lib/schedulers/plugins-check-scheduler' | ||
116 | 117 | ||
117 | // ----------- Command line ----------- | 118 | // ----------- Command line ----------- |
118 | 119 | ||
@@ -250,6 +251,7 @@ async function startApplication () { | |||
250 | VideosRedundancyScheduler.Instance.enable() | 251 | VideosRedundancyScheduler.Instance.enable() |
251 | RemoveOldHistoryScheduler.Instance.enable() | 252 | RemoveOldHistoryScheduler.Instance.enable() |
252 | RemoveOldViewsScheduler.Instance.enable() | 253 | RemoveOldViewsScheduler.Instance.enable() |
254 | PluginsCheckScheduler.Instance.enable() | ||
253 | 255 | ||
254 | // Redis initialization | 256 | // Redis initialization |
255 | Redis.Instance.init() | 257 | Redis.Instance.init() |
diff --git a/server/controllers/api/plugins.ts b/server/controllers/api/plugins.ts index 114cc49b6..bb410e891 100644 --- a/server/controllers/api/plugins.ts +++ b/server/controllers/api/plugins.ts | |||
@@ -180,5 +180,11 @@ async function listAvailablePlugins (req: express.Request, res: express.Response | |||
180 | 180 | ||
181 | const resultList = await listAvailablePluginsFromIndex(query) | 181 | const resultList = await listAvailablePluginsFromIndex(query) |
182 | 182 | ||
183 | if (!resultList) { | ||
184 | return res.status(503) | ||
185 | .json({ error: 'Plugin index unavailable. Please retry later' }) | ||
186 | .end() | ||
187 | } | ||
188 | |||
183 | return res.json(resultList) | 189 | return res.json(resultList) |
184 | } | 190 | } |
diff --git a/server/helpers/requests.ts b/server/helpers/requests.ts index 2e30c94a1..80476d649 100644 --- a/server/helpers/requests.ts +++ b/server/helpers/requests.ts | |||
@@ -1,18 +1,22 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { createWriteStream, remove } from 'fs-extra' | 2 | import { createWriteStream, remove } from 'fs-extra' |
3 | import * as request from 'request' | 3 | import * as request from 'request' |
4 | import { ACTIVITY_PUB } from '../initializers/constants' | 4 | import { ACTIVITY_PUB, WEBSERVER } from '../initializers/constants' |
5 | import { processImage } from './image-utils' | 5 | import { processImage } from './image-utils' |
6 | import { join } from 'path' | 6 | import { join } from 'path' |
7 | import { logger } from './logger' | 7 | import { logger } from './logger' |
8 | import { CONFIG } from '../initializers/config' | 8 | import { CONFIG } from '../initializers/config' |
9 | 9 | ||
10 | const packageJSON = require('../../../package.json') | ||
11 | |||
10 | function doRequest <T> ( | 12 | function doRequest <T> ( |
11 | requestOptions: request.CoreOptions & request.UriOptions & { activityPub?: boolean }, | 13 | requestOptions: request.CoreOptions & request.UriOptions & { activityPub?: boolean }, |
12 | bodyKBLimit = 1000 // 1MB | 14 | bodyKBLimit = 1000 // 1MB |
13 | ): Bluebird<{ response: request.RequestResponse, body: T }> { | 15 | ): Bluebird<{ response: request.RequestResponse, body: T }> { |
16 | if (!(requestOptions.headers)) requestOptions.headers = {} | ||
17 | requestOptions.headers['User-Agent'] = getUserAgent() | ||
18 | |||
14 | if (requestOptions.activityPub === true) { | 19 | if (requestOptions.activityPub === true) { |
15 | if (!Array.isArray(requestOptions.headers)) requestOptions.headers = {} | ||
16 | requestOptions.headers['accept'] = ACTIVITY_PUB.ACCEPT_HEADER | 20 | requestOptions.headers['accept'] = ACTIVITY_PUB.ACCEPT_HEADER |
17 | } | 21 | } |
18 | 22 | ||
@@ -27,6 +31,9 @@ function doRequestAndSaveToFile ( | |||
27 | destPath: string, | 31 | destPath: string, |
28 | bodyKBLimit = 10000 // 10MB | 32 | bodyKBLimit = 10000 // 10MB |
29 | ) { | 33 | ) { |
34 | if (!requestOptions.headers) requestOptions.headers = {} | ||
35 | requestOptions.headers['User-Agent'] = getUserAgent() | ||
36 | |||
30 | return new Bluebird<void>((res, rej) => { | 37 | return new Bluebird<void>((res, rej) => { |
31 | const file = createWriteStream(destPath) | 38 | const file = createWriteStream(destPath) |
32 | file.on('finish', () => res()) | 39 | file.on('finish', () => res()) |
@@ -60,6 +67,10 @@ async function downloadImage (url: string, destDir: string, destName: string, si | |||
60 | } | 67 | } |
61 | } | 68 | } |
62 | 69 | ||
70 | function getUserAgent () { | ||
71 | return `PeerTube/${packageJSON.version} (+${WEBSERVER.URL})` | ||
72 | } | ||
73 | |||
63 | // --------------------------------------------------------------------------- | 74 | // --------------------------------------------------------------------------- |
64 | 75 | ||
65 | export { | 76 | export { |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 06e8c070b..367ae8d45 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -618,6 +618,7 @@ if (isTestInstance() === true) { | |||
618 | SCHEDULER_INTERVALS_MS.removeOldHistory = 5000 | 618 | SCHEDULER_INTERVALS_MS.removeOldHistory = 5000 |
619 | SCHEDULER_INTERVALS_MS.removeOldViews = 5000 | 619 | SCHEDULER_INTERVALS_MS.removeOldViews = 5000 |
620 | SCHEDULER_INTERVALS_MS.updateVideos = 5000 | 620 | SCHEDULER_INTERVALS_MS.updateVideos = 5000 |
621 | SCHEDULER_INTERVALS_MS.checkPlugins = 10000 | ||
621 | REPEAT_JOBS[ 'videos-views' ] = { every: 5000 } | 622 | REPEAT_JOBS[ 'videos-views' ] = { every: 5000 } |
622 | 623 | ||
623 | REDUNDANCY.VIDEOS.RANDOMIZED_FACTOR = 1 | 624 | REDUNDANCY.VIDEOS.RANDOMIZED_FACTOR = 1 |
diff --git a/server/lib/plugins/plugin-index.ts b/server/lib/plugins/plugin-index.ts index 4a8a90ec8..63cd47e63 100644 --- a/server/lib/plugins/plugin-index.ts +++ b/server/lib/plugins/plugin-index.ts | |||
@@ -27,13 +27,18 @@ async function listAvailablePluginsFromIndex (options: PeertubePluginIndexList) | |||
27 | 27 | ||
28 | const uri = CONFIG.PLUGINS.INDEX.URL + '/api/v1/plugins' | 28 | const uri = CONFIG.PLUGINS.INDEX.URL + '/api/v1/plugins' |
29 | 29 | ||
30 | const { body } = await doRequest({ uri, qs, json: true }) | 30 | try { |
31 | const { body } = await doRequest({ uri, qs, json: true }) | ||
31 | 32 | ||
32 | logger.debug('Got result from PeerTube index.', { body }) | 33 | logger.debug('Got result from PeerTube index.', { body }) |
33 | 34 | ||
34 | await addInstanceInformation(body) | 35 | await addInstanceInformation(body) |
35 | 36 | ||
36 | return body as ResultList<PeerTubePluginIndex> | 37 | return body as ResultList<PeerTubePluginIndex> |
38 | } catch (err) { | ||
39 | logger.error('Cannot list available plugins from index %s.', uri, { err }) | ||
40 | return undefined | ||
41 | } | ||
37 | } | 42 | } |
38 | 43 | ||
39 | async function addInstanceInformation (result: ResultList<PeerTubePluginIndex>) { | 44 | async function addInstanceInformation (result: ResultList<PeerTubePluginIndex>) { |
@@ -53,7 +58,7 @@ async function getLatestPluginsVersion (npmNames: string[]): Promise<PeertubePlu | |||
53 | 58 | ||
54 | const uri = CONFIG.PLUGINS.INDEX.URL + '/api/v1/plugins/latest-version' | 59 | const uri = CONFIG.PLUGINS.INDEX.URL + '/api/v1/plugins/latest-version' |
55 | 60 | ||
56 | const { body } = await doRequest({ uri, body: bodyRequest }) | 61 | const { body } = await doRequest({ uri, body: bodyRequest, json: true, method: 'POST' }) |
57 | 62 | ||
58 | return body | 63 | return body |
59 | } | 64 | } |
diff --git a/server/lib/schedulers/plugins-check-scheduler.ts b/server/lib/schedulers/plugins-check-scheduler.ts index 9c60dbcd4..8dfdd5177 100644 --- a/server/lib/schedulers/plugins-check-scheduler.ts +++ b/server/lib/schedulers/plugins-check-scheduler.ts | |||
@@ -1,6 +1,5 @@ | |||
1 | import { logger } from '../../helpers/logger' | 1 | import { logger } from '../../helpers/logger' |
2 | import { AbstractScheduler } from './abstract-scheduler' | 2 | import { AbstractScheduler } from './abstract-scheduler' |
3 | import { retryTransactionWrapper } from '../../helpers/database-utils' | ||
4 | import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants' | 3 | import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants' |
5 | import { CONFIG } from '../../initializers/config' | 4 | import { CONFIG } from '../../initializers/config' |
6 | import { PluginModel } from '../../models/server/plugin' | 5 | import { PluginModel } from '../../models/server/plugin' |
@@ -19,13 +18,13 @@ export class PluginsCheckScheduler extends AbstractScheduler { | |||
19 | } | 18 | } |
20 | 19 | ||
21 | protected async internalExecute () { | 20 | protected async internalExecute () { |
22 | return retryTransactionWrapper(this.checkLatestPluginsVersion.bind(this)) | 21 | return this.checkLatestPluginsVersion() |
23 | } | 22 | } |
24 | 23 | ||
25 | private async checkLatestPluginsVersion () { | 24 | private async checkLatestPluginsVersion () { |
26 | if (CONFIG.PLUGINS.INDEX.ENABLED === false) return | 25 | if (CONFIG.PLUGINS.INDEX.ENABLED === false) return |
27 | 26 | ||
28 | logger.info('Checkin latest plugins version.') | 27 | logger.info('Checking latest plugins version.') |
29 | 28 | ||
30 | const plugins = await PluginModel.listInstalled() | 29 | const plugins = await PluginModel.listInstalled() |
31 | 30 | ||
@@ -39,19 +38,28 @@ export class PluginsCheckScheduler extends AbstractScheduler { | |||
39 | } | 38 | } |
40 | 39 | ||
41 | const npmNames = Object.keys(pluginIndex) | 40 | const npmNames = Object.keys(pluginIndex) |
42 | const results = await getLatestPluginsVersion(npmNames) | ||
43 | 41 | ||
44 | for (const result of results) { | 42 | try { |
45 | const plugin = pluginIndex[result.npmName] | 43 | const results = await getLatestPluginsVersion(npmNames) |
46 | if (!result.latestVersion) continue | ||
47 | 44 | ||
48 | if (plugin.latestVersion !== result.latestVersion && compareSemVer(plugin.latestVersion, result.latestVersion) < 0) { | 45 | for (const result of results) { |
49 | plugin.latestVersion = result.latestVersion | 46 | const plugin = pluginIndex[ result.npmName ] |
50 | await plugin.save() | 47 | if (!result.latestVersion) continue |
48 | |||
49 | if ( | ||
50 | !plugin.latestVersion || | ||
51 | (plugin.latestVersion !== result.latestVersion && compareSemVer(plugin.latestVersion, result.latestVersion) < 0) | ||
52 | ) { | ||
53 | plugin.latestVersion = result.latestVersion | ||
54 | await plugin.save() | ||
55 | |||
56 | logger.info('Plugin %s has a new latest version %s.', PluginModel.buildNpmName(plugin.name, plugin.type), plugin.latestVersion) | ||
57 | } | ||
51 | } | 58 | } |
59 | } catch (err) { | ||
60 | logger.error('Cannot get latest plugins version.', { npmNames, err }) | ||
52 | } | 61 | } |
53 | } | 62 | } |
54 | |||
55 | } | 63 | } |
56 | 64 | ||
57 | static get Instance () { | 65 | static get Instance () { |