Refactor code structure for improved readability and maintainability

This commit is contained in:
MaddoScientisto 2026-02-21 10:40:12 +01:00
commit 4f488bae45
78 changed files with 3309 additions and 1570 deletions

View file

@ -0,0 +1,14 @@
using Microsoft.EntityFrameworkCore;
using TwitchArchive.Core.Persistence.Models;
namespace TwitchArchive.Core.Persistence
{
public class ArchiveDbContext : DbContext
{
public ArchiveDbContext(DbContextOptions<ArchiveDbContext> options) : base(options) { }
public DbSet<StreamSession> StreamSessions { get; set; } = null!;
public DbSet<ArchiveJob> ArchiveJobs { get; set; } = null!;
public DbSet<StreamerState> StreamerStates { get; set; } = null!;
}
}

View file

@ -0,0 +1,17 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using TwitchArchive.Core.Persistence.Models;
namespace TwitchArchive.Core.Persistence
{
public interface ISessionRepository
{
Task<StreamSession> CreateSessionAsync(string username, string streamId, DateTime startedAt, CancellationToken ct = default);
Task EndSessionAsync(long sessionId, DateTime endedAt, string status, CancellationToken ct = default);
Task<ArchiveJob> CreateJobAsync(long sessionId, string jobType, DateTime startedAt, CancellationToken ct = default);
Task UpdateJobAsync(ArchiveJob job, CancellationToken ct = default);
Task<List<StreamSession>> GetRecentSessionsAsync(int max = 50, CancellationToken ct = default);
Task<List<ArchiveJob>> GetJobsForSessionAsync(long sessionId, CancellationToken ct = default);
}
}

View file

@ -0,0 +1,16 @@
using System;
namespace TwitchArchive.Core.Persistence.Models
{
public class ArchiveJob
{
public long Id { get; set; }
public long StreamSessionId { get; set; }
public string JobType { get; set; } = string.Empty; // enum name
public string Status { get; set; } = string.Empty; // Pending, Running, Completed, Failed
public DateTime StartedAt { get; set; }
public DateTime? CompletedAt { get; set; }
public string? FilePath { get; set; }
public string? ErrorMessage { get; set; }
}
}

View file

@ -0,0 +1,15 @@
using System;
namespace TwitchArchive.Core.Persistence.Models
{
public class StreamSession
{
public long Id { get; set; }
public string StreamerUsername { get; set; } = string.Empty;
public string TwitchStreamId { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public DateTime StartedAt { get; set; }
public DateTime? EndedAt { get; set; }
public string Status { get; set; } = string.Empty; // Recording, Processing, Uploading, Complete, Failed
}
}

View file

@ -0,0 +1,13 @@
using System;
namespace TwitchArchive.Core.Persistence.Models
{
public class StreamerState
{
public long Id { get; set; }
public string Username { get; set; } = string.Empty;
public bool IsMonitoring { get; set; }
public DateTime? LastCheckedAt { get; set; }
public string? CurrentRecoveryState { get; set; }
}
}

View file

@ -0,0 +1,62 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using TwitchArchive.Core.Persistence.Models;
namespace TwitchArchive.Core.Persistence
{
public class SessionRepository : ISessionRepository
{
private readonly IDbContextFactory<ArchiveDbContext> _factory;
public SessionRepository(IDbContextFactory<ArchiveDbContext> factory) { _factory = factory ?? throw new ArgumentNullException(nameof(factory)); }
public async Task<StreamSession> CreateSessionAsync(string username, string streamId, DateTime startedAt, CancellationToken ct = default)
{
await using var db = _factory.CreateDbContext();
var s = new StreamSession { StreamerUsername = username, TwitchStreamId = streamId, StartedAt = startedAt, Status = "Recording" };
db.StreamSessions.Add(s);
await db.SaveChangesAsync(ct).ConfigureAwait(false);
return s;
}
public async Task EndSessionAsync(long sessionId, DateTime endedAt, string status, CancellationToken ct = default)
{
await using var db = _factory.CreateDbContext();
var s = await db.StreamSessions.FindAsync(new object[] { sessionId }, ct).ConfigureAwait(false);
if (s == null) return;
s.EndedAt = endedAt;
s.Status = status;
await db.SaveChangesAsync(ct).ConfigureAwait(false);
}
public async Task<ArchiveJob> CreateJobAsync(long sessionId, string jobType, DateTime startedAt, CancellationToken ct = default)
{
await using var db = _factory.CreateDbContext();
var j = new ArchiveJob { StreamSessionId = sessionId, JobType = jobType, StartedAt = startedAt, Status = "Running" };
db.ArchiveJobs.Add(j);
await db.SaveChangesAsync(ct).ConfigureAwait(false);
return j;
}
public async Task UpdateJobAsync(ArchiveJob job, CancellationToken ct = default)
{
await using var db = _factory.CreateDbContext();
db.ArchiveJobs.Update(job);
await db.SaveChangesAsync(ct).ConfigureAwait(false);
}
public async Task<List<StreamSession>> GetRecentSessionsAsync(int max = 50, CancellationToken ct = default)
{
await using var db = _factory.CreateDbContext();
return await db.StreamSessions.OrderByDescending(s => s.StartedAt).Take(max).ToListAsync(ct).ConfigureAwait(false);
}
public async Task<List<ArchiveJob>> GetJobsForSessionAsync(long sessionId, CancellationToken ct = default)
{
await using var db = _factory.CreateDbContext();
return await db.ArchiveJobs.Where(j => j.StreamSessionId == sessionId).OrderBy(j => j.StartedAt).ToListAsync(ct).ConfigureAwait(false);
}
}
}