aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/lib/redundancy.ts11
-rw-r--r--server/lib/schedulers/videos-redundancy-scheduler.ts54
-rw-r--r--server/models/redundancy/video-redundancy.ts9
3 files changed, 51 insertions, 23 deletions
diff --git a/server/lib/redundancy.ts b/server/lib/redundancy.ts
index 2a9241249..2613d01be 100644
--- a/server/lib/redundancy.ts
+++ b/server/lib/redundancy.ts
@@ -1,5 +1,5 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { logger } from '@server/helpers/logger' 2import { logger, loggerTagsFactory } from '@server/helpers/logger'
3import { CONFIG } from '@server/initializers/config' 3import { CONFIG } from '@server/initializers/config'
4import { ActorFollowModel } from '@server/models/actor/actor-follow' 4import { ActorFollowModel } from '@server/models/actor/actor-follow'
5import { getServerActor } from '@server/models/application/application' 5import { getServerActor } from '@server/models/application/application'
@@ -8,6 +8,8 @@ import { Activity } from '@shared/models'
8import { VideoRedundancyModel } from '../models/redundancy/video-redundancy' 8import { VideoRedundancyModel } from '../models/redundancy/video-redundancy'
9import { sendUndoCacheFile } from './activitypub/send' 9import { sendUndoCacheFile } from './activitypub/send'
10 10
11const lTags = loggerTagsFactory('redundancy')
12
11async function removeVideoRedundancy (videoRedundancy: MVideoRedundancyVideo, t?: Transaction) { 13async function removeVideoRedundancy (videoRedundancy: MVideoRedundancyVideo, t?: Transaction) {
12 const serverActor = await getServerActor() 14 const serverActor = await getServerActor()
13 15
@@ -28,7 +30,7 @@ async function removeRedundanciesOfServer (serverId: number) {
28async function isRedundancyAccepted (activity: Activity, byActor: MActorSignature) { 30async function isRedundancyAccepted (activity: Activity, byActor: MActorSignature) {
29 const configAcceptFrom = CONFIG.REMOTE_REDUNDANCY.VIDEOS.ACCEPT_FROM 31 const configAcceptFrom = CONFIG.REMOTE_REDUNDANCY.VIDEOS.ACCEPT_FROM
30 if (configAcceptFrom === 'nobody') { 32 if (configAcceptFrom === 'nobody') {
31 logger.info('Do not accept remote redundancy %s due instance accept policy.', activity.id) 33 logger.info('Do not accept remote redundancy %s due instance accept policy.', activity.id, lTags())
32 return false 34 return false
33 } 35 }
34 36
@@ -37,7 +39,10 @@ async function isRedundancyAccepted (activity: Activity, byActor: MActorSignatur
37 const allowed = await ActorFollowModel.isFollowedBy(byActor.id, serverActor.id) 39 const allowed = await ActorFollowModel.isFollowedBy(byActor.id, serverActor.id)
38 40
39 if (allowed !== true) { 41 if (allowed !== true) {
40 logger.info('Do not accept remote redundancy %s because actor %s is not followed by our instance.', activity.id, byActor.url) 42 logger.info(
43 'Do not accept remote redundancy %s because actor %s is not followed by our instance.',
44 activity.id, byActor.url, lTags()
45 )
41 return false 46 return false
42 } 47 }
43 } 48 }
diff --git a/server/lib/schedulers/videos-redundancy-scheduler.ts b/server/lib/schedulers/videos-redundancy-scheduler.ts
index ebfd015b5..d9988157d 100644
--- a/server/lib/schedulers/videos-redundancy-scheduler.ts
+++ b/server/lib/schedulers/videos-redundancy-scheduler.ts
@@ -14,7 +14,7 @@ import {
14 MVideoWithAllFiles 14 MVideoWithAllFiles
15} from '@server/types/models' 15} from '@server/types/models'
16import { VideosRedundancyStrategy } from '../../../shared/models/redundancy' 16import { VideosRedundancyStrategy } from '../../../shared/models/redundancy'
17import { logger } from '../../helpers/logger' 17import { logger, loggerTagsFactory } from '../../helpers/logger'
18import { downloadWebTorrentVideo, generateMagnetUri } from '../../helpers/webtorrent' 18import { downloadWebTorrentVideo, generateMagnetUri } from '../../helpers/webtorrent'
19import { CONFIG } from '../../initializers/config' 19import { CONFIG } from '../../initializers/config'
20import { HLS_REDUNDANCY_DIRECTORY, REDUNDANCY, VIDEO_IMPORT_TIMEOUT } from '../../initializers/constants' 20import { HLS_REDUNDANCY_DIRECTORY, REDUNDANCY, VIDEO_IMPORT_TIMEOUT } from '../../initializers/constants'
@@ -27,6 +27,8 @@ import { removeVideoRedundancy } from '../redundancy'
27import { generateHLSRedundancyUrl, generateWebTorrentRedundancyUrl } from '../video-urls' 27import { generateHLSRedundancyUrl, generateWebTorrentRedundancyUrl } from '../video-urls'
28import { AbstractScheduler } from './abstract-scheduler' 28import { AbstractScheduler } from './abstract-scheduler'
29 29
30const lTags = loggerTagsFactory('redundancy')
31
30type CandidateToDuplicate = { 32type CandidateToDuplicate = {
31 redundancy: VideosRedundancyStrategy 33 redundancy: VideosRedundancyStrategy
32 video: MVideoWithAllFiles 34 video: MVideoWithAllFiles
@@ -54,7 +56,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
54 const videoToDuplicate = await VideoModel.loadWithFiles(videoId) 56 const videoToDuplicate = await VideoModel.loadWithFiles(videoId)
55 57
56 if (!videoToDuplicate) { 58 if (!videoToDuplicate) {
57 logger.warn('Video to manually duplicate %d does not exist anymore.', videoId) 59 logger.warn('Video to manually duplicate %d does not exist anymore.', videoId, lTags())
58 return 60 return
59 } 61 }
60 62
@@ -68,7 +70,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
68 70
69 protected async internalExecute () { 71 protected async internalExecute () {
70 for (const redundancyConfig of CONFIG.REDUNDANCY.VIDEOS.STRATEGIES) { 72 for (const redundancyConfig of CONFIG.REDUNDANCY.VIDEOS.STRATEGIES) {
71 logger.info('Running redundancy scheduler for strategy %s.', redundancyConfig.strategy) 73 logger.info('Running redundancy scheduler for strategy %s.', redundancyConfig.strategy, lTags())
72 74
73 try { 75 try {
74 const videoToDuplicate = await this.findVideoToDuplicate(redundancyConfig) 76 const videoToDuplicate = await this.findVideoToDuplicate(redundancyConfig)
@@ -84,15 +86,18 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
84 await this.purgeCacheIfNeeded(candidateToDuplicate) 86 await this.purgeCacheIfNeeded(candidateToDuplicate)
85 87
86 if (await this.isTooHeavy(candidateToDuplicate)) { 88 if (await this.isTooHeavy(candidateToDuplicate)) {
87 logger.info('Video %s is too big for our cache, skipping.', videoToDuplicate.url) 89 logger.info('Video %s is too big for our cache, skipping.', videoToDuplicate.url, lTags(videoToDuplicate.uuid))
88 continue 90 continue
89 } 91 }
90 92
91 logger.info('Will duplicate video %s in redundancy scheduler "%s".', videoToDuplicate.url, redundancyConfig.strategy) 93 logger.info(
94 'Will duplicate video %s in redundancy scheduler "%s".',
95 videoToDuplicate.url, redundancyConfig.strategy, lTags(videoToDuplicate.uuid)
96 )
92 97
93 await this.createVideoRedundancies(candidateToDuplicate) 98 await this.createVideoRedundancies(candidateToDuplicate)
94 } catch (err) { 99 } catch (err) {
95 logger.error('Cannot run videos redundancy %s.', redundancyConfig.strategy, { err }) 100 logger.error('Cannot run videos redundancy %s.', redundancyConfig.strategy, { err, ...lTags() })
96 } 101 }
97 } 102 }
98 103
@@ -120,15 +125,19 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
120 125
121 // If the administrator disabled the redundancy or decreased the cache size, remove this redundancy instead of extending it 126 // If the administrator disabled the redundancy or decreased the cache size, remove this redundancy instead of extending it
122 if (!redundancyConfig || await this.isTooHeavy(candidate)) { 127 if (!redundancyConfig || await this.isTooHeavy(candidate)) {
123 logger.info('Destroying redundancy %s because the cache size %s is too heavy.', redundancyModel.url, redundancyModel.strategy) 128 logger.info(
129 'Destroying redundancy %s because the cache size %s is too heavy.',
130 redundancyModel.url, redundancyModel.strategy, lTags(candidate.video.uuid)
131 )
132
124 await removeVideoRedundancy(redundancyModel) 133 await removeVideoRedundancy(redundancyModel)
125 } else { 134 } else {
126 await this.extendsRedundancy(redundancyModel) 135 await this.extendsRedundancy(redundancyModel)
127 } 136 }
128 } catch (err) { 137 } catch (err) {
129 logger.error( 138 logger.error(
130 'Cannot extend or remove expiration of %s video from our redundancy system.', this.buildEntryLogId(redundancyModel), 139 'Cannot extend or remove expiration of %s video from our redundancy system.',
131 { err } 140 this.buildEntryLogId(redundancyModel), { err, ...lTags(redundancyModel.getVideoUUID()) }
132 ) 141 )
133 } 142 }
134 } 143 }
@@ -152,7 +161,10 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
152 try { 161 try {
153 await removeVideoRedundancy(redundancyModel) 162 await removeVideoRedundancy(redundancyModel)
154 } catch (err) { 163 } catch (err) {
155 logger.error('Cannot remove redundancy %s from our redundancy system.', this.buildEntryLogId(redundancyModel)) 164 logger.error(
165 'Cannot remove redundancy %s from our redundancy system.',
166 this.buildEntryLogId(redundancyModel), lTags(redundancyModel.getVideoUUID())
167 )
156 } 168 }
157 } 169 }
158 } 170 }
@@ -176,7 +188,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
176 const video = await this.loadAndRefreshVideo(data.video.url) 188 const video = await this.loadAndRefreshVideo(data.video.url)
177 189
178 if (!video) { 190 if (!video) {
179 logger.info('Video %s we want to duplicate does not existing anymore, skipping.', data.video.url) 191 logger.info('Video %s we want to duplicate does not existing anymore, skipping.', data.video.url, lTags(data.video.uuid))
180 192
181 return 193 return
182 } 194 }
@@ -218,7 +230,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
218 230
219 const serverActor = await getServerActor() 231 const serverActor = await getServerActor()
220 232
221 logger.info('Duplicating %s - %d in videos redundancy with "%s" strategy.', video.url, file.resolution, strategy) 233 logger.info('Duplicating %s - %d in videos redundancy with "%s" strategy.', video.url, file.resolution, strategy, lTags(video.uuid))
222 234
223 const trackerUrls = await TrackerModel.listUrlsByVideoId(video.id) 235 const trackerUrls = await TrackerModel.listUrlsByVideoId(video.id)
224 const magnetUri = generateMagnetUri(video, file, trackerUrls) 236 const magnetUri = generateMagnetUri(video, file, trackerUrls)
@@ -241,7 +253,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
241 253
242 await sendCreateCacheFile(serverActor, video, createdModel) 254 await sendCreateCacheFile(serverActor, video, createdModel)
243 255
244 logger.info('Duplicated %s - %d -> %s.', video.url, file.resolution, createdModel.url) 256 logger.info('Duplicated %s - %d -> %s.', video.url, file.resolution, createdModel.url, lTags(video.uuid))
245 } 257 }
246 258
247 private async createStreamingPlaylistRedundancy ( 259 private async createStreamingPlaylistRedundancy (
@@ -260,7 +272,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
260 const playlist = Object.assign(playlistArg, { Video: video }) 272 const playlist = Object.assign(playlistArg, { Video: video })
261 const serverActor = await getServerActor() 273 const serverActor = await getServerActor()
262 274
263 logger.info('Duplicating %s streaming playlist in videos redundancy with "%s" strategy.', video.url, strategy) 275 logger.info('Duplicating %s streaming playlist in videos redundancy with "%s" strategy.', video.url, strategy, lTags(video.uuid))
264 276
265 const destDirectory = join(HLS_REDUNDANCY_DIRECTORY, video.uuid) 277 const destDirectory = join(HLS_REDUNDANCY_DIRECTORY, video.uuid)
266 const masterPlaylistUrl = playlist.getMasterPlaylistUrl(video) 278 const masterPlaylistUrl = playlist.getMasterPlaylistUrl(video)
@@ -282,11 +294,11 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
282 294
283 await sendCreateCacheFile(serverActor, video, createdModel) 295 await sendCreateCacheFile(serverActor, video, createdModel)
284 296
285 logger.info('Duplicated playlist %s -> %s.', masterPlaylistUrl, createdModel.url) 297 logger.info('Duplicated playlist %s -> %s.', masterPlaylistUrl, createdModel.url, lTags(video.uuid))
286 } 298 }
287 299
288 private async extendsExpirationOf (redundancy: MVideoRedundancyVideo, expiresAfterMs: number) { 300 private async extendsExpirationOf (redundancy: MVideoRedundancyVideo, expiresAfterMs: number) {
289 logger.info('Extending expiration of %s.', redundancy.url) 301 logger.info('Extending expiration of %s.', redundancy.url, lTags(redundancy.getVideoUUID()))
290 302
291 const serverActor = await getServerActor() 303 const serverActor = await getServerActor()
292 304
@@ -317,10 +329,14 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
317 private async isTooHeavy (candidateToDuplicate: CandidateToDuplicate) { 329 private async isTooHeavy (candidateToDuplicate: CandidateToDuplicate) {
318 const maxSize = candidateToDuplicate.redundancy.size 330 const maxSize = candidateToDuplicate.redundancy.size
319 331
320 const { totalUsed } = await VideoRedundancyModel.getStats(candidateToDuplicate.redundancy.strategy) 332 const { totalUsed: used } = await VideoRedundancyModel.getStats(candidateToDuplicate.redundancy.strategy)
321 const totalWillDuplicate = totalUsed + this.getTotalFileSizes(candidateToDuplicate.files, candidateToDuplicate.streamingPlaylists) 333
334 const videoSize = this.getTotalFileSizes(candidateToDuplicate.files, candidateToDuplicate.streamingPlaylists)
335 const total = used + videoSize
336
337 logger.debug('Checking candidate size.', { used, videoSize, total, ...lTags(candidateToDuplicate.video.uuid) })
322 338
323 return totalWillDuplicate > maxSize 339 return total > maxSize
324 } 340 }
325 341
326 private buildNewExpiration (expiresAfterMs: number) { 342 private buildNewExpiration (expiresAfterMs: number) {
diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts
index 44c17f8e5..529977924 100644
--- a/server/models/redundancy/video-redundancy.ts
+++ b/server/models/redundancy/video-redundancy.ts
@@ -411,7 +411,7 @@ export class VideoRedundancyModel extends Model<Partial<AttributesOnly<VideoRedu
411 return VideoRedundancyModel.scope([ ScopeNames.WITH_VIDEO ]).findOne(query) 411 return VideoRedundancyModel.scope([ ScopeNames.WITH_VIDEO ]).findOne(query)
412 } 412 }
413 413
414 static async listLocalExpired () { 414 static async listLocalExpired (): Promise<MVideoRedundancyVideo[]> {
415 const actor = await getServerActor() 415 const actor = await getServerActor()
416 416
417 const query = { 417 const query = {
@@ -701,6 +701,13 @@ export class VideoRedundancyModel extends Model<Partial<AttributesOnly<VideoRedu
701 return undefined 701 return undefined
702 } 702 }
703 703
704 getVideoUUID () {
705 const video = this.getVideo()
706 if (!video) return undefined
707
708 return video.uuid
709 }
710
704 isOwned () { 711 isOwned () {
705 return !!this.strategy 712 return !!this.strategy
706 } 713 }