Remove duplicated videos on unfollow/delete redundancy
This commit is contained in:
parent
d0b52b5285
commit
161b061d4e
|
@ -1,4 +1,4 @@
|
||||||
$icon-font-path: '../../node_modules/@neos21/bootstrap3-glyphicons/assets/fonts/';
|
$icon-font-path: '~@neos21/bootstrap3-glyphicons/assets/fonts/';
|
||||||
@import '_bootstrap';
|
@import '_bootstrap';
|
||||||
|
|
||||||
@import '_variables';
|
@import '_variables';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
$FontPathSourceSansPro: '../../node_modules/npm-font-source-sans-pro/fonts';
|
$FontPathSourceSansPro: '~npm-font-source-sans-pro/fonts';
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Source Sans Pro';
|
font-family: 'Source Sans Pro';
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
import { followersSortValidator, followingSortValidator, followValidator } from '../../../middlewares/validators'
|
import { followersSortValidator, followingSortValidator, followValidator } from '../../../middlewares/validators'
|
||||||
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
||||||
import { JobQueue } from '../../../lib/job-queue'
|
import { JobQueue } from '../../../lib/job-queue'
|
||||||
|
import { removeRedundancyOf } from '../../../lib/redundancy'
|
||||||
|
|
||||||
const serverFollowsRouter = express.Router()
|
const serverFollowsRouter = express.Router()
|
||||||
serverFollowsRouter.get('/following',
|
serverFollowsRouter.get('/following',
|
||||||
|
@ -101,6 +102,10 @@ async function removeFollow (req: express.Request, res: express.Response, next:
|
||||||
server.redundancyAllowed = false
|
server.redundancyAllowed = false
|
||||||
await server.save({ transaction: t })
|
await server.save({ transaction: t })
|
||||||
|
|
||||||
|
// Async, could be long
|
||||||
|
removeRedundancyOf(server.id)
|
||||||
|
.catch(err => logger.error('Cannot remove redundancy of %s.', server.host, err))
|
||||||
|
|
||||||
await follow.destroy({ transaction: t })
|
await follow.destroy({ transaction: t })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { UserRight } from '../../../../shared/models/users'
|
||||||
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
|
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
|
||||||
import { updateServerRedundancyValidator } from '../../../middlewares/validators/redundancy'
|
import { updateServerRedundancyValidator } from '../../../middlewares/validators/redundancy'
|
||||||
import { ServerModel } from '../../../models/server/server'
|
import { ServerModel } from '../../../models/server/server'
|
||||||
|
import { removeRedundancyOf } from '../../../lib/redundancy'
|
||||||
|
import { logger } from '../../../helpers/logger'
|
||||||
|
|
||||||
const serverRedundancyRouter = express.Router()
|
const serverRedundancyRouter = express.Router()
|
||||||
|
|
||||||
|
@ -28,5 +30,9 @@ async function updateRedundancy (req: express.Request, res: express.Response, ne
|
||||||
|
|
||||||
await server.save()
|
await server.save()
|
||||||
|
|
||||||
|
// Async, could be long
|
||||||
|
removeRedundancyOf(server.id)
|
||||||
|
.catch(err => logger.error('Cannot remove redundancy of %s.', server.host, err))
|
||||||
|
|
||||||
return res.sendStatus(204)
|
return res.sendStatus(204)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,17 @@ async function removeVideoRedundancy (videoRedundancy: VideoRedundancyModel, t?:
|
||||||
await videoRedundancy.destroy({ transaction: t })
|
await videoRedundancy.destroy({ transaction: t })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function removeRedundancyOf (serverId: number) {
|
||||||
|
const videosRedundancy = await VideoRedundancyModel.listLocalOfServer(serverId)
|
||||||
|
|
||||||
|
for (const redundancy of videosRedundancy) {
|
||||||
|
await removeVideoRedundancy(redundancy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
removeRedundancyOf,
|
||||||
removeVideoRedundancy
|
removeVideoRedundancy
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,6 +286,47 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
|
||||||
return VideoRedundancyModel.scope([ ScopeNames.WITH_VIDEO ]).findAll(query)
|
return VideoRedundancyModel.scope([ ScopeNames.WITH_VIDEO ]).findAll(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async listLocalOfServer (serverId: number) {
|
||||||
|
const actor = await getServerActor()
|
||||||
|
|
||||||
|
const query = {
|
||||||
|
where: {
|
||||||
|
actorId: actor.id
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: VideoFileModel,
|
||||||
|
required: true,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: VideoModel,
|
||||||
|
required: true,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
attributes: [],
|
||||||
|
model: VideoChannelModel.unscoped(),
|
||||||
|
required: true,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
attributes: [],
|
||||||
|
model: ActorModel.unscoped(),
|
||||||
|
required: true,
|
||||||
|
where: {
|
||||||
|
serverId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return VideoRedundancyModel.findAll(query)
|
||||||
|
}
|
||||||
|
|
||||||
static async getStats (strategy: VideoRedundancyStrategy) {
|
static async getStats (strategy: VideoRedundancyStrategy) {
|
||||||
const actor = await getServerActor()
|
const actor = await getServerActor()
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
killallServers, makeGetRequest,
|
killallServers, makeGetRequest,
|
||||||
root,
|
root,
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers, unfollow,
|
||||||
uploadVideo,
|
uploadVideo,
|
||||||
viewVideo,
|
viewVideo,
|
||||||
wait
|
wait
|
||||||
|
@ -39,6 +39,8 @@ function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: numbe
|
||||||
const found = parsed.urlList.find(url => url === `${ws}-${file.resolution.id}.mp4`)
|
const found = parsed.urlList.find(url => url === `${ws}-${file.resolution.id}.mp4`)
|
||||||
expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined
|
expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runServers (strategy: VideoRedundancyStrategy, additionalParams: any = {}) {
|
async function runServers (strategy: VideoRedundancyStrategy, additionalParams: any = {}) {
|
||||||
|
@ -136,23 +138,21 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st
|
||||||
]
|
]
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
{
|
const res = await getVideo(server.url, videoUUID)
|
||||||
const res = await getVideo(server.url, videoUUID)
|
|
||||||
|
|
||||||
const video: VideoDetails = res.body
|
const video: VideoDetails = res.body
|
||||||
|
|
||||||
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
|
// Only servers 1 and 2 have the video
|
||||||
if (server.serverNumber !== 3) {
|
if (server.serverNumber !== 3) {
|
||||||
await makeGetRequest({
|
await makeGetRequest({
|
||||||
url: server.url,
|
url: server.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
|
||||||
})
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,6 +182,21 @@ async function enableRedundancyOnServer1 () {
|
||||||
expect(server2.following.hostRedundancyAllowed).to.be.true
|
expect(server2.following.hostRedundancyAllowed).to.be.true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function disableRedundancyOnServer1 () {
|
||||||
|
await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, false)
|
||||||
|
|
||||||
|
const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, '-createdAt')
|
||||||
|
const follows: ActorFollow[] = res.body.data
|
||||||
|
const server2 = follows.find(f => f.following.host === 'localhost:9002')
|
||||||
|
const server3 = follows.find(f => f.following.host === 'localhost:9003')
|
||||||
|
|
||||||
|
expect(server3).to.not.be.undefined
|
||||||
|
expect(server3.following.hostRedundancyAllowed).to.be.false
|
||||||
|
|
||||||
|
expect(server2).to.not.be.undefined
|
||||||
|
expect(server2.following.hostRedundancyAllowed).to.be.false
|
||||||
|
}
|
||||||
|
|
||||||
async function cleanServers () {
|
async function cleanServers () {
|
||||||
killallServers(servers)
|
killallServers(servers)
|
||||||
}
|
}
|
||||||
|
@ -217,6 +232,17 @@ describe('Test videos redundancy', function () {
|
||||||
await checkStatsWith2Webseed(strategy)
|
await checkStatsWith2Webseed(strategy)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should undo redundancy on server 1 and remove duplicated videos', async function () {
|
||||||
|
this.timeout(40000)
|
||||||
|
|
||||||
|
await disableRedundancyOnServer1()
|
||||||
|
|
||||||
|
await waitJobs(servers)
|
||||||
|
await wait(5000)
|
||||||
|
|
||||||
|
await check1WebSeed(strategy)
|
||||||
|
})
|
||||||
|
|
||||||
after(function () {
|
after(function () {
|
||||||
return cleanServers()
|
return cleanServers()
|
||||||
})
|
})
|
||||||
|
@ -251,6 +277,17 @@ describe('Test videos redundancy', function () {
|
||||||
await checkStatsWith2Webseed(strategy)
|
await checkStatsWith2Webseed(strategy)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should unfollow on server 1 and remove duplicated videos', async function () {
|
||||||
|
this.timeout(40000)
|
||||||
|
|
||||||
|
await unfollow(servers[0].url, servers[0].accessToken, servers[1])
|
||||||
|
|
||||||
|
await waitJobs(servers)
|
||||||
|
await wait(5000)
|
||||||
|
|
||||||
|
await check1WebSeed(strategy)
|
||||||
|
})
|
||||||
|
|
||||||
after(function () {
|
after(function () {
|
||||||
return cleanServers()
|
return cleanServers()
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue