diff options
author | Chocobozzz <me@florianbigard.com> | 2023-04-21 14:55:10 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2023-05-09 08:57:34 +0200 |
commit | 0c9668f77901e7540e2c7045eb0f2974a4842a69 (patch) | |
tree | 226d3dd1565b0bb56588897af3b8530e6216e96b /server/initializers | |
parent | 6bcb854cdea8688a32240bc5719c7d139806e00b (diff) | |
download | PeerTube-0c9668f77901e7540e2c7045eb0f2974a4842a69.tar.gz PeerTube-0c9668f77901e7540e2c7045eb0f2974a4842a69.tar.zst PeerTube-0c9668f77901e7540e2c7045eb0f2974a4842a69.zip |
Implement remote runner jobs in server
Move ffmpeg functions to @shared
Diffstat (limited to 'server/initializers')
-rw-r--r-- | server/initializers/checker-after-init.ts | 2 | ||||
-rw-r--r-- | server/initializers/checker-before-init.ts | 10 | ||||
-rw-r--r-- | server/initializers/config.ts | 12 | ||||
-rw-r--r-- | server/initializers/constants.ts | 78 | ||||
-rw-r--r-- | server/initializers/database.ts | 10 | ||||
-rw-r--r-- | server/initializers/installer.ts | 16 | ||||
-rw-r--r-- | server/initializers/migrations/0765-remote-transcoding.ts | 78 |
7 files changed, 183 insertions, 23 deletions
diff --git a/server/initializers/checker-after-init.ts b/server/initializers/checker-after-init.ts index 14ed82cb4..68dea909d 100644 --- a/server/initializers/checker-after-init.ts +++ b/server/initializers/checker-after-init.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import config from 'config' | 1 | import config from 'config' |
2 | import { URL } from 'url' | 2 | import { URL } from 'url' |
3 | import { getFFmpegVersion } from '@server/helpers/ffmpeg' | ||
4 | import { uniqify } from '@shared/core-utils' | 3 | import { uniqify } from '@shared/core-utils' |
4 | import { getFFmpegVersion } from '@shared/ffmpeg' | ||
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 { RecentlyAddedStrategy } from '../../shared/models/redundancy' | 6 | import { RecentlyAddedStrategy } from '../../shared/models/redundancy' |
7 | import { isProdInstance, parseBytes, parseSemVersion } from '../helpers/core-utils' | 7 | import { isProdInstance, parseBytes, parseSemVersion } from '../helpers/core-utils' |
diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts index 49010c059..2361aa1eb 100644 --- a/server/initializers/checker-before-init.ts +++ b/server/initializers/checker-before-init.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { IConfig } from 'config' | 1 | import { IConfig } from 'config' |
2 | import { parseSemVersion, promisify0 } from '../helpers/core-utils' | 2 | import { promisify0 } from '@shared/core-utils' |
3 | import { parseSemVersion } from '../helpers/core-utils' | ||
3 | import { logger } from '../helpers/logger' | 4 | import { logger } from '../helpers/logger' |
4 | 5 | ||
5 | // Special behaviour for config because we can reload it | 6 | // Special behaviour for config because we can reload it |
@@ -36,7 +37,9 @@ function checkMissedConfig () { | |||
36 | 'transcoding.profile', 'transcoding.concurrency', | 37 | 'transcoding.profile', 'transcoding.concurrency', |
37 | 'transcoding.resolutions.0p', 'transcoding.resolutions.144p', 'transcoding.resolutions.240p', 'transcoding.resolutions.360p', | 38 | 'transcoding.resolutions.0p', 'transcoding.resolutions.144p', 'transcoding.resolutions.240p', 'transcoding.resolutions.360p', |
38 | 'transcoding.resolutions.480p', 'transcoding.resolutions.720p', 'transcoding.resolutions.1080p', 'transcoding.resolutions.1440p', | 39 | 'transcoding.resolutions.480p', 'transcoding.resolutions.720p', 'transcoding.resolutions.1080p', 'transcoding.resolutions.1440p', |
39 | 'transcoding.resolutions.2160p', 'transcoding.always_transcode_original_resolution', 'video_studio.enabled', | 40 | 'transcoding.resolutions.2160p', 'transcoding.always_transcode_original_resolution', 'transcoding.remote_runners.enabled', |
41 | 'video_studio.enabled', | ||
42 | 'remote_runners.stalled_jobs.vod', 'remote_runners.stalled_jobs.live', | ||
40 | 'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'import.videos.timeout', | 43 | 'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'import.videos.timeout', |
41 | 'import.video_channel_synchronization.enabled', 'import.video_channel_synchronization.max_per_user', | 44 | 'import.video_channel_synchronization.enabled', 'import.video_channel_synchronization.max_per_user', |
42 | 'import.video_channel_synchronization.check_interval', 'import.video_channel_synchronization.videos_limit_per_synchronization', | 45 | 'import.video_channel_synchronization.check_interval', 'import.video_channel_synchronization.videos_limit_per_synchronization', |
@@ -74,7 +77,8 @@ function checkMissedConfig () { | |||
74 | 'live.transcoding.enabled', 'live.transcoding.threads', 'live.transcoding.profile', | 77 | 'live.transcoding.enabled', 'live.transcoding.threads', 'live.transcoding.profile', |
75 | 'live.transcoding.resolutions.144p', 'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', | 78 | 'live.transcoding.resolutions.144p', 'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', |
76 | 'live.transcoding.resolutions.480p', 'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', | 79 | 'live.transcoding.resolutions.480p', 'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', |
77 | 'live.transcoding.resolutions.1440p', 'live.transcoding.resolutions.2160p', 'live.transcoding.always_transcode_original_resolution' | 80 | 'live.transcoding.resolutions.1440p', 'live.transcoding.resolutions.2160p', 'live.transcoding.always_transcode_original_resolution', |
81 | 'live.transcoding.remote_runners.enabled' | ||
78 | ] | 82 | ] |
79 | 83 | ||
80 | const requiredAlternatives = [ | 84 | const requiredAlternatives = [ |
diff --git a/server/initializers/config.ts b/server/initializers/config.ts index e2442213c..699dd4704 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts | |||
@@ -304,6 +304,12 @@ const CONFIG = { | |||
304 | COUNT: config.get<number>('feeds.comments.count') | 304 | COUNT: config.get<number>('feeds.comments.count') |
305 | } | 305 | } |
306 | }, | 306 | }, |
307 | REMOTE_RUNNERS: { | ||
308 | STALLED_JOBS: { | ||
309 | LIVE: parseDurationToMs(config.get<string>('remote_runners.stalled_jobs.live')), | ||
310 | VOD: parseDurationToMs(config.get<string>('remote_runners.stalled_jobs.vod')) | ||
311 | } | ||
312 | }, | ||
307 | ADMIN: { | 313 | ADMIN: { |
308 | get EMAIL () { return config.get<string>('admin.email') } | 314 | get EMAIL () { return config.get<string>('admin.email') } |
309 | }, | 315 | }, |
@@ -359,6 +365,9 @@ const CONFIG = { | |||
359 | }, | 365 | }, |
360 | WEBTORRENT: { | 366 | WEBTORRENT: { |
361 | get ENABLED () { return config.get<boolean>('transcoding.webtorrent.enabled') } | 367 | get ENABLED () { return config.get<boolean>('transcoding.webtorrent.enabled') } |
368 | }, | ||
369 | REMOTE_RUNNERS: { | ||
370 | get ENABLED () { return config.get<boolean>('transcoding.remote_runners.enabled') } | ||
362 | } | 371 | } |
363 | }, | 372 | }, |
364 | LIVE: { | 373 | LIVE: { |
@@ -406,6 +415,9 @@ const CONFIG = { | |||
406 | get '1080p' () { return config.get<boolean>('live.transcoding.resolutions.1080p') }, | 415 | get '1080p' () { return config.get<boolean>('live.transcoding.resolutions.1080p') }, |
407 | get '1440p' () { return config.get<boolean>('live.transcoding.resolutions.1440p') }, | 416 | get '1440p' () { return config.get<boolean>('live.transcoding.resolutions.1440p') }, |
408 | get '2160p' () { return config.get<boolean>('live.transcoding.resolutions.2160p') } | 417 | get '2160p' () { return config.get<boolean>('live.transcoding.resolutions.2160p') } |
418 | }, | ||
419 | REMOTE_RUNNERS: { | ||
420 | get ENABLED () { return config.get<boolean>('live.transcoding.remote_runners.enabled') } | ||
409 | } | 421 | } |
410 | } | 422 | } |
411 | }, | 423 | }, |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 6cad4eb23..279e77421 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -6,6 +6,7 @@ import { randomInt, root } from '@shared/core-utils' | |||
6 | import { | 6 | import { |
7 | AbuseState, | 7 | AbuseState, |
8 | JobType, | 8 | JobType, |
9 | RunnerJobState, | ||
9 | UserRegistrationState, | 10 | UserRegistrationState, |
10 | VideoChannelSyncState, | 11 | VideoChannelSyncState, |
11 | VideoImportState, | 12 | VideoImportState, |
@@ -26,7 +27,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' | |||
26 | 27 | ||
27 | // --------------------------------------------------------------------------- | 28 | // --------------------------------------------------------------------------- |
28 | 29 | ||
29 | const LAST_MIGRATION_VERSION = 760 | 30 | const LAST_MIGRATION_VERSION = 765 |
30 | 31 | ||
31 | // --------------------------------------------------------------------------- | 32 | // --------------------------------------------------------------------------- |
32 | 33 | ||
@@ -81,6 +82,10 @@ const SORTABLE_COLUMNS = { | |||
81 | 82 | ||
82 | USER_REGISTRATIONS: [ 'createdAt', 'state' ], | 83 | USER_REGISTRATIONS: [ 'createdAt', 'state' ], |
83 | 84 | ||
85 | RUNNERS: [ 'createdAt' ], | ||
86 | RUNNER_REGISTRATION_TOKENS: [ 'createdAt' ], | ||
87 | RUNNER_JOBS: [ 'updatedAt', 'createdAt', 'priority', 'state', 'progress' ], | ||
88 | |||
84 | VIDEOS: [ 'name', 'duration', 'createdAt', 'publishedAt', 'originallyPublishedAt', 'views', 'likes', 'trending', 'hot', 'best' ], | 89 | VIDEOS: [ 'name', 'duration', 'createdAt', 'publishedAt', 'originallyPublishedAt', 'views', 'likes', 'trending', 'hot', 'best' ], |
85 | 90 | ||
86 | // Don't forget to update peertube-search-index with the same values | 91 | // Don't forget to update peertube-search-index with the same values |
@@ -139,6 +144,8 @@ const REMOTE_SCHEME = { | |||
139 | WS: 'wss' | 144 | WS: 'wss' |
140 | } | 145 | } |
141 | 146 | ||
147 | // --------------------------------------------------------------------------- | ||
148 | |||
142 | const JOB_ATTEMPTS: { [id in JobType]: number } = { | 149 | const JOB_ATTEMPTS: { [id in JobType]: number } = { |
143 | 'activitypub-http-broadcast': 1, | 150 | 'activitypub-http-broadcast': 1, |
144 | 'activitypub-http-broadcast-parallel': 1, | 151 | 'activitypub-http-broadcast-parallel': 1, |
@@ -160,6 +167,7 @@ const JOB_ATTEMPTS: { [id in JobType]: number } = { | |||
160 | 'video-channel-import': 1, | 167 | 'video-channel-import': 1, |
161 | 'after-video-channel-import': 1, | 168 | 'after-video-channel-import': 1, |
162 | 'move-to-object-storage': 3, | 169 | 'move-to-object-storage': 3, |
170 | 'transcoding-job-builder': 1, | ||
163 | 'notify': 1, | 171 | 'notify': 1, |
164 | 'federate-video': 1 | 172 | 'federate-video': 1 |
165 | } | 173 | } |
@@ -183,6 +191,7 @@ const JOB_CONCURRENCY: { [id in Exclude<JobType, 'video-transcoding' | 'video-im | |||
183 | 'move-to-object-storage': 1, | 191 | 'move-to-object-storage': 1, |
184 | 'video-channel-import': 1, | 192 | 'video-channel-import': 1, |
185 | 'after-video-channel-import': 1, | 193 | 'after-video-channel-import': 1, |
194 | 'transcoding-job-builder': 1, | ||
186 | 'notify': 5, | 195 | 'notify': 5, |
187 | 'federate-video': 3 | 196 | 'federate-video': 3 |
188 | } | 197 | } |
@@ -207,6 +216,7 @@ const JOB_TTL: { [id in JobType]: number } = { | |||
207 | 'move-to-object-storage': 1000 * 60 * 60 * 3, // 3 hours | 216 | 'move-to-object-storage': 1000 * 60 * 60 * 3, // 3 hours |
208 | 'video-channel-import': 1000 * 60 * 60 * 4, // 4 hours | 217 | 'video-channel-import': 1000 * 60 * 60 * 4, // 4 hours |
209 | 'after-video-channel-import': 60000 * 5, // 5 minutes | 218 | 'after-video-channel-import': 60000 * 5, // 5 minutes |
219 | 'transcoding-job-builder': 60000, // 1 minute | ||
210 | 'notify': 60000 * 5, // 5 minutes | 220 | 'notify': 60000 * 5, // 5 minutes |
211 | 'federate-video': 60000 * 5 // 5 minutes | 221 | 'federate-video': 60000 * 5 // 5 minutes |
212 | } | 222 | } |
@@ -222,21 +232,6 @@ const JOB_PRIORITY = { | |||
222 | TRANSCODING: 100 | 232 | TRANSCODING: 100 |
223 | } | 233 | } |
224 | 234 | ||
225 | const BROADCAST_CONCURRENCY = 30 // How many requests in parallel we do in activitypub-http-broadcast job | ||
226 | const CRAWL_REQUEST_CONCURRENCY = 1 // How many requests in parallel to fetch remote data (likes, shares...) | ||
227 | |||
228 | const AP_CLEANER = { | ||
229 | CONCURRENCY: 10, // How many requests in parallel we do in activitypub-cleaner job | ||
230 | UNAVAILABLE_TRESHOLD: 3, // How many attempts we do before removing an unavailable remote resource | ||
231 | PERIOD: parseDurationToMs('1 week') // /!\ Has to be sync with REPEAT_JOBS | ||
232 | } | ||
233 | |||
234 | const REQUEST_TIMEOUTS = { | ||
235 | DEFAULT: 7000, // 7 seconds | ||
236 | FILE: 30000, // 30 seconds | ||
237 | REDUNDANCY: JOB_TTL['video-redundancy'] | ||
238 | } | ||
239 | |||
240 | const JOB_REMOVAL_OPTIONS = { | 235 | const JOB_REMOVAL_OPTIONS = { |
241 | COUNT: 10000, // Max jobs to store | 236 | COUNT: 10000, // Max jobs to store |
242 | 237 | ||
@@ -256,7 +251,29 @@ const JOB_REMOVAL_OPTIONS = { | |||
256 | 251 | ||
257 | const VIDEO_IMPORT_TIMEOUT = Math.floor(JOB_TTL['video-import'] * 0.9) | 252 | const VIDEO_IMPORT_TIMEOUT = Math.floor(JOB_TTL['video-import'] * 0.9) |
258 | 253 | ||
254 | const RUNNER_JOBS = { | ||
255 | MAX_FAILURES: 5 | ||
256 | } | ||
257 | |||
258 | // --------------------------------------------------------------------------- | ||
259 | |||
260 | const BROADCAST_CONCURRENCY = 30 // How many requests in parallel we do in activitypub-http-broadcast job | ||
261 | const CRAWL_REQUEST_CONCURRENCY = 1 // How many requests in parallel to fetch remote data (likes, shares...) | ||
262 | |||
263 | const AP_CLEANER = { | ||
264 | CONCURRENCY: 10, // How many requests in parallel we do in activitypub-cleaner job | ||
265 | UNAVAILABLE_TRESHOLD: 3, // How many attempts we do before removing an unavailable remote resource | ||
266 | PERIOD: parseDurationToMs('1 week') // /!\ Has to be sync with REPEAT_JOBS | ||
267 | } | ||
268 | |||
269 | const REQUEST_TIMEOUTS = { | ||
270 | DEFAULT: 7000, // 7 seconds | ||
271 | FILE: 30000, // 30 seconds | ||
272 | REDUNDANCY: JOB_TTL['video-redundancy'] | ||
273 | } | ||
274 | |||
259 | const SCHEDULER_INTERVALS_MS = { | 275 | const SCHEDULER_INTERVALS_MS = { |
276 | RUNNER_JOB_WATCH_DOG: Math.min(CONFIG.REMOTE_RUNNERS.STALLED_JOBS.VOD, CONFIG.REMOTE_RUNNERS.STALLED_JOBS.LIVE), | ||
260 | ACTOR_FOLLOW_SCORES: 60000 * 60, // 1 hour | 277 | ACTOR_FOLLOW_SCORES: 60000 * 60, // 1 hour |
261 | REMOVE_OLD_JOBS: 60000 * 60, // 1 hour | 278 | REMOVE_OLD_JOBS: 60000 * 60, // 1 hour |
262 | UPDATE_VIDEOS: 60000, // 1 minute | 279 | UPDATE_VIDEOS: 60000, // 1 minute |
@@ -410,6 +427,17 @@ const CONSTRAINTS_FIELDS = { | |||
410 | CLIENT_STACK_TRACE: { min: 1, max: 15000 }, // Length | 427 | CLIENT_STACK_TRACE: { min: 1, max: 15000 }, // Length |
411 | CLIENT_META: { min: 1, max: 5000 }, // Length | 428 | CLIENT_META: { min: 1, max: 5000 }, // Length |
412 | CLIENT_USER_AGENT: { min: 1, max: 200 } // Length | 429 | CLIENT_USER_AGENT: { min: 1, max: 200 } // Length |
430 | }, | ||
431 | RUNNERS: { | ||
432 | TOKEN: { min: 1, max: 1000 }, // Length | ||
433 | NAME: { min: 1, max: 100 }, // Length | ||
434 | DESCRIPTION: { min: 1, max: 1000 } // Length | ||
435 | }, | ||
436 | RUNNER_JOBS: { | ||
437 | TOKEN: { min: 1, max: 1000 }, // Length | ||
438 | REASON: { min: 1, max: 5000 }, // Length | ||
439 | ERROR_MESSAGE: { min: 1, max: 5000 }, // Length | ||
440 | PROGRESS: { min: 0, max: 100 } // Value | ||
413 | } | 441 | } |
414 | } | 442 | } |
415 | 443 | ||
@@ -540,6 +568,17 @@ const VIDEO_PLAYLIST_TYPES: { [ id in VideoPlaylistType ]: string } = { | |||
540 | [VideoPlaylistType.WATCH_LATER]: 'Watch later' | 568 | [VideoPlaylistType.WATCH_LATER]: 'Watch later' |
541 | } | 569 | } |
542 | 570 | ||
571 | const RUNNER_JOB_STATES: { [ id in RunnerJobState ]: string } = { | ||
572 | [RunnerJobState.PROCESSING]: 'Processing', | ||
573 | [RunnerJobState.COMPLETED]: 'Completed', | ||
574 | [RunnerJobState.PENDING]: 'Pending', | ||
575 | [RunnerJobState.ERRORED]: 'Errored', | ||
576 | [RunnerJobState.WAITING_FOR_PARENT_JOB]: 'Waiting for parent job to finish', | ||
577 | [RunnerJobState.CANCELLED]: 'Cancelled', | ||
578 | [RunnerJobState.PARENT_ERRORED]: 'Parent job failed', | ||
579 | [RunnerJobState.PARENT_CANCELLED]: 'Parent job cancelled' | ||
580 | } | ||
581 | |||
543 | const MIMETYPES = { | 582 | const MIMETYPES = { |
544 | AUDIO: { | 583 | AUDIO: { |
545 | MIMETYPE_EXT: { | 584 | MIMETYPE_EXT: { |
@@ -594,6 +633,11 @@ const MIMETYPES = { | |||
594 | MIMETYPE_EXT: { | 633 | MIMETYPE_EXT: { |
595 | 'application/x-bittorrent': '.torrent' | 634 | 'application/x-bittorrent': '.torrent' |
596 | } | 635 | } |
636 | }, | ||
637 | M3U8: { | ||
638 | MIMETYPE_EXT: { | ||
639 | 'application/vnd.apple.mpegurl': '.m3u8' | ||
640 | } | ||
597 | } | 641 | } |
598 | } | 642 | } |
599 | MIMETYPES.AUDIO.EXT_MIMETYPE = invert(MIMETYPES.AUDIO.MIMETYPE_EXT) | 643 | MIMETYPES.AUDIO.EXT_MIMETYPE = invert(MIMETYPES.AUDIO.MIMETYPE_EXT) |
@@ -1027,6 +1071,7 @@ export { | |||
1027 | SEARCH_INDEX, | 1071 | SEARCH_INDEX, |
1028 | DIRECTORIES, | 1072 | DIRECTORIES, |
1029 | RESUMABLE_UPLOAD_SESSION_LIFETIME, | 1073 | RESUMABLE_UPLOAD_SESSION_LIFETIME, |
1074 | RUNNER_JOB_STATES, | ||
1030 | P2P_MEDIA_LOADER_PEER_VERSION, | 1075 | P2P_MEDIA_LOADER_PEER_VERSION, |
1031 | ACTOR_IMAGES_SIZE, | 1076 | ACTOR_IMAGES_SIZE, |
1032 | ACCEPT_HEADERS, | 1077 | ACCEPT_HEADERS, |
@@ -1085,6 +1130,7 @@ export { | |||
1085 | USER_REGISTRATION_STATES, | 1130 | USER_REGISTRATION_STATES, |
1086 | LRU_CACHE, | 1131 | LRU_CACHE, |
1087 | REQUEST_TIMEOUTS, | 1132 | REQUEST_TIMEOUTS, |
1133 | RUNNER_JOBS, | ||
1088 | MAX_LOCAL_VIEWER_WATCH_SECTIONS, | 1134 | MAX_LOCAL_VIEWER_WATCH_SECTIONS, |
1089 | USER_PASSWORD_RESET_LIFETIME, | 1135 | USER_PASSWORD_RESET_LIFETIME, |
1090 | USER_PASSWORD_CREATE_LIFETIME, | 1136 | USER_PASSWORD_CREATE_LIFETIME, |
diff --git a/server/initializers/database.ts b/server/initializers/database.ts index 3f31099ed..14dd8c379 100644 --- a/server/initializers/database.ts +++ b/server/initializers/database.ts | |||
@@ -1,6 +1,9 @@ | |||
1 | import { QueryTypes, Transaction } from 'sequelize' | 1 | import { QueryTypes, Transaction } from 'sequelize' |
2 | import { Sequelize as SequelizeTypescript } from 'sequelize-typescript' | 2 | import { Sequelize as SequelizeTypescript } from 'sequelize-typescript' |
3 | import { ActorCustomPageModel } from '@server/models/account/actor-custom-page' | 3 | import { ActorCustomPageModel } from '@server/models/account/actor-custom-page' |
4 | import { RunnerModel } from '@server/models/runner/runner' | ||
5 | import { RunnerJobModel } from '@server/models/runner/runner-job' | ||
6 | import { RunnerRegistrationTokenModel } from '@server/models/runner/runner-registration-token' | ||
4 | import { TrackerModel } from '@server/models/server/tracker' | 7 | import { TrackerModel } from '@server/models/server/tracker' |
5 | import { VideoTrackerModel } from '@server/models/server/video-tracker' | 8 | import { VideoTrackerModel } from '@server/models/server/video-tracker' |
6 | import { UserModel } from '@server/models/user/user' | 9 | import { UserModel } from '@server/models/user/user' |
@@ -9,6 +12,7 @@ import { UserRegistrationModel } from '@server/models/user/user-registration' | |||
9 | import { UserVideoHistoryModel } from '@server/models/user/user-video-history' | 12 | import { UserVideoHistoryModel } from '@server/models/user/user-video-history' |
10 | import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync' | 13 | import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync' |
11 | import { VideoJobInfoModel } from '@server/models/video/video-job-info' | 14 | import { VideoJobInfoModel } from '@server/models/video/video-job-info' |
15 | import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting' | ||
12 | import { VideoLiveSessionModel } from '@server/models/video/video-live-session' | 16 | import { VideoLiveSessionModel } from '@server/models/video/video-live-session' |
13 | import { VideoSourceModel } from '@server/models/video/video-source' | 17 | import { VideoSourceModel } from '@server/models/video/video-source' |
14 | import { LocalVideoViewerModel } from '@server/models/view/local-video-viewer' | 18 | import { LocalVideoViewerModel } from '@server/models/view/local-video-viewer' |
@@ -52,7 +56,6 @@ import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-pla | |||
52 | import { VideoTagModel } from '../models/video/video-tag' | 56 | import { VideoTagModel } from '../models/video/video-tag' |
53 | import { VideoViewModel } from '../models/view/video-view' | 57 | import { VideoViewModel } from '../models/view/video-view' |
54 | import { CONFIG } from './config' | 58 | import { CONFIG } from './config' |
55 | import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting' | ||
56 | 59 | ||
57 | require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string | 60 | require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string |
58 | 61 | ||
@@ -159,7 +162,10 @@ async function initDatabaseModels (silent: boolean) { | |||
159 | ActorCustomPageModel, | 162 | ActorCustomPageModel, |
160 | VideoJobInfoModel, | 163 | VideoJobInfoModel, |
161 | VideoChannelSyncModel, | 164 | VideoChannelSyncModel, |
162 | UserRegistrationModel | 165 | UserRegistrationModel, |
166 | RunnerRegistrationTokenModel, | ||
167 | RunnerModel, | ||
168 | RunnerJobModel | ||
163 | ]) | 169 | ]) |
164 | 170 | ||
165 | // Check extensions exist in the database | 171 | // Check extensions exist in the database |
diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index f48f348a7..2406a5936 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts | |||
@@ -2,7 +2,9 @@ import { ensureDir, readdir, remove } from 'fs-extra' | |||
2 | import passwordGenerator from 'password-generator' | 2 | import passwordGenerator from 'password-generator' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { isTestOrDevInstance } from '@server/helpers/core-utils' | 4 | import { isTestOrDevInstance } from '@server/helpers/core-utils' |
5 | import { generateRunnerRegistrationToken } from '@server/helpers/token-generator' | ||
5 | import { getNodeABIVersion } from '@server/helpers/version' | 6 | import { getNodeABIVersion } from '@server/helpers/version' |
7 | import { RunnerRegistrationTokenModel } from '@server/models/runner/runner-registration-token' | ||
6 | import { UserRole } from '@shared/models' | 8 | import { UserRole } from '@shared/models' |
7 | import { logger } from '../helpers/logger' | 9 | import { logger } from '../helpers/logger' |
8 | import { buildUser, createApplicationActor, createUserAccountAndChannelAndPlaylist } from '../lib/user' | 10 | import { buildUser, createApplicationActor, createUserAccountAndChannelAndPlaylist } from '../lib/user' |
@@ -22,7 +24,8 @@ async function installApplication () { | |||
22 | return Promise.all([ | 24 | return Promise.all([ |
23 | createApplicationIfNotExist(), | 25 | createApplicationIfNotExist(), |
24 | createOAuthClientIfNotExist(), | 26 | createOAuthClientIfNotExist(), |
25 | createOAuthAdminIfNotExist() | 27 | createOAuthAdminIfNotExist(), |
28 | createRunnerRegistrationTokenIfNotExist() | ||
26 | ]) | 29 | ]) |
27 | }), | 30 | }), |
28 | 31 | ||
@@ -183,3 +186,14 @@ async function createApplicationIfNotExist () { | |||
183 | 186 | ||
184 | return createApplicationActor(application.id) | 187 | return createApplicationActor(application.id) |
185 | } | 188 | } |
189 | |||
190 | async function createRunnerRegistrationTokenIfNotExist () { | ||
191 | const total = await RunnerRegistrationTokenModel.countTotal() | ||
192 | if (total !== 0) return undefined | ||
193 | |||
194 | const token = new RunnerRegistrationTokenModel({ | ||
195 | registrationToken: generateRunnerRegistrationToken() | ||
196 | }) | ||
197 | |||
198 | await token.save() | ||
199 | } | ||
diff --git a/server/initializers/migrations/0765-remote-transcoding.ts b/server/initializers/migrations/0765-remote-transcoding.ts new file mode 100644 index 000000000..40cca03b4 --- /dev/null +++ b/server/initializers/migrations/0765-remote-transcoding.ts | |||
@@ -0,0 +1,78 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | async function up (utils: { | ||
4 | transaction: Sequelize.Transaction | ||
5 | queryInterface: Sequelize.QueryInterface | ||
6 | sequelize: Sequelize.Sequelize | ||
7 | }): Promise<void> { | ||
8 | { | ||
9 | const query = ` | ||
10 | CREATE TABLE IF NOT EXISTS "runnerRegistrationToken"( | ||
11 | "id" serial, | ||
12 | "registrationToken" varchar(255) NOT NULL, | ||
13 | "createdAt" timestamp with time zone NOT NULL, | ||
14 | "updatedAt" timestamp with time zone NOT NULL, | ||
15 | PRIMARY KEY ("id") | ||
16 | ); | ||
17 | ` | ||
18 | |||
19 | await utils.sequelize.query(query, { transaction : utils.transaction }) | ||
20 | } | ||
21 | |||
22 | { | ||
23 | const query = ` | ||
24 | CREATE TABLE IF NOT EXISTS "runner"( | ||
25 | "id" serial, | ||
26 | "runnerToken" varchar(255) NOT NULL, | ||
27 | "name" varchar(255) NOT NULL, | ||
28 | "description" varchar(1000), | ||
29 | "lastContact" timestamp with time zone NOT NULL, | ||
30 | "ip" varchar(255) NOT NULL, | ||
31 | "runnerRegistrationTokenId" integer REFERENCES "runnerRegistrationToken"("id") ON DELETE CASCADE ON UPDATE CASCADE, | ||
32 | "createdAt" timestamp with time zone NOT NULL, | ||
33 | "updatedAt" timestamp with time zone NOT NULL, | ||
34 | PRIMARY KEY ("id") | ||
35 | ); | ||
36 | ` | ||
37 | |||
38 | await utils.sequelize.query(query, { transaction : utils.transaction }) | ||
39 | } | ||
40 | |||
41 | { | ||
42 | const query = ` | ||
43 | CREATE TABLE IF NOT EXISTS "runnerJob"( | ||
44 | "id" serial, | ||
45 | "uuid" uuid NOT NULL, | ||
46 | "type" varchar(255) NOT NULL, | ||
47 | "payload" jsonb NOT NULL, | ||
48 | "privatePayload" jsonb NOT NULL, | ||
49 | "state" integer NOT NULL, | ||
50 | "failures" integer NOT NULL DEFAULT 0, | ||
51 | "error" varchar(5000), | ||
52 | "priority" integer NOT NULL, | ||
53 | "processingJobToken" varchar(255), | ||
54 | "progress" integer, | ||
55 | "startedAt" timestamp with time zone, | ||
56 | "finishedAt" timestamp with time zone, | ||
57 | "dependsOnRunnerJobId" integer REFERENCES "runnerJob"("id") ON DELETE CASCADE ON UPDATE CASCADE, | ||
58 | "runnerId" integer REFERENCES "runner"("id") ON DELETE SET NULL ON UPDATE CASCADE, | ||
59 | "createdAt" timestamp with time zone NOT NULL, | ||
60 | "updatedAt" timestamp with time zone NOT NULL, | ||
61 | PRIMARY KEY ("id") | ||
62 | ); | ||
63 | |||
64 | |||
65 | ` | ||
66 | |||
67 | await utils.sequelize.query(query, { transaction : utils.transaction }) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | function down (options) { | ||
72 | throw new Error('Not implemented.') | ||
73 | } | ||
74 | |||
75 | export { | ||
76 | up, | ||
77 | down | ||
78 | } | ||