Correctly cleanup permanent live empty directories

This commit is contained in:
Chocobozzz 2024-09-11 14:45:02 +02:00
parent be7bc3a6a9
commit 71bdad9f5e
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
3 changed files with 40 additions and 17 deletions

View File

@ -269,7 +269,7 @@ describe('Save replay setting', function () {
await publishLiveAndDelete({ permanent: false, replay: false })
await checkVideosExist(liveVideoUUID, 0, HttpStatusCode.NOT_FOUND_404)
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false, deleted: true })
})
})
@ -381,7 +381,7 @@ describe('Save replay setting', function () {
await publishLiveAndDelete({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } })
await checkVideosExist(liveVideoUUID, 0, HttpStatusCode.NOT_FOUND_404)
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false, deleted: true })
})
})
@ -563,7 +563,14 @@ describe('Save replay setting', function () {
})
it('Should have cleaned up the live files', async function () {
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: true })
})
it('Should delete the empty live and also delete the empty directory', async function () {
await servers[0].videos.remove({ id: liveVideoUUID })
await waitJobs(servers)
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: true, deleted: true })
})
it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
@ -586,7 +593,7 @@ describe('Save replay setting', function () {
await servers[1].videos.get({ id: videoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: true })
})
it('Should correctly terminate the stream on delete and not save the video', async function () {
@ -602,7 +609,7 @@ describe('Save replay setting', function () {
expect(replay).to.not.exist
await checkVideosExist(liveVideoUUID, 1, HttpStatusCode.NOT_FOUND_404)
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: true, deleted: true })
})
})
})

View File

@ -16,14 +16,21 @@ async function checkLiveCleanup (options: {
videoUUID: string
permanent: boolean
savedResolutions?: number[]
deleted?: boolean // default false
}) {
const { server, videoUUID, permanent, savedResolutions = [] } = options
const { server, videoUUID, permanent, savedResolutions = [], deleted = false } = options
const basePath = server.servers.buildDirectory('streaming-playlists')
const hlsPath = join(basePath, 'hls', videoUUID)
const hlsPathExists = await pathExists(hlsPath)
if (deleted) {
expect(hlsPathExists).to.be.false
return
}
if (permanent) {
if (!await pathExists(hlsPath)) return
if (!hlsPathExists) return
const files = await readdir(hlsPath)
expect(files.filter(f => f !== 'replay')).to.have.lengthOf(0)
@ -32,15 +39,13 @@ async function checkLiveCleanup (options: {
if (await pathExists(replayDir)) {
expect(await readdir(replayDir)).to.have.lengthOf(0)
}
} else {
if (savedResolutions.length === 0) {
return checkUnsavedLiveCleanup(server, videoUUID, hlsPath)
}
return
return checkSavedLiveCleanup(hlsPath, savedResolutions)
}
if (savedResolutions.length === 0) {
return checkUnsavedLiveCleanup(server, videoUUID, hlsPath)
}
return checkSavedLiveCleanup(hlsPath, savedResolutions)
}
// ---------------------------------------------------------------------------

View File

@ -1,12 +1,12 @@
import { pathExists, remove } from 'fs-extra/esm'
import { readdir } from 'fs/promises'
import { readdir, rmdir } from 'fs/promises'
import { basename, join } from 'path'
import { LiveVideoLatencyMode, LiveVideoLatencyModeType, FileStorage } from '@peertube/peertube-models'
import { LiveVideoLatencyMode, LiveVideoLatencyModeType, FileStorage, VideoState } from '@peertube/peertube-models'
import { logger } from '@server/helpers/logger.js'
import { VIDEO_LIVE } from '@server/initializers/constants.js'
import { MStreamingPlaylist, MStreamingPlaylistVideo, MVideo } from '@server/types/models/index.js'
import { listHLSFileKeysOf, removeHLSFileObjectStorageByFullKey, removeHLSObjectStorage } from '../object-storage/index.js'
import { getLiveDirectory } from '../paths.js'
import { getLiveDirectory, getLiveReplayBaseDirectory } from '../paths.js'
function buildConcatenatedName (segmentOrPlaylistPath: string) {
const num = basename(segmentOrPlaylistPath).match(/^(\d+)(-|\.)/)
@ -17,6 +17,17 @@ function buildConcatenatedName (segmentOrPlaylistPath: string) {
async function cleanupAndDestroyPermanentLive (video: MVideo, streamingPlaylist: MStreamingPlaylist) {
await cleanupTMPLiveFiles(video, streamingPlaylist)
if (video.state === VideoState.WAITING_FOR_LIVE) {
// Try to delete local filesystem empty paths
// Object storage doesn't have the concept of directories so we don't need to duplicate the logic here
try {
await rmdir(getLiveReplayBaseDirectory(video))
await rmdir(getLiveDirectory(video))
} catch (err) {
logger.debug('Cannot cleanup permanent local live files', { err })
}
}
await streamingPlaylist.destroy()
}