X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;ds=inline;f=server%2Fmodels%2Fredundancy%2Fvideo-redundancy.ts;h=b722bed1482f62bd68b15e7c6cfcd2d7fc483286;hb=092092969633bbcf6d4891a083ea497a7d5c3154;hp=8f2ef2d9ac4206ebe1b8ce3905fed6ad4f3bc968;hpb=4348a27d252a3349bafa7ef4859c0e2cf060c255;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts index 8f2ef2d9a..b722bed14 100644 --- a/server/models/redundancy/video-redundancy.ts +++ b/server/models/redundancy/video-redundancy.ts @@ -28,6 +28,7 @@ import { sample } from 'lodash' import { isTestInstance } from '../../helpers/core-utils' import * as Bluebird from 'bluebird' import * as Sequelize from 'sequelize' +import { VideoStreamingPlaylistModel } from '../video/video-streaming-playlist' export enum ScopeNames { WITH_VIDEO = 'WITH_VIDEO' @@ -38,7 +39,17 @@ export enum ScopeNames { include: [ { model: () => VideoFileModel, - required: true, + required: false, + include: [ + { + model: () => VideoModel, + required: true + } + ] + }, + { + model: () => VideoStreamingPlaylistModel, + required: false, include: [ { model: () => VideoModel, @@ -97,12 +108,24 @@ export class VideoRedundancyModel extends Model { @BelongsTo(() => VideoFileModel, { foreignKey: { - allowNull: false + allowNull: true }, onDelete: 'cascade' }) VideoFile: VideoFileModel + @ForeignKey(() => VideoStreamingPlaylistModel) + @Column + videoStreamingPlaylistId: number + + @BelongsTo(() => VideoStreamingPlaylistModel, { + foreignKey: { + allowNull: true + }, + onDelete: 'cascade' + }) + VideoStreamingPlaylist: VideoStreamingPlaylistModel + @ForeignKey(() => ActorModel) @Column actorId: number @@ -119,13 +142,25 @@ export class VideoRedundancyModel extends Model { static async removeFile (instance: VideoRedundancyModel) { if (!instance.isOwned()) return - const videoFile = await VideoFileModel.loadWithVideo(instance.videoFileId) + if (instance.videoFileId) { + const videoFile = await VideoFileModel.loadWithVideo(instance.videoFileId) - const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}` - logger.info('Removing duplicated video file %s.', logIdentifier) + const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}` + logger.info('Removing duplicated video file %s.', logIdentifier) - videoFile.Video.removeFile(videoFile, true) - .catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err })) + videoFile.Video.removeFile(videoFile, true) + .catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err })) + } + + if (instance.videoStreamingPlaylistId) { + const videoStreamingPlaylist = await VideoStreamingPlaylistModel.loadWithVideo(instance.videoStreamingPlaylistId) + + const videoUUID = videoStreamingPlaylist.Video.uuid + logger.info('Removing duplicated video streaming playlist %s.', videoUUID) + + videoStreamingPlaylist.Video.removeStreamingPlaylist(true) + .catch(err => logger.error('Cannot delete video streaming playlist files of %s.', videoUUID, { err })) + } return undefined } @@ -143,6 +178,19 @@ export class VideoRedundancyModel extends Model { return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query) } + static async loadLocalByStreamingPlaylistId (videoStreamingPlaylistId: number) { + const actor = await getServerActor() + + const query = { + where: { + actorId: actor.id, + videoStreamingPlaylistId + } + } + + return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query) + } + static loadByUrl (url: string, transaction?: Sequelize.Transaction) { const query = { where: { @@ -191,7 +239,7 @@ export class VideoRedundancyModel extends Model { const ids = rows.map(r => r.id) const id = sample(ids) - return VideoModel.loadWithFile(id, undefined, !isTestInstance()) + return VideoModel.loadWithFiles(id, undefined, !isTestInstance()) } static async findMostViewToDuplicate (randomizedFactor: number) { @@ -333,40 +381,44 @@ export class VideoRedundancyModel extends Model { static async listLocalOfServer (serverId: number) { const actor = await getServerActor() - - const query = { - where: { - actorId: actor.id - }, + const buildVideoInclude = () => ({ + model: VideoModel, + required: true, include: [ { - model: VideoFileModel, + attributes: [], + model: VideoChannelModel.unscoped(), required: true, include: [ { - model: VideoModel, + attributes: [], + model: ActorModel.unscoped(), required: true, - include: [ - { - attributes: [], - model: VideoChannelModel.unscoped(), - required: true, - include: [ - { - attributes: [], - model: ActorModel.unscoped(), - required: true, - where: { - serverId - } - } - ] - } - ] + where: { + serverId + } } ] } ] + }) + + const query = { + where: { + actorId: actor.id + }, + include: [ + { + model: VideoFileModel, + required: false, + include: [ buildVideoInclude() ] + }, + { + model: VideoStreamingPlaylistModel, + required: false, + include: [ buildVideoInclude() ] + } + ] } return VideoRedundancyModel.findAll(query) @@ -403,11 +455,32 @@ export class VideoRedundancyModel extends Model { })) } + getVideo () { + if (this.VideoFile) return this.VideoFile.Video + + return this.VideoStreamingPlaylist.Video + } + isOwned () { return !!this.strategy } toActivityPubObject (): CacheFileObject { + if (this.VideoStreamingPlaylist) { + return { + id: this.url, + type: 'CacheFile' as 'CacheFile', + object: this.VideoStreamingPlaylist.Video.url, + expires: this.expiresOn.toISOString(), + url: { + type: 'Link', + mimeType: 'application/x-mpegURL', + mediaType: 'application/x-mpegURL', + href: this.fileUrl + } + } + } + return { id: this.url, type: 'CacheFile' as 'CacheFile', @@ -431,7 +504,7 @@ export class VideoRedundancyModel extends Model { const notIn = Sequelize.literal( '(' + - `SELECT "videoFileId" FROM "videoRedundancy" WHERE "actorId" = ${actor.id}` + + `SELECT "videoFileId" FROM "videoRedundancy" WHERE "actorId" = ${actor.id} AND "videoFileId" IS NOT NULL` + ')' )