Create redundancy endpoint

This commit is contained in:
Chocobozzz 2018-12-04 17:08:55 +01:00
parent 6040f87d14
commit b9fffa297f
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
7 changed files with 38 additions and 23 deletions

View File

@ -37,12 +37,12 @@ staticRouter.use(
staticRouter.use( staticRouter.use(
STATIC_PATHS.WEBSEED, STATIC_PATHS.WEBSEED,
cors(), cors(),
express.static(CONFIG.STORAGE.VIDEOS_DIR) express.static(CONFIG.STORAGE.VIDEOS_DIR, { fallthrough: false }) // 404 because we don't have this video
) )
staticRouter.use( staticRouter.use(
STATIC_PATHS.WEBSEED, STATIC_PATHS.REDUNDANCY,
cors(), cors(),
express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404, because we don't have this video express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404 because we don't have this video
) )
staticRouter.use( staticRouter.use(

View File

@ -571,6 +571,7 @@ const STATIC_PATHS = {
THUMBNAILS: '/static/thumbnails/', THUMBNAILS: '/static/thumbnails/',
TORRENTS: '/static/torrents/', TORRENTS: '/static/torrents/',
WEBSEED: '/static/webseed/', WEBSEED: '/static/webseed/',
REDUNDANCY: '/static/redundancy/',
AVATARS: '/static/avatars/', AVATARS: '/static/avatars/',
VIDEO_CAPTIONS: '/static/video-captions/' VIDEO_CAPTIONS: '/static/video-captions/'
} }

View File

@ -145,13 +145,13 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
const tmpPath = await downloadWebTorrentVideo({ magnetUri }, VIDEO_IMPORT_TIMEOUT) const tmpPath = await downloadWebTorrentVideo({ magnetUri }, VIDEO_IMPORT_TIMEOUT)
const destPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename(file)) const destPath = join(CONFIG.STORAGE.REDUNDANCY_DIR, video.getVideoFilename(file))
await rename(tmpPath, destPath) await rename(tmpPath, destPath)
const createdModel = await VideoRedundancyModel.create({ const createdModel = await VideoRedundancyModel.create({
expiresOn: this.buildNewExpiration(redundancy.minLifetime), expiresOn: this.buildNewExpiration(redundancy.minLifetime),
url: getVideoCacheFileActivityPubUrl(file), url: getVideoCacheFileActivityPubUrl(file),
fileUrl: video.getVideoFileUrl(file, CONFIG.WEBSERVER.URL), fileUrl: video.getVideoRedundancyUrl(file, CONFIG.WEBSERVER.URL),
strategy: redundancy.strategy, strategy: redundancy.strategy,
videoFileId: file.id, videoFileId: file.id,
actorId: serverActor.id actorId: serverActor.id

View File

@ -15,7 +15,7 @@ import {
import { ActorModel } from '../activitypub/actor' import { ActorModel } from '../activitypub/actor'
import { getVideoSort, throwIfNotValid } from '../utils' import { getVideoSort, throwIfNotValid } from '../utils'
import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
import { CONFIG, CONSTRAINTS_FIELDS, VIDEO_EXT_MIMETYPE } from '../../initializers' import { CONFIG, CONSTRAINTS_FIELDS, STATIC_PATHS, VIDEO_EXT_MIMETYPE } from '../../initializers'
import { VideoFileModel } from '../video/video-file' import { VideoFileModel } from '../video/video-file'
import { getServerActor } from '../../helpers/utils' import { getServerActor } from '../../helpers/utils'
import { VideoModel } from '../video/video' import { VideoModel } from '../video/video'
@ -124,7 +124,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}` const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}`
logger.info('Removing duplicated video file %s.', logIdentifier) logger.info('Removing duplicated video file %s.', logIdentifier)
videoFile.Video.removeFile(videoFile) videoFile.Video.removeFile(videoFile, true)
.catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err })) .catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err }))
return undefined return undefined

View File

@ -1538,8 +1538,10 @@ export class VideoModel extends Model<VideoModel> {
.catch(err => logger.warn('Cannot delete preview %s.', previewPath, { err })) .catch(err => logger.warn('Cannot delete preview %s.', previewPath, { err }))
} }
removeFile (videoFile: VideoFileModel) { removeFile (videoFile: VideoFileModel, isRedundancy = false) {
const filePath = join(CONFIG.STORAGE.VIDEOS_DIR, this.getVideoFilename(videoFile)) const baseDir = isRedundancy ? CONFIG.STORAGE.REDUNDANCY_DIR : CONFIG.STORAGE.VIDEOS_DIR
const filePath = join(baseDir, this.getVideoFilename(videoFile))
return remove(filePath) return remove(filePath)
.catch(err => logger.warn('Cannot delete file %s.', filePath, { err })) .catch(err => logger.warn('Cannot delete file %s.', filePath, { err }))
} }
@ -1617,6 +1619,10 @@ export class VideoModel extends Model<VideoModel> {
return baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile) return baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile)
} }
getVideoRedundancyUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
return baseUrlHttp + STATIC_PATHS.REDUNDANCY + this.getVideoFilename(videoFile)
}
getVideoFileDownloadUrl (videoFile: VideoFileModel, baseUrlHttp: string) { getVideoFileDownloadUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
return baseUrlHttp + STATIC_DOWNLOAD_PATHS.VIDEOS + this.getVideoFilename(videoFile) return baseUrlHttp + STATIC_DOWNLOAD_PATHS.VIDEOS + this.getVideoFilename(videoFile)
} }

View File

@ -136,7 +136,7 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st
if (!videoUUID) videoUUID = video1Server2UUID if (!videoUUID) videoUUID = video1Server2UUID
const webseeds = [ const webseeds = [
'http://localhost:9001/static/webseed/' + videoUUID, 'http://localhost:9001/static/redundancy/' + videoUUID,
'http://localhost:9002/static/webseed/' + videoUUID 'http://localhost:9002/static/webseed/' + videoUUID
] ]
@ -148,20 +148,23 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st
for (const file of video.files) { for (const file of video.files) {
checkMagnetWebseeds(file, webseeds, server) checkMagnetWebseeds(file, webseeds, server)
// Only servers 1 and 2 have the video
if (server.serverNumber !== 3) {
await makeGetRequest({ await makeGetRequest({
url: server.url, url: servers[0].url,
statusCodeExpected: 200,
path: '/static/redundancy/' + `${videoUUID}-${file.resolution.id}.mp4`,
contentType: null
})
await makeGetRequest({
url: servers[1].url,
statusCodeExpected: 200, statusCodeExpected: 200,
path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`, path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`,
contentType: null contentType: null
}) })
} }
} }
}
for (const directory of [ 'test1', 'test2' ]) { for (const directory of [ 'test1/redundancy', 'test2/videos' ]) {
const files = await readdir(join(root(), directory, 'videos')) const files = await readdir(join(root(), directory))
expect(files).to.have.length.at.least(4) expect(files).to.have.length.at.least(4)
for (const resolution of [ 240, 360, 480, 720 ]) { for (const resolution of [ 240, 360, 480, 720 ]) {

View File

@ -105,7 +105,7 @@ server {
} }
# Bypass PeerTube for performance reasons. Could be removed # Bypass PeerTube for performance reasons. Could be removed
location /static/webseed { location ~ ^/static/(webseed|redundancy)/ {
# Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client # Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client
limit_rate 800k; limit_rate 800k;
@ -128,7 +128,12 @@ server {
access_log off; access_log off;
} }
alias /var/www/peertube/storage/videos; root /var/www/peertube/storage;
rewrite ^/static/webseed/(.*)$ /videos/$1 break;
rewrite ^/static/redundancy/(.*)$ /redundancy/$1 break;
try_files $uri /;
} }
# Websocket tracker # Websocket tracker