Skip to content

Commit 5a74514

Browse files
kernicPanellunika
authored andcommitted
✨(back) cleanup transcoding temp files
Once a video transcoded we want to delete the first transcoded video that is using a temporary file. Also a management command cleaning old temporary transcoded video is added
1 parent c4ba0df commit 5a74514

File tree

5 files changed

+121
-15
lines changed

5 files changed

+121
-15
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Versioning](https://semver.org/spec/v2.0.0.html).
88

99
## [Unreleased]
1010

11+
### Added
12+
13+
- Cleanup transcoding temp files
14+
1115
## [5.2.0] - 2024-10-22
1216

1317
### Added
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""Management command to delete transcoding temp files."""
2+
3+
import logging
4+
5+
from django.core.management import BaseCommand
6+
7+
from marsha.core.utils.transcode import delete_transcoding_temp_files
8+
9+
10+
logger = logging.getLogger(__name__)
11+
12+
13+
class Command(BaseCommand):
14+
"""Delete transcoding temp files."""
15+
16+
help = "Delete transcoding temp files"
17+
18+
def handle(self, *args, **options):
19+
"""Delete all transcoding temp files."""
20+
delete_transcoding_temp_files()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Test transcript_video command."""
2+
3+
from unittest.mock import patch
4+
5+
from django.core.management import call_command
6+
from django.test import TestCase
7+
8+
from marsha.core.utils import transcode
9+
10+
11+
@patch.object(transcode, "delete_transcoding_temp_files")
12+
class TranscriptVideosTestCase(TestCase):
13+
"""
14+
Test case for the transcript_videos command.
15+
"""
16+
17+
maxDiff = None
18+
19+
def test_delete_transcoding_temp_files(self, mock_delete_temp_files):
20+
"""Should call delete_transcoding_temp_files function."""
21+
call_command("delete_transcoding_temp_files")
22+
23+
mock_delete_temp_files.assert_called_once()

src/backend/marsha/core/tests/utils/test_transcode.py

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
"""Tests for the `core.utils.transcode` module."""
22

3+
from unittest.mock import patch
4+
from uuid import uuid4
5+
36
from django.test import TestCase
47

8+
from django_peertube_runner_connector.factories import (
9+
VideoFactory as TranscodedVideoFactory,
10+
)
511
from django_peertube_runner_connector.models import (
612
Video as TranscodedVideo,
713
VideoFile,
@@ -12,11 +18,14 @@
1218
from marsha.core import defaults
1319
from marsha.core.factories import VideoFactory
1420
from marsha.core.utils.time_utils import to_datetime
15-
from marsha.core.utils.transcode import transcoding_ended_callback
21+
from marsha.core.utils.transcode import (
22+
delete_transcoding_temp_files,
23+
transcoding_ended_callback,
24+
)
1625

1726

18-
class TranscodeTestCase(TestCase):
19-
"""Test the `transcode` functions."""
27+
class TranscodingEndedCallbackTestCase(TestCase):
28+
"""Test the `transcoding_ended_callback` function."""
2029

2130
def setUp(self):
2231
# Create a test video
@@ -31,6 +40,7 @@ def setUp(self):
3140
state=VideoState.PUBLISHED,
3241
directory=f"vod/{self.video.pk}/video/1698941501",
3342
)
43+
3444
self.video_playlist = VideoStreamingPlaylist.objects.create(
3545
video=self.transcoded_video
3646
)
@@ -50,31 +60,59 @@ def setUp(self):
5060
extname="mp4",
5161
)
5262

53-
def test_transcoding_ended_callback(self):
63+
@patch("marsha.core.utils.transcode.delete_temp_file")
64+
def test_transcoding_ended_callback(self, mock_delete_temp_file):
5465
"""The marsha video should correctly be updated."""
5566
transcoding_ended_callback(self.transcoded_video)
5667

5768
self.video.refresh_from_db()
58-
5969
self.assertEqual(self.video.uploaded_on, to_datetime("1698941501"))
60-
6170
self.assertEqual(self.video.resolutions, [720, 1080])
62-
6371
self.assertEqual(self.video.upload_state, defaults.READY)
6472
self.assertEqual(self.video.transcode_pipeline, defaults.PEERTUBE_PIPELINE)
73+
mock_delete_temp_file.assert_called_once_with(
74+
self.transcoded_video, f"tmp/{self.video.pk}/video/1698941501"
75+
)
6576

66-
def test_transcoding_ended_callback_with_error(self):
77+
@patch("marsha.core.utils.transcode.delete_temp_file")
78+
def test_transcoding_ended_callback_with_error(self, mock_delete_temp_file):
6779
"""The marsha video should be set with state on error and nothing else should be done."""
6880
self.transcoded_video.state = VideoState.TRANSCODING_FAILED
6981

7082
transcoding_ended_callback(self.transcoded_video)
7183

7284
self.video.refresh_from_db()
73-
7485
self.assertEqual(self.video.upload_state, defaults.ERROR)
75-
7686
self.assertEqual(self.video.uploaded_on, None)
77-
7887
self.assertEqual(self.video.resolutions, [])
79-
8088
self.assertEqual(self.video.transcode_pipeline, None)
89+
mock_delete_temp_file.assert_called_once_with(
90+
self.transcoded_video, f"tmp/{self.video.pk}/video/1698941501"
91+
)
92+
93+
94+
class DeleteTranscodingTempFilesTestCase(TestCase):
95+
"""Test the `delete_transcoding_temp_files` function."""
96+
97+
@patch("marsha.core.utils.transcode.delete_temp_file")
98+
def test_transcoding_delete_transcoding_temp_files(self, mock_delete_temp_file):
99+
"""The temp files should be deleted."""
100+
video_id = uuid4()
101+
video_file = TranscodedVideoFactory(
102+
directory=f"vod/{video_id}/video/1698941501"
103+
)
104+
105+
delete_transcoding_temp_files()
106+
107+
mock_delete_temp_file.assert_called_once_with(
108+
video_file, f"tmp/{video_id}/video/1698941501"
109+
)
110+
111+
@patch("marsha.core.utils.transcode.delete_temp_file")
112+
def test_transcoding_delete_transcoding_temp_files_all(self, mock_delete_temp_file):
113+
"""All video files should be processed."""
114+
TranscodedVideoFactory.create_batch(15)
115+
116+
delete_transcoding_temp_files()
117+
118+
self.assertEqual(mock_delete_temp_file.call_count, 15)

src/backend/marsha/core/utils/transcode.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
""" Utils related to transcoding """
22

33
from django_peertube_runner_connector.models import Video as TranscodedVideo, VideoState
4-
5-
from marsha.core.defaults import ERROR, PEERTUBE_PIPELINE, READY
4+
from django_peertube_runner_connector.utils.files import delete_temp_file
5+
6+
from marsha.core.defaults import (
7+
ERROR,
8+
PEERTUBE_PIPELINE,
9+
READY,
10+
TMP_VIDEOS_STORAGE_BASE_DIRECTORY,
11+
VOD_VIDEOS_STORAGE_BASE_DIRECTORY,
12+
)
613
from marsha.core.models.video import Video
714
from marsha.core.utils.time_utils import to_datetime
815

916

1017
def transcoding_ended_callback(transcoded_video: TranscodedVideo):
1118
"""
12-
Callback used when the a Peertube runnner has finished
19+
Callback used when a Peertube runner has finished
1320
to transcode a video.
1421
1522
Parameters
@@ -23,6 +30,11 @@ def transcoding_ended_callback(transcoded_video: TranscodedVideo):
2330
uploaded_on = directory[-1]
2431
video_id = directory[-3]
2532
video = Video.objects.get(pk=video_id)
33+
tmp_filename = transcoded_video.directory.replace(
34+
VOD_VIDEOS_STORAGE_BASE_DIRECTORY, TMP_VIDEOS_STORAGE_BASE_DIRECTORY
35+
)
36+
37+
delete_temp_file(transcoded_video, tmp_filename)
2638

2739
if transcoded_video.state == VideoState.TRANSCODING_FAILED:
2840
video.update_upload_state(ERROR, None)
@@ -39,3 +51,12 @@ def transcoding_ended_callback(transcoded_video: TranscodedVideo):
3951
to_datetime(uploaded_on),
4052
**{"resolutions": resolutions},
4153
)
54+
55+
56+
def delete_transcoding_temp_files():
57+
"""Delete all transcoding temp files."""
58+
for transcoded_video in TranscodedVideo.objects.all():
59+
tmp_filename = transcoded_video.directory.replace(
60+
VOD_VIDEOS_STORAGE_BASE_DIRECTORY, TMP_VIDEOS_STORAGE_BASE_DIRECTORY
61+
)
62+
delete_temp_file(transcoded_video, tmp_filename)

0 commit comments

Comments
 (0)