using Microsoft.Extensions.Logging; using SharpChat.Messages; using ZLogger; namespace SharpChat; public class StorageMigrator(ILogger logger, Storage source, Storage target) { public async Task Migrate(CancellationToken cancellationToken) { try { logger.ZLogInformation($"Converting from {source.GetType().Name} to {target.GetType().Name}!"); logger.ZLogInformation($"Ensuring both source and target are fully upgraded..."); if(cancellationToken.IsCancellationRequested) return; await source.UpgradeStorage(); if(cancellationToken.IsCancellationRequested) return; await target.UpgradeStorage(); if(cancellationToken.IsCancellationRequested) return; logger.ZLogInformation($"Creating message storage instances..."); MessageStorage sourceMsgs = source.CreateMessageStorage(); MessageStorage targetMsgs = target.CreateMessageStorage(); if(cancellationToken.IsCancellationRequested) return; long msgCount = await sourceMsgs.CountMessages(includeDeleted: true); if(msgCount < 1) { logger.ZLogInformation($"No messages to migrate, skipping..."); } else { logger.ZLogInformation($"Migrating {msgCount} message{(msgCount == 1 ? "" : "s")}..."); long migrated = 0; DateTimeOffset lastReport = DateTimeOffset.UtcNow; IEnumerable<Message> msgs = await sourceMsgs.GetMessages(take: null, includeDeleted: true); foreach(Message msg in msgs) { if(cancellationToken.IsCancellationRequested) break; await targetMsgs.LogMessage(msg); ++migrated; if(DateTimeOffset.UtcNow - lastReport > TimeSpan.FromMinutes(1)) { lastReport = DateTimeOffset.UtcNow; double completion = (double)migrated / msgCount; logger.ZLogInformation($"{migrated} of {msgCount} message{(migrated == 1 ? "" : "s")} migrated ({completion:P2})..."); } } logger.ZLogInformation($"Migrated {migrated} message{(migrated == 1 ? "" : "s")}!"); } } catch(Exception ex) { logger.ZLogError($"Error during migration: {ex}"); throw; } } }