aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/initializers
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-04-21 14:55:10 +0200
committerChocobozzz <chocobozzz@cpy.re>2023-05-09 08:57:34 +0200
commit0c9668f77901e7540e2c7045eb0f2974a4842a69 (patch)
tree226d3dd1565b0bb56588897af3b8530e6216e96b /server/initializers
parent6bcb854cdea8688a32240bc5719c7d139806e00b (diff)
downloadPeerTube-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.ts2
-rw-r--r--server/initializers/checker-before-init.ts10
-rw-r--r--server/initializers/config.ts12
-rw-r--r--server/initializers/constants.ts78
-rw-r--r--server/initializers/database.ts10
-rw-r--r--server/initializers/installer.ts16
-rw-r--r--server/initializers/migrations/0765-remote-transcoding.ts78
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 @@
1import config from 'config' 1import config from 'config'
2import { URL } from 'url' 2import { URL } from 'url'
3import { getFFmpegVersion } from '@server/helpers/ffmpeg'
4import { uniqify } from '@shared/core-utils' 3import { uniqify } from '@shared/core-utils'
4import { getFFmpegVersion } from '@shared/ffmpeg'
5import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' 5import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type'
6import { RecentlyAddedStrategy } from '../../shared/models/redundancy' 6import { RecentlyAddedStrategy } from '../../shared/models/redundancy'
7import { isProdInstance, parseBytes, parseSemVersion } from '../helpers/core-utils' 7import { 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 @@
1import { IConfig } from 'config' 1import { IConfig } from 'config'
2import { parseSemVersion, promisify0 } from '../helpers/core-utils' 2import { promisify0 } from '@shared/core-utils'
3import { parseSemVersion } from '../helpers/core-utils'
3import { logger } from '../helpers/logger' 4import { 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'
6import { 6import {
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
29const LAST_MIGRATION_VERSION = 760 30const 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
142const JOB_ATTEMPTS: { [id in JobType]: number } = { 149const 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
225const BROADCAST_CONCURRENCY = 30 // How many requests in parallel we do in activitypub-http-broadcast job
226const CRAWL_REQUEST_CONCURRENCY = 1 // How many requests in parallel to fetch remote data (likes, shares...)
227
228const 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
234const REQUEST_TIMEOUTS = {
235 DEFAULT: 7000, // 7 seconds
236 FILE: 30000, // 30 seconds
237 REDUNDANCY: JOB_TTL['video-redundancy']
238}
239
240const JOB_REMOVAL_OPTIONS = { 235const 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
257const VIDEO_IMPORT_TIMEOUT = Math.floor(JOB_TTL['video-import'] * 0.9) 252const VIDEO_IMPORT_TIMEOUT = Math.floor(JOB_TTL['video-import'] * 0.9)
258 253
254const RUNNER_JOBS = {
255 MAX_FAILURES: 5
256}
257
258// ---------------------------------------------------------------------------
259
260const BROADCAST_CONCURRENCY = 30 // How many requests in parallel we do in activitypub-http-broadcast job
261const CRAWL_REQUEST_CONCURRENCY = 1 // How many requests in parallel to fetch remote data (likes, shares...)
262
263const 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
269const REQUEST_TIMEOUTS = {
270 DEFAULT: 7000, // 7 seconds
271 FILE: 30000, // 30 seconds
272 REDUNDANCY: JOB_TTL['video-redundancy']
273}
274
259const SCHEDULER_INTERVALS_MS = { 275const 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
571const 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
543const MIMETYPES = { 582const 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}
599MIMETYPES.AUDIO.EXT_MIMETYPE = invert(MIMETYPES.AUDIO.MIMETYPE_EXT) 643MIMETYPES.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 @@
1import { QueryTypes, Transaction } from 'sequelize' 1import { QueryTypes, Transaction } from 'sequelize'
2import { Sequelize as SequelizeTypescript } from 'sequelize-typescript' 2import { Sequelize as SequelizeTypescript } from 'sequelize-typescript'
3import { ActorCustomPageModel } from '@server/models/account/actor-custom-page' 3import { ActorCustomPageModel } from '@server/models/account/actor-custom-page'
4import { RunnerModel } from '@server/models/runner/runner'
5import { RunnerJobModel } from '@server/models/runner/runner-job'
6import { RunnerRegistrationTokenModel } from '@server/models/runner/runner-registration-token'
4import { TrackerModel } from '@server/models/server/tracker' 7import { TrackerModel } from '@server/models/server/tracker'
5import { VideoTrackerModel } from '@server/models/server/video-tracker' 8import { VideoTrackerModel } from '@server/models/server/video-tracker'
6import { UserModel } from '@server/models/user/user' 9import { UserModel } from '@server/models/user/user'
@@ -9,6 +12,7 @@ import { UserRegistrationModel } from '@server/models/user/user-registration'
9import { UserVideoHistoryModel } from '@server/models/user/user-video-history' 12import { UserVideoHistoryModel } from '@server/models/user/user-video-history'
10import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync' 13import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync'
11import { VideoJobInfoModel } from '@server/models/video/video-job-info' 14import { VideoJobInfoModel } from '@server/models/video/video-job-info'
15import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting'
12import { VideoLiveSessionModel } from '@server/models/video/video-live-session' 16import { VideoLiveSessionModel } from '@server/models/video/video-live-session'
13import { VideoSourceModel } from '@server/models/video/video-source' 17import { VideoSourceModel } from '@server/models/video/video-source'
14import { LocalVideoViewerModel } from '@server/models/view/local-video-viewer' 18import { LocalVideoViewerModel } from '@server/models/view/local-video-viewer'
@@ -52,7 +56,6 @@ import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-pla
52import { VideoTagModel } from '../models/video/video-tag' 56import { VideoTagModel } from '../models/video/video-tag'
53import { VideoViewModel } from '../models/view/video-view' 57import { VideoViewModel } from '../models/view/video-view'
54import { CONFIG } from './config' 58import { CONFIG } from './config'
55import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting'
56 59
57require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string 60require('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'
2import passwordGenerator from 'password-generator' 2import passwordGenerator from 'password-generator'
3import { join } from 'path' 3import { join } from 'path'
4import { isTestOrDevInstance } from '@server/helpers/core-utils' 4import { isTestOrDevInstance } from '@server/helpers/core-utils'
5import { generateRunnerRegistrationToken } from '@server/helpers/token-generator'
5import { getNodeABIVersion } from '@server/helpers/version' 6import { getNodeABIVersion } from '@server/helpers/version'
7import { RunnerRegistrationTokenModel } from '@server/models/runner/runner-registration-token'
6import { UserRole } from '@shared/models' 8import { UserRole } from '@shared/models'
7import { logger } from '../helpers/logger' 9import { logger } from '../helpers/logger'
8import { buildUser, createApplicationActor, createUserAccountAndChannelAndPlaylist } from '../lib/user' 10import { 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
190async 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 @@
1import * as Sequelize from 'sequelize'
2
3async 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
71function down (options) {
72 throw new Error('Not implemented.')
73}
74
75export {
76 up,
77 down
78}