prune-storage.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
  2. import { expect } from 'chai'
  3. import { createFile, readdir } from 'fs-extra'
  4. import { join } from 'path'
  5. import { wait } from '@shared/core-utils'
  6. import { buildUUID } from '@shared/extra-utils'
  7. import { HttpStatusCode, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
  8. import {
  9. cleanupTests,
  10. CLICommand,
  11. createMultipleServers,
  12. doubleFollow,
  13. killallServers,
  14. makeGetRequest,
  15. PeerTubeServer,
  16. setAccessTokensToServers,
  17. setDefaultVideoChannel,
  18. waitJobs
  19. } from '@shared/server-commands'
  20. async function countFiles (server: PeerTubeServer, directory: string) {
  21. const files = await readdir(server.servers.buildDirectory(directory))
  22. return files.length
  23. }
  24. async function assertNotExists (server: PeerTubeServer, directory: string, substring: string) {
  25. const files = await readdir(server.servers.buildDirectory(directory))
  26. for (const f of files) {
  27. expect(f).to.not.contain(substring)
  28. }
  29. }
  30. async function assertCountAreOkay (servers: PeerTubeServer[]) {
  31. for (const server of servers) {
  32. const videosCount = await countFiles(server, 'videos')
  33. expect(videosCount).to.equal(9) // 2 videos with 4 resolutions + private directory
  34. const privateVideosCount = await countFiles(server, 'videos/private')
  35. expect(privateVideosCount).to.equal(4)
  36. const torrentsCount = await countFiles(server, 'torrents')
  37. expect(torrentsCount).to.equal(24)
  38. const previewsCount = await countFiles(server, 'previews')
  39. expect(previewsCount).to.equal(3)
  40. const thumbnailsCount = await countFiles(server, 'thumbnails')
  41. expect(thumbnailsCount).to.equal(7) // 3 local videos, 1 local playlist, 2 remotes videos and 1 remote playlist
  42. const avatarsCount = await countFiles(server, 'avatars')
  43. expect(avatarsCount).to.equal(4)
  44. const hlsRootCount = await countFiles(server, join('streaming-playlists', 'hls'))
  45. expect(hlsRootCount).to.equal(3) // 2 videos + private directory
  46. const hlsPrivateRootCount = await countFiles(server, join('streaming-playlists', 'hls', 'private'))
  47. expect(hlsPrivateRootCount).to.equal(1)
  48. }
  49. }
  50. describe('Test prune storage scripts', function () {
  51. let servers: PeerTubeServer[]
  52. const badNames: { [directory: string]: string[] } = {}
  53. before(async function () {
  54. this.timeout(120000)
  55. servers = await createMultipleServers(2, { transcoding: { enabled: true } })
  56. await setAccessTokensToServers(servers)
  57. await setDefaultVideoChannel(servers)
  58. for (const server of servers) {
  59. await server.videos.upload({ attributes: { name: 'video 1', privacy: VideoPrivacy.PUBLIC } })
  60. await server.videos.upload({ attributes: { name: 'video 2', privacy: VideoPrivacy.PUBLIC } })
  61. await server.videos.upload({ attributes: { name: 'video 3', privacy: VideoPrivacy.PRIVATE } })
  62. await server.users.updateMyAvatar({ fixture: 'avatar.png' })
  63. await server.playlists.create({
  64. attributes: {
  65. displayName: 'playlist',
  66. privacy: VideoPlaylistPrivacy.PUBLIC,
  67. videoChannelId: server.store.channel.id,
  68. thumbnailfile: 'thumbnail.jpg'
  69. }
  70. })
  71. }
  72. await doubleFollow(servers[0], servers[1])
  73. // Lazy load the remote avatars
  74. {
  75. const account = await servers[0].accounts.get({ accountName: 'root@localhost:' + servers[1].port })
  76. for (const avatar of account.avatars) {
  77. await makeGetRequest({
  78. url: servers[0].url,
  79. path: avatar.path,
  80. expectedStatus: HttpStatusCode.OK_200
  81. })
  82. }
  83. }
  84. {
  85. const account = await servers[1].accounts.get({ accountName: 'root@localhost:' + servers[0].port })
  86. for (const avatar of account.avatars) {
  87. await makeGetRequest({
  88. url: servers[1].url,
  89. path: avatar.path,
  90. expectedStatus: HttpStatusCode.OK_200
  91. })
  92. }
  93. }
  94. await wait(1000)
  95. await waitJobs(servers)
  96. await killallServers(servers)
  97. await wait(1000)
  98. })
  99. it('Should have the files on the disk', async function () {
  100. await assertCountAreOkay(servers)
  101. })
  102. it('Should create some dirty files', async function () {
  103. for (let i = 0; i < 2; i++) {
  104. {
  105. const basePublic = servers[0].servers.buildDirectory('videos')
  106. const basePrivate = servers[0].servers.buildDirectory(join('videos', 'private'))
  107. const n1 = buildUUID() + '.mp4'
  108. const n2 = buildUUID() + '.webm'
  109. await createFile(join(basePublic, n1))
  110. await createFile(join(basePublic, n2))
  111. await createFile(join(basePrivate, n1))
  112. await createFile(join(basePrivate, n2))
  113. badNames['videos'] = [ n1, n2 ]
  114. }
  115. {
  116. const base = servers[0].servers.buildDirectory('torrents')
  117. const n1 = buildUUID() + '-240.torrent'
  118. const n2 = buildUUID() + '-480.torrent'
  119. await createFile(join(base, n1))
  120. await createFile(join(base, n2))
  121. badNames['torrents'] = [ n1, n2 ]
  122. }
  123. {
  124. const base = servers[0].servers.buildDirectory('thumbnails')
  125. const n1 = buildUUID() + '.jpg'
  126. const n2 = buildUUID() + '.jpg'
  127. await createFile(join(base, n1))
  128. await createFile(join(base, n2))
  129. badNames['thumbnails'] = [ n1, n2 ]
  130. }
  131. {
  132. const base = servers[0].servers.buildDirectory('previews')
  133. const n1 = buildUUID() + '.jpg'
  134. const n2 = buildUUID() + '.jpg'
  135. await createFile(join(base, n1))
  136. await createFile(join(base, n2))
  137. badNames['previews'] = [ n1, n2 ]
  138. }
  139. {
  140. const base = servers[0].servers.buildDirectory('avatars')
  141. const n1 = buildUUID() + '.png'
  142. const n2 = buildUUID() + '.jpg'
  143. await createFile(join(base, n1))
  144. await createFile(join(base, n2))
  145. badNames['avatars'] = [ n1, n2 ]
  146. }
  147. {
  148. const directory = join('streaming-playlists', 'hls')
  149. const basePublic = servers[0].servers.buildDirectory(directory)
  150. const basePrivate = servers[0].servers.buildDirectory(join(directory, 'private'))
  151. const n1 = buildUUID()
  152. await createFile(join(basePublic, n1))
  153. await createFile(join(basePrivate, n1))
  154. badNames[directory] = [ n1 ]
  155. }
  156. }
  157. })
  158. it('Should run prune storage', async function () {
  159. this.timeout(30000)
  160. const env = servers[0].cli.getEnv()
  161. await CLICommand.exec(`echo y | ${env} npm run prune-storage`)
  162. })
  163. it('Should have removed files', async function () {
  164. await assertCountAreOkay(servers)
  165. for (const directory of Object.keys(badNames)) {
  166. for (const name of badNames[directory]) {
  167. await assertNotExists(servers[0], directory, name)
  168. }
  169. }
  170. })
  171. after(async function () {
  172. await cleanupTests(servers)
  173. })
  174. })