]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/redundancy/manage-redundancy.ts
03857f51268fe25a973326dc27ed2ef81957129b
[github/Chocobozzz/PeerTube.git] / server / tests / api / redundancy / manage-redundancy.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import * as chai from 'chai'
5 import {
6 cleanupTests,
7 doubleFollow,
8 flushAndRunMultipleServers,
9 getLocalIdByUUID,
10 RedundancyCommand,
11 ServerInfo,
12 setAccessTokensToServers,
13 uploadVideo,
14 uploadVideoAndGetId,
15 waitJobs
16 } from '@shared/extra-utils'
17 import { VideoPrivacy, VideoRedundanciesTarget } from '@shared/models'
18
19 const expect = chai.expect
20
21 describe('Test manage videos redundancy', function () {
22 const targets: VideoRedundanciesTarget[] = [ 'my-videos', 'remote-videos' ]
23
24 let servers: ServerInfo[]
25 let video1Server2UUID: string
26 let video2Server2UUID: string
27 let redundanciesToRemove: number[] = []
28
29 let commands: RedundancyCommand[]
30
31 before(async function () {
32 this.timeout(120000)
33
34 const config = {
35 transcoding: {
36 hls: {
37 enabled: true
38 }
39 },
40 redundancy: {
41 videos: {
42 check_interval: '1 second',
43 strategies: [
44 {
45 strategy: 'recently-added',
46 min_lifetime: '1 hour',
47 size: '10MB',
48 min_views: 0
49 }
50 ]
51 }
52 }
53 }
54 servers = await flushAndRunMultipleServers(3, config)
55
56 // Get the access tokens
57 await setAccessTokensToServers(servers)
58
59 commands = servers.map(s => s.redundancyCommand)
60
61 {
62 const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 1 server 2' })
63 video1Server2UUID = res.body.video.uuid
64 }
65
66 {
67 const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video 2 server 2' })
68 video2Server2UUID = res.body.video.uuid
69 }
70
71 await waitJobs(servers)
72
73 // Server 1 and server 2 follow each other
74 await doubleFollow(servers[0], servers[1])
75 await commands[0].updateRedundancy({ host: servers[1].host, redundancyAllowed: true })
76
77 await waitJobs(servers)
78 })
79
80 it('Should not have redundancies on server 3', async function () {
81 for (const target of targets) {
82 const body = await commands[2].listVideos({ target })
83
84 expect(body.total).to.equal(0)
85 expect(body.data).to.have.lengthOf(0)
86 }
87 })
88
89 it('Should not have "remote-videos" redundancies on server 2', async function () {
90 this.timeout(120000)
91
92 await waitJobs(servers)
93 await servers[0].serversCommand.waitUntilLog('Duplicated ', 10)
94 await waitJobs(servers)
95
96 const body = await commands[1].listVideos({ target: 'remote-videos' })
97
98 expect(body.total).to.equal(0)
99 expect(body.data).to.have.lengthOf(0)
100 })
101
102 it('Should have "my-videos" redundancies on server 2', async function () {
103 this.timeout(120000)
104
105 const body = await commands[1].listVideos({ target: 'my-videos' })
106 expect(body.total).to.equal(2)
107
108 const videos = body.data
109 expect(videos).to.have.lengthOf(2)
110
111 const videos1 = videos.find(v => v.uuid === video1Server2UUID)
112 const videos2 = videos.find(v => v.uuid === video2Server2UUID)
113
114 expect(videos1.name).to.equal('video 1 server 2')
115 expect(videos2.name).to.equal('video 2 server 2')
116
117 expect(videos1.redundancies.files).to.have.lengthOf(4)
118 expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)
119
120 const redundancies = videos1.redundancies.files.concat(videos1.redundancies.streamingPlaylists)
121
122 for (const r of redundancies) {
123 expect(r.strategy).to.be.null
124 expect(r.fileUrl).to.exist
125 expect(r.createdAt).to.exist
126 expect(r.updatedAt).to.exist
127 expect(r.expiresOn).to.exist
128 }
129 })
130
131 it('Should not have "my-videos" redundancies on server 1', async function () {
132 const body = await commands[0].listVideos({ target: 'my-videos' })
133
134 expect(body.total).to.equal(0)
135 expect(body.data).to.have.lengthOf(0)
136 })
137
138 it('Should have "remote-videos" redundancies on server 1', async function () {
139 this.timeout(120000)
140
141 const body = await commands[0].listVideos({ target: 'remote-videos' })
142 expect(body.total).to.equal(2)
143
144 const videos = body.data
145 expect(videos).to.have.lengthOf(2)
146
147 const videos1 = videos.find(v => v.uuid === video1Server2UUID)
148 const videos2 = videos.find(v => v.uuid === video2Server2UUID)
149
150 expect(videos1.name).to.equal('video 1 server 2')
151 expect(videos2.name).to.equal('video 2 server 2')
152
153 expect(videos1.redundancies.files).to.have.lengthOf(4)
154 expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)
155
156 const redundancies = videos1.redundancies.files.concat(videos1.redundancies.streamingPlaylists)
157
158 for (const r of redundancies) {
159 expect(r.strategy).to.equal('recently-added')
160 expect(r.fileUrl).to.exist
161 expect(r.createdAt).to.exist
162 expect(r.updatedAt).to.exist
163 expect(r.expiresOn).to.exist
164 }
165 })
166
167 it('Should correctly paginate and sort results', async function () {
168 {
169 const body = await commands[0].listVideos({
170 target: 'remote-videos',
171 sort: 'name',
172 start: 0,
173 count: 2
174 })
175
176 const videos = body.data
177 expect(videos[0].name).to.equal('video 1 server 2')
178 expect(videos[1].name).to.equal('video 2 server 2')
179 }
180
181 {
182 const body = await commands[0].listVideos({
183 target: 'remote-videos',
184 sort: '-name',
185 start: 0,
186 count: 2
187 })
188
189 const videos = body.data
190 expect(videos[0].name).to.equal('video 2 server 2')
191 expect(videos[1].name).to.equal('video 1 server 2')
192 }
193
194 {
195 const body = await commands[0].listVideos({
196 target: 'remote-videos',
197 sort: '-name',
198 start: 1,
199 count: 1
200 })
201
202 expect(body.data[0].name).to.equal('video 1 server 2')
203 }
204 })
205
206 it('Should manually add a redundancy and list it', async function () {
207 this.timeout(120000)
208
209 const uuid = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 3 server 2', privacy: VideoPrivacy.UNLISTED })).uuid
210 await waitJobs(servers)
211 const videoId = await getLocalIdByUUID(servers[0].url, uuid)
212
213 await commands[0].addVideo({ videoId })
214
215 await waitJobs(servers)
216 await servers[0].serversCommand.waitUntilLog('Duplicated ', 15)
217 await waitJobs(servers)
218
219 {
220 const body = await commands[0].listVideos({
221 target: 'remote-videos',
222 sort: '-name',
223 start: 0,
224 count: 5
225 })
226
227 const video = body.data[0]
228
229 expect(video.name).to.equal('video 3 server 2')
230 expect(video.redundancies.files).to.have.lengthOf(4)
231 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
232
233 const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
234
235 for (const r of redundancies) {
236 redundanciesToRemove.push(r.id)
237
238 expect(r.strategy).to.equal('manual')
239 expect(r.fileUrl).to.exist
240 expect(r.createdAt).to.exist
241 expect(r.updatedAt).to.exist
242 expect(r.expiresOn).to.be.null
243 }
244 }
245
246 const body = await commands[1].listVideos({
247 target: 'my-videos',
248 sort: '-name',
249 start: 0,
250 count: 5
251 })
252
253 const video = body.data[0]
254 expect(video.name).to.equal('video 3 server 2')
255 expect(video.redundancies.files).to.have.lengthOf(4)
256 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
257
258 const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
259
260 for (const r of redundancies) {
261 expect(r.strategy).to.be.null
262 expect(r.fileUrl).to.exist
263 expect(r.createdAt).to.exist
264 expect(r.updatedAt).to.exist
265 expect(r.expiresOn).to.be.null
266 }
267 })
268
269 it('Should manually remove a redundancy and remove it from the list', async function () {
270 this.timeout(120000)
271
272 for (const redundancyId of redundanciesToRemove) {
273 await commands[0].removeVideo({ redundancyId })
274 }
275
276 {
277 const body = await commands[0].listVideos({
278 target: 'remote-videos',
279 sort: '-name',
280 start: 0,
281 count: 5
282 })
283
284 const videos = body.data
285
286 expect(videos).to.have.lengthOf(2)
287
288 const video = videos[0]
289 expect(video.name).to.equal('video 2 server 2')
290 expect(video.redundancies.files).to.have.lengthOf(4)
291 expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
292
293 const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
294
295 redundanciesToRemove = redundancies.map(r => r.id)
296 }
297 })
298
299 it('Should remove another (auto) redundancy', async function () {
300 for (const redundancyId of redundanciesToRemove) {
301 await commands[0].removeVideo({ redundancyId })
302 }
303
304 const body = await commands[0].listVideos({
305 target: 'remote-videos',
306 sort: '-name',
307 start: 0,
308 count: 5
309 })
310
311 const videos = body.data
312 expect(videos).to.have.lengthOf(1)
313 expect(videos[0].name).to.equal('video 1 server 2')
314 })
315
316 after(async function () {
317 await cleanupTests(servers)
318 })
319 })