From 0c9668f77901e7540e2c7045eb0f2974a4842a69 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 21 Apr 2023 14:55:10 +0200 Subject: Implement remote runner jobs in server Move ffmpeg functions to @shared --- server/initializers/checker-after-init.ts | 2 +- server/initializers/checker-before-init.ts | 10 ++- server/initializers/config.ts | 12 ++++ server/initializers/constants.ts | 78 +++++++++++++++++----- server/initializers/database.ts | 10 ++- server/initializers/installer.ts | 16 ++++- .../migrations/0765-remote-transcoding.ts | 78 ++++++++++++++++++++++ 7 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 server/initializers/migrations/0765-remote-transcoding.ts (limited to 'server/initializers') 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 @@ import config from 'config' import { URL } from 'url' -import { getFFmpegVersion } from '@server/helpers/ffmpeg' import { uniqify } from '@shared/core-utils' +import { getFFmpegVersion } from '@shared/ffmpeg' import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' import { RecentlyAddedStrategy } from '../../shared/models/redundancy' 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 @@ import { IConfig } from 'config' -import { parseSemVersion, promisify0 } from '../helpers/core-utils' +import { promisify0 } from '@shared/core-utils' +import { parseSemVersion } from '../helpers/core-utils' import { logger } from '../helpers/logger' // Special behaviour for config because we can reload it @@ -36,7 +37,9 @@ function checkMissedConfig () { 'transcoding.profile', 'transcoding.concurrency', 'transcoding.resolutions.0p', 'transcoding.resolutions.144p', 'transcoding.resolutions.240p', 'transcoding.resolutions.360p', 'transcoding.resolutions.480p', 'transcoding.resolutions.720p', 'transcoding.resolutions.1080p', 'transcoding.resolutions.1440p', - 'transcoding.resolutions.2160p', 'transcoding.always_transcode_original_resolution', 'video_studio.enabled', + 'transcoding.resolutions.2160p', 'transcoding.always_transcode_original_resolution', 'transcoding.remote_runners.enabled', + 'video_studio.enabled', + 'remote_runners.stalled_jobs.vod', 'remote_runners.stalled_jobs.live', 'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'import.videos.timeout', 'import.video_channel_synchronization.enabled', 'import.video_channel_synchronization.max_per_user', 'import.video_channel_synchronization.check_interval', 'import.video_channel_synchronization.videos_limit_per_synchronization', @@ -74,7 +77,8 @@ function checkMissedConfig () { 'live.transcoding.enabled', 'live.transcoding.threads', 'live.transcoding.profile', 'live.transcoding.resolutions.144p', 'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', 'live.transcoding.resolutions.480p', 'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', - 'live.transcoding.resolutions.1440p', 'live.transcoding.resolutions.2160p', 'live.transcoding.always_transcode_original_resolution' + 'live.transcoding.resolutions.1440p', 'live.transcoding.resolutions.2160p', 'live.transcoding.always_transcode_original_resolution', + 'live.transcoding.remote_runners.enabled' ] 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 = { COUNT: config.get('feeds.comments.count') } }, + REMOTE_RUNNERS: { + STALLED_JOBS: { + LIVE: parseDurationToMs(config.get('remote_runners.stalled_jobs.live')), + VOD: parseDurationToMs(config.get('remote_runners.stalled_jobs.vod')) + } + }, ADMIN: { get EMAIL () { return config.get('admin.email') } }, @@ -359,6 +365,9 @@ const CONFIG = { }, WEBTORRENT: { get ENABLED () { return config.get('transcoding.webtorrent.enabled') } + }, + REMOTE_RUNNERS: { + get ENABLED () { return config.get('transcoding.remote_runners.enabled') } } }, LIVE: { @@ -406,6 +415,9 @@ const CONFIG = { get '1080p' () { return config.get('live.transcoding.resolutions.1080p') }, get '1440p' () { return config.get('live.transcoding.resolutions.1440p') }, get '2160p' () { return config.get('live.transcoding.resolutions.2160p') } + }, + REMOTE_RUNNERS: { + get ENABLED () { return config.get('live.transcoding.remote_runners.enabled') } } } }, 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' import { AbuseState, JobType, + RunnerJobState, UserRegistrationState, VideoChannelSyncState, VideoImportState, @@ -26,7 +27,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' // --------------------------------------------------------------------------- -const LAST_MIGRATION_VERSION = 760 +const LAST_MIGRATION_VERSION = 765 // --------------------------------------------------------------------------- @@ -81,6 +82,10 @@ const SORTABLE_COLUMNS = { USER_REGISTRATIONS: [ 'createdAt', 'state' ], + RUNNERS: [ 'createdAt' ], + RUNNER_REGISTRATION_TOKENS: [ 'createdAt' ], + RUNNER_JOBS: [ 'updatedAt', 'createdAt', 'priority', 'state', 'progress' ], + VIDEOS: [ 'name', 'duration', 'createdAt', 'publishedAt', 'originallyPublishedAt', 'views', 'likes', 'trending', 'hot', 'best' ], // Don't forget to update peertube-search-index with the same values @@ -139,6 +144,8 @@ const REMOTE_SCHEME = { WS: 'wss' } +// --------------------------------------------------------------------------- + const JOB_ATTEMPTS: { [id in JobType]: number } = { 'activitypub-http-broadcast': 1, 'activitypub-http-broadcast-parallel': 1, @@ -160,6 +167,7 @@ const JOB_ATTEMPTS: { [id in JobType]: number } = { 'video-channel-import': 1, 'after-video-channel-import': 1, 'move-to-object-storage': 3, + 'transcoding-job-builder': 1, 'notify': 1, 'federate-video': 1 } @@ -183,6 +191,7 @@ const JOB_CONCURRENCY: { [id in Exclude { + { + const query = ` + CREATE TABLE IF NOT EXISTS "runnerRegistrationToken"( + "id" serial, + "registrationToken" varchar(255) NOT NULL, + "createdAt" timestamp with time zone NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + PRIMARY KEY ("id") + ); + ` + + await utils.sequelize.query(query, { transaction : utils.transaction }) + } + + { + const query = ` + CREATE TABLE IF NOT EXISTS "runner"( + "id" serial, + "runnerToken" varchar(255) NOT NULL, + "name" varchar(255) NOT NULL, + "description" varchar(1000), + "lastContact" timestamp with time zone NOT NULL, + "ip" varchar(255) NOT NULL, + "runnerRegistrationTokenId" integer REFERENCES "runnerRegistrationToken"("id") ON DELETE CASCADE ON UPDATE CASCADE, + "createdAt" timestamp with time zone NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + PRIMARY KEY ("id") + ); + ` + + await utils.sequelize.query(query, { transaction : utils.transaction }) + } + + { + const query = ` + CREATE TABLE IF NOT EXISTS "runnerJob"( + "id" serial, + "uuid" uuid NOT NULL, + "type" varchar(255) NOT NULL, + "payload" jsonb NOT NULL, + "privatePayload" jsonb NOT NULL, + "state" integer NOT NULL, + "failures" integer NOT NULL DEFAULT 0, + "error" varchar(5000), + "priority" integer NOT NULL, + "processingJobToken" varchar(255), + "progress" integer, + "startedAt" timestamp with time zone, + "finishedAt" timestamp with time zone, + "dependsOnRunnerJobId" integer REFERENCES "runnerJob"("id") ON DELETE CASCADE ON UPDATE CASCADE, + "runnerId" integer REFERENCES "runner"("id") ON DELETE SET NULL ON UPDATE CASCADE, + "createdAt" timestamp with time zone NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + PRIMARY KEY ("id") + ); + + + ` + + await utils.sequelize.query(query, { transaction : utils.transaction }) + } +} + +function down (options) { + throw new Error('Not implemented.') +} + +export { + up, + down +} -- cgit v1.2.3