Lazily create session directories on first MP3 save

Session directories are now created only when the first MP3 file is saved, not at session creation. Added EnsureSessionDirectoryExists to ISessionService and SessionService to handle this logic. Updated VideoService to call this method before saving files. Cleanup now logs when no directory exists for expired sessions.
This commit is contained in:
Michal Vrba
2025-12-14 16:39:00 +01:00
parent dec69eb937
commit 879fbd4a53
3 changed files with 45 additions and 7 deletions
@@ -7,4 +7,5 @@ public interface ISessionService
bool IsValidSession(string sessionId);
void CleanupExpiredSessions();
string GetSessionDownloadsPath(string sessionId);
void EnsureSessionDirectoryExists(string sessionId);
}
+40 -5
View File
@@ -26,15 +26,18 @@ public class SessionService : ISessionService
);
}
/// <summary>
/// Creates a new session with a unique ID.
/// Note: The session directory is NOT created at this point - it will be created
/// lazily when the first MP3 file is saved using EnsureSessionDirectoryExists().
/// </summary>
/// <returns>The unique session ID</returns>
public string CreateSession()
{
var sessionId = Guid.NewGuid().ToString("N")[..16]; // Use first 16 characters for shorter IDs
_sessions[sessionId] = DateTime.UtcNow;
// Ensure session directory exists
var sessionPath = GetSessionDownloadsPath(sessionId);
Directory.CreateDirectory(sessionPath);
// Don't create directory here - it will be created when first MP3 is saved
_logger.LogInformation("Created new session: {SessionId}", sessionId);
return sessionId;
}
@@ -83,7 +86,7 @@ public class SessionService : ISessionService
{
if (_sessions.TryRemove(sessionId, out _))
{
// Clean up session directory
// Clean up session directory if it exists
var sessionPath = GetSessionDownloadsPath(sessionId);
if (Directory.Exists(sessionPath))
{
@@ -97,6 +100,10 @@ public class SessionService : ISessionService
_logger.LogWarning(ex, "Failed to delete expired session directory: {SessionId}", sessionId);
}
}
else
{
_logger.LogDebug("No directory to clean up for expired session: {SessionId} (no MP3 files were downloaded)", sessionId);
}
}
}
@@ -117,6 +124,34 @@ public class SessionService : ISessionService
return Path.Combine(downloadsRoot, sessionId);
}
/// <summary>
/// Ensures that the session directory exists, creating it if necessary.
/// This method should be called just before saving the first MP3 file in a session.
/// </summary>
/// <param name="sessionId">The session ID</param>
/// <exception cref="ArgumentException">Thrown when sessionId is null or empty</exception>
/// <exception cref="InvalidOperationException">Thrown when session is invalid or expired</exception>
public void EnsureSessionDirectoryExists(string sessionId)
{
if (string.IsNullOrWhiteSpace(sessionId))
{
throw new ArgumentException("Session ID cannot be null or empty", nameof(sessionId));
}
if (!IsValidSession(sessionId))
{
throw new InvalidOperationException($"Invalid session ID: {sessionId}");
}
var sessionPath = GetSessionDownloadsPath(sessionId);
if (!Directory.Exists(sessionPath))
{
Directory.CreateDirectory(sessionPath);
_logger.LogInformation("Created session directory for session: {SessionId} at {Path}", sessionId, sessionPath);
}
}
public void Dispose()
{
_cleanupTimer?.Dispose();
+4 -2
View File
@@ -104,9 +104,11 @@ public class VideoService : IVideoService
throw new FileNotFoundException($"yt-dlp.exe not found at {ytDlpPath}");
}
// Get session-specific download directory
// Ensure session directory exists only when we're about to save the first MP3 file
_sessionService.EnsureSessionDirectoryExists(sessionId);
// Get session-specific download directory (now guaranteed to exist)
var downloadDir = _sessionService.GetSessionDownloadsPath(sessionId);
Directory.CreateDirectory(downloadDir);
// Get video details first for better filename
var videoDetails = await GetVideoDetailsAsync(url);