aboutsummaryrefslogblamecommitdiffhomepage
path: root/server/tests/api/redundancy/manage-redundancy.ts
blob: efb60dc56a31f0540baec1c05a3c41ac4b8121be (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                                              
 
              
                            



                             
                    

                           
          

                                                                      










                                                                             

                                   



























                                                         

                                                    
     

                                                                                                          


     

                                                                                                          




                                              
                                              
                                                                                          





                                                                    
                                                           
 

                                           






                                                                                    
                                                                   

                           
                                                                          
 

                                         




                                                                            

                                                                      
 
                            






















                                                                                                   
                                                                      
 

                                         




                                                                                

                                                                          
 
                            























                                                                                                   
                                                 





                                
                              

                                                         


     
                                                 





                                
                              

                                                         


     
                                                 





                                
                                                            





                                                                        
                                                                                                                                
                           
                                                                  
 
                                           

                           
                                                                   


                           
                                                 





                                
                                
 
                                                     















                                                                                                 
                                               





                          

                                                   

















                                                                                               
                                                     


     
                                                 





                                
                              
 
                                        
 
                             
                                                     




                                                                                                 
                                                        



                                                                   


                                                      
 





                                               
 


                                                       





                               
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */

import 'mocha'
import * as chai from 'chai'
import {
  cleanupTests,
  doubleFollow,
  flushAndRunMultipleServers,
  RedundancyCommand,
  ServerInfo,
  setAccessTokensToServers,
  waitJobs
} from '@shared/extra-utils'
import { VideoPrivacy, VideoRedundanciesTarget } from '@shared/models'

const expect = chai.expect

describe('Test manage videos redundancy', function () {
  const targets: VideoRedundanciesTarget[] = [ 'my-videos', 'remote-videos' ]

  let servers: ServerInfo[]
  let video1Server2UUID: string
  let video2Server2UUID: string
  let redundanciesToRemove: number[] = []

  let commands: RedundancyCommand[]

  before(async function () {
    this.timeout(120000)

    const config = {
      transcoding: {
        hls: {
          enabled: true
        }
      },
      redundancy: {
        videos: {
          check_interval: '1 second',
          strategies: [
            {
              strategy: 'recently-added',
              min_lifetime: '1 hour',
              size: '10MB',
              min_views: 0
            }
          ]
        }
      }
    }
    servers = await flushAndRunMultipleServers(3, config)

    // Get the access tokens
    await setAccessTokensToServers(servers)

    commands = servers.map(s => s.redundancyCommand)

    {
      const { uuid } = await servers[1].videosCommand.upload({ attributes: { name: 'video 1 server 2' } })
      video1Server2UUID = uuid
    }

    {
      const { uuid } = await servers[1].videosCommand.upload({ attributes: { name: 'video 2 server 2' } })
      video2Server2UUID = uuid
    }

    await waitJobs(servers)

    // Server 1 and server 2 follow each other
    await doubleFollow(servers[0], servers[1])
    await commands[0].updateRedundancy({ host: servers[1].host, redundancyAllowed: true })

    await waitJobs(servers)
  })

  it('Should not have redundancies on server 3', async function () {
    for (const target of targets) {
      const body = await commands[2].listVideos({ target })

      expect(body.total).to.equal(0)
      expect(body.data).to.have.lengthOf(0)
    }
  })

  it('Should not have "remote-videos" redundancies on server 2', async function () {
    this.timeout(120000)

    await waitJobs(servers)
    await servers[0].serversCommand.waitUntilLog('Duplicated ', 10)
    await waitJobs(servers)

    const body = await commands[1].listVideos({ target: 'remote-videos' })

    expect(body.total).to.equal(0)
    expect(body.data).to.have.lengthOf(0)
  })

  it('Should have "my-videos" redundancies on server 2', async function () {
    this.timeout(120000)

    const body = await commands[1].listVideos({ target: 'my-videos' })
    expect(body.total).to.equal(2)

    const videos = body.data
    expect(videos).to.have.lengthOf(2)

    const videos1 = videos.find(v => v.uuid === video1Server2UUID)
    const videos2 = videos.find(v => v.uuid === video2Server2UUID)

    expect(videos1.name).to.equal('video 1 server 2')
    expect(videos2.name).to.equal('video 2 server 2')

    expect(videos1.redundancies.files).to.have.lengthOf(4)
    expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)

    const redundancies = videos1.redundancies.files.concat(videos1.redundancies.streamingPlaylists)

    for (const r of redundancies) {
      expect(r.strategy).to.be.null
      expect(r.fileUrl).to.exist
      expect(r.createdAt).to.exist
      expect(r.updatedAt).to.exist
      expect(r.expiresOn).to.exist
    }
  })

  it('Should not have "my-videos" redundancies on server 1', async function () {
    const body = await commands[0].listVideos({ target: 'my-videos' })

    expect(body.total).to.equal(0)
    expect(body.data).to.have.lengthOf(0)
  })

  it('Should have "remote-videos" redundancies on server 1', async function () {
    this.timeout(120000)

    const body = await commands[0].listVideos({ target: 'remote-videos' })
    expect(body.total).to.equal(2)

    const videos = body.data
    expect(videos).to.have.lengthOf(2)

    const videos1 = videos.find(v => v.uuid === video1Server2UUID)
    const videos2 = videos.find(v => v.uuid === video2Server2UUID)

    expect(videos1.name).to.equal('video 1 server 2')
    expect(videos2.name).to.equal('video 2 server 2')

    expect(videos1.redundancies.files).to.have.lengthOf(4)
    expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)

    const redundancies = videos1.redundancies.files.concat(videos1.redundancies.streamingPlaylists)

    for (const r of redundancies) {
      expect(r.strategy).to.equal('recently-added')
      expect(r.fileUrl).to.exist
      expect(r.createdAt).to.exist
      expect(r.updatedAt).to.exist
      expect(r.expiresOn).to.exist
    }
  })

  it('Should correctly paginate and sort results', async function () {
    {
      const body = await commands[0].listVideos({
        target: 'remote-videos',
        sort: 'name',
        start: 0,
        count: 2
      })

      const videos = body.data
      expect(videos[0].name).to.equal('video 1 server 2')
      expect(videos[1].name).to.equal('video 2 server 2')
    }

    {
      const body = await commands[0].listVideos({
        target: 'remote-videos',
        sort: '-name',
        start: 0,
        count: 2
      })

      const videos = body.data
      expect(videos[0].name).to.equal('video 2 server 2')
      expect(videos[1].name).to.equal('video 1 server 2')
    }

    {
      const body = await commands[0].listVideos({
        target: 'remote-videos',
        sort: '-name',
        start: 1,
        count: 1
      })

      expect(body.data[0].name).to.equal('video 1 server 2')
    }
  })

  it('Should manually add a redundancy and list it', async function () {
    this.timeout(120000)

    const uuid = (await servers[1].videosCommand.quickUpload({ name: 'video 3 server 2', privacy: VideoPrivacy.UNLISTED })).uuid
    await waitJobs(servers)
    const videoId = await servers[0].videosCommand.getId({ uuid })

    await commands[0].addVideo({ videoId })

    await waitJobs(servers)
    await servers[0].serversCommand.waitUntilLog('Duplicated ', 15)
    await waitJobs(servers)

    {
      const body = await commands[0].listVideos({
        target: 'remote-videos',
        sort: '-name',
        start: 0,
        count: 5
      })

      const video = body.data[0]

      expect(video.name).to.equal('video 3 server 2')
      expect(video.redundancies.files).to.have.lengthOf(4)
      expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)

      const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)

      for (const r of redundancies) {
        redundanciesToRemove.push(r.id)

        expect(r.strategy).to.equal('manual')
        expect(r.fileUrl).to.exist
        expect(r.createdAt).to.exist
        expect(r.updatedAt).to.exist
        expect(r.expiresOn).to.be.null
      }
    }

    const body = await commands[1].listVideos({
      target: 'my-videos',
      sort: '-name',
      start: 0,
      count: 5
    })

    const video = body.data[0]
    expect(video.name).to.equal('video 3 server 2')
    expect(video.redundancies.files).to.have.lengthOf(4)
    expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)

    const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)

    for (const r of redundancies) {
      expect(r.strategy).to.be.null
      expect(r.fileUrl).to.exist
      expect(r.createdAt).to.exist
      expect(r.updatedAt).to.exist
      expect(r.expiresOn).to.be.null
    }
  })

  it('Should manually remove a redundancy and remove it from the list', async function () {
    this.timeout(120000)

    for (const redundancyId of redundanciesToRemove) {
      await commands[0].removeVideo({ redundancyId })
    }

    {
      const body = await commands[0].listVideos({
        target: 'remote-videos',
        sort: '-name',
        start: 0,
        count: 5
      })

      const videos = body.data

      expect(videos).to.have.lengthOf(2)

      const video = videos[0]
      expect(video.name).to.equal('video 2 server 2')
      expect(video.redundancies.files).to.have.lengthOf(4)
      expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)

      const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)

      redundanciesToRemove = redundancies.map(r => r.id)
    }
  })

  it('Should remove another (auto) redundancy', async function () {
    for (const redundancyId of redundanciesToRemove) {
      await commands[0].removeVideo({ redundancyId })
    }

    const body = await commands[0].listVideos({
      target: 'remote-videos',
      sort: '-name',
      start: 0,
      count: 5
    })

    const videos = body.data
    expect(videos).to.have.lengthOf(1)
    expect(videos[0].name).to.equal('video 1 server 2')
  })

  after(async function () {
    await cleanupTests(servers)
  })
})