Move partitioning to message renderer facade

pull/278/head
Alexey Golub 5 years ago
parent bf56902134
commit 5c2e725739

@ -10,16 +10,19 @@ namespace DiscordChatExporter.Core.Rendering
private readonly string _baseFilePath; private readonly string _baseFilePath;
private readonly ExportFormat _format; private readonly ExportFormat _format;
private readonly RenderContext _context; private readonly RenderContext _context;
private readonly int? _partitionLimit;
private long _renderedMessageCount;
private int _partitionIndex; private int _partitionIndex;
private TextWriter _writer; private TextWriter _writer;
private IMessageRenderer _innerRenderer; private IMessageRenderer _innerRenderer;
public FacadeMessageRenderer(string baseFilePath, ExportFormat format, RenderContext context) public FacadeMessageRenderer(string baseFilePath, ExportFormat format, RenderContext context, int? partitionLimit)
{ {
_baseFilePath = baseFilePath; _baseFilePath = baseFilePath;
_format = format; _format = format;
_context = context; _context = context;
_partitionLimit = partitionLimit;
} }
private void EnsureInnerRendererInitialized() private void EnsureInnerRendererInitialized()
@ -35,7 +38,7 @@ namespace DiscordChatExporter.Core.Rendering
if (!string.IsNullOrWhiteSpace(dirPath)) if (!string.IsNullOrWhiteSpace(dirPath))
Directory.CreateDirectory(dirPath); Directory.CreateDirectory(dirPath);
// Create writer (will be disposed by renderer) // Create writer
_writer = File.CreateText(filePath); _writer = File.CreateText(filePath);
// Create inner renderer // Create inner renderer
@ -61,33 +64,43 @@ namespace DiscordChatExporter.Core.Rendering
} }
} }
public async Task NextPartitionAsync() private async Task ResetInnerRendererAsync()
{ {
// Dispose writer and inner renderer if (_innerRenderer != null)
await DisposeAsync(); {
_writer = null; await _innerRenderer.DisposeAsync();
_innerRenderer = null; _innerRenderer = null;
}
// Increment partition index if (_writer != null)
_partitionIndex++; {
await _writer.DisposeAsync();
_writer = null;
}
} }
public async Task RenderMessageAsync(Message message) public async Task RenderMessageAsync(Message message)
{ {
// Ensure underlying writer and renderer are initialized
EnsureInnerRendererInitialized(); EnsureInnerRendererInitialized();
// Render the actual message
await _innerRenderer.RenderMessageAsync(message); await _innerRenderer.RenderMessageAsync(message);
}
public async ValueTask DisposeAsync() // Increment count
{ _renderedMessageCount++;
if (_innerRenderer != null)
await _innerRenderer.DisposeAsync();
if (_writer != null) // Update partition if necessary
await _writer.DisposeAsync(); if (_partitionLimit != null && _partitionLimit != 0 && _renderedMessageCount % _partitionLimit == 0)
{
await ResetInnerRendererAsync();
_partitionIndex++;
} }
} }
public async ValueTask DisposeAsync() => await ResetInnerRendererAsync();
}
public partial class FacadeMessageRenderer public partial class FacadeMessageRenderer
{ {
private static string GetPartitionFilePath(string baseFilePath, int partitionIndex) private static string GetPartitionFilePath(string baseFilePath, int partitionIndex)

@ -38,10 +38,10 @@ namespace DiscordChatExporter.Core.Services
// Create renderer // Create renderer
var baseFilePath = GetFilePathFromOutputPath(outputPath, format, context); var baseFilePath = GetFilePathFromOutputPath(outputPath, format, context);
await using var renderer = new FacadeMessageRenderer(baseFilePath, format, context); await using var renderer = new FacadeMessageRenderer(baseFilePath, format, context, partitionLimit);
// Render messages // Render messages
var messageCount = 0L; var renderedAnything = false;
await foreach (var message in _dataService.GetMessagesAsync(token, channel.Id, after, before, progress)) await foreach (var message in _dataService.GetMessagesAsync(token, channel.Id, after, before, progress))
{ {
// Add encountered users to the list of mentionable users // Add encountered users to the list of mentionable users
@ -50,19 +50,11 @@ namespace DiscordChatExporter.Core.Services
// Render message // Render message
await renderer.RenderMessageAsync(message); await renderer.RenderMessageAsync(message);
messageCount++; renderedAnything = true;
// Trigger next partition when needed
if (partitionLimit != null &&
partitionLimit != 0 &&
messageCount % partitionLimit.Value == 0)
{
await renderer.NextPartitionAsync();
}
} }
// Throw if no messages were rendered // Throw if no messages were rendered
if (messageCount == 0) if (!renderedAnything)
throw new DomainException($"Channel [{channel.Name}] contains no messages for specified period"); throw new DomainException($"Channel [{channel.Name}] contains no messages for specified period");
} }
} }

Loading…
Cancel
Save