Kavita/API/Data/ManualMigrations/v0.8.9/MigrateFormatToActivityData.cs
Joe Milazzo e1f421ccc0
Stats Page Overhaul (#4292)
Co-authored-by: Amelia <77553571+Fesaa@users.noreply.github.com>
2025-12-19 12:23:55 -08:00

67 lines
2.3 KiB
C#

using System.Linq;
using System.Threading.Tasks;
using API.Data.Misc;
using API.Entities.Enums;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace API.Data.ManualMigrations;
/// <summary>
/// v0.8.8.16 - Needed to add Format to the ActivityData to optimize a query
/// </summary>
public class MigrateFormatToActivityData : ManualMigration
{
protected override string MigrationName => nameof(MigrateFormatToActivityData);
protected override async Task ExecuteAsync(DataContext context, ILogger<Program> logger)
{
var activitiesWithoutFormat = await context.AppUserReadingSessionActivityData
.Where(d => d.Format == MangaFormat.Unknown)
.Select(d => d.ChapterId)
.Distinct()
.ToListAsync();
if (activitiesWithoutFormat.Count == 0)
{
logger.LogInformation("No activity data requires Format backfill");
return;
}
logger.LogInformation("Backfilling Format for {Count} chapters worth of activity data", activitiesWithoutFormat.Count);
// Batch fetch formats for all affected chapters
var chapterFormats = await context.MangaFile
.Where(f => activitiesWithoutFormat.Contains(f.ChapterId))
.GroupBy(f => f.ChapterId)
.Select(g => new
{
ChapterId = g.Key,
Format = g.OrderBy(f => f.Id).First().Format
})
.ToDictionaryAsync(x => x.ChapterId, x => x.Format);
// Update in batches to avoid memory issues
const int batchSize = 1000;
var updated = 0;
foreach (var chapterIdBatch in activitiesWithoutFormat.Chunk(batchSize))
{
var activities = await context.AppUserReadingSessionActivityData
.Where(d => d.Format == MangaFormat.Unknown && chapterIdBatch.Contains(d.ChapterId))
.ToListAsync();
foreach (var activity in activities)
{
if (!chapterFormats.TryGetValue(activity.ChapterId, out var format)) continue;
activity.Format = format;
updated++;
}
await context.SaveChangesAsync();
}
logger.LogInformation("Backfilled Format for {Count} activity records", updated);
}
}