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:
@@ -7,4 +7,5 @@ public interface ISessionService
|
|||||||
bool IsValidSession(string sessionId);
|
bool IsValidSession(string sessionId);
|
||||||
void CleanupExpiredSessions();
|
void CleanupExpiredSessions();
|
||||||
string GetSessionDownloadsPath(string sessionId);
|
string GetSessionDownloadsPath(string sessionId);
|
||||||
|
void EnsureSessionDirectoryExists(string sessionId);
|
||||||
}
|
}
|
||||||
@@ -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()
|
public string CreateSession()
|
||||||
{
|
{
|
||||||
var sessionId = Guid.NewGuid().ToString("N")[..16]; // Use first 16 characters for shorter IDs
|
var sessionId = Guid.NewGuid().ToString("N")[..16]; // Use first 16 characters for shorter IDs
|
||||||
_sessions[sessionId] = DateTime.UtcNow;
|
_sessions[sessionId] = DateTime.UtcNow;
|
||||||
|
|
||||||
// Ensure session directory exists
|
// Don't create directory here - it will be created when first MP3 is saved
|
||||||
var sessionPath = GetSessionDownloadsPath(sessionId);
|
|
||||||
Directory.CreateDirectory(sessionPath);
|
|
||||||
|
|
||||||
_logger.LogInformation("Created new session: {SessionId}", sessionId);
|
_logger.LogInformation("Created new session: {SessionId}", sessionId);
|
||||||
return sessionId;
|
return sessionId;
|
||||||
}
|
}
|
||||||
@@ -83,7 +86,7 @@ public class SessionService : ISessionService
|
|||||||
{
|
{
|
||||||
if (_sessions.TryRemove(sessionId, out _))
|
if (_sessions.TryRemove(sessionId, out _))
|
||||||
{
|
{
|
||||||
// Clean up session directory
|
// Clean up session directory if it exists
|
||||||
var sessionPath = GetSessionDownloadsPath(sessionId);
|
var sessionPath = GetSessionDownloadsPath(sessionId);
|
||||||
if (Directory.Exists(sessionPath))
|
if (Directory.Exists(sessionPath))
|
||||||
{
|
{
|
||||||
@@ -97,6 +100,10 @@ public class SessionService : ISessionService
|
|||||||
_logger.LogWarning(ex, "Failed to delete expired session directory: {SessionId}", sessionId);
|
_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);
|
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()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_cleanupTimer?.Dispose();
|
_cleanupTimer?.Dispose();
|
||||||
|
|||||||
@@ -104,9 +104,11 @@ public class VideoService : IVideoService
|
|||||||
throw new FileNotFoundException($"yt-dlp.exe not found at {ytDlpPath}");
|
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);
|
var downloadDir = _sessionService.GetSessionDownloadsPath(sessionId);
|
||||||
Directory.CreateDirectory(downloadDir);
|
|
||||||
|
|
||||||
// Get video details first for better filename
|
// Get video details first for better filename
|
||||||
var videoDetails = await GetVideoDetailsAsync(url);
|
var videoDetails = await GetVideoDetailsAsync(url);
|
||||||
|
|||||||
Reference in New Issue
Block a user