Actually fix concurrency in tests this time

pull/1002/head
Tyrrrz 2 years ago
parent d5848bebc6
commit 1fc27fd5c4

@ -1,9 +1,11 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.Json; using System.Text.Json;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using AngleSharp.Html.Dom; using AngleSharp.Html.Dom;
@ -18,6 +20,8 @@ namespace DiscordChatExporter.Cli.Tests.Infra;
public static class ExportWrapper public static class ExportWrapper
{ {
private static readonly ConcurrentDictionary<string, SemaphoreSlim> Locks = new();
private static readonly string DirPath = Path.Combine( private static readonly string DirPath = Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Directory.GetCurrentDirectory(), Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Directory.GetCurrentDirectory(),
"ExportCache" "ExportCache"
@ -38,22 +42,33 @@ public static class ExportWrapper
private static async ValueTask<string> ExportAsync(Snowflake channelId, ExportFormat format) private static async ValueTask<string> ExportAsync(Snowflake channelId, ExportFormat format)
{ {
var fileName = channelId.ToString() + '.' + format.GetFileExtension(); // Lock separately for each channel and format
var filePath = Path.Combine(DirPath, fileName); var channelLock = Locks.GetOrAdd($"{channelId}_{format}", _ => new SemaphoreSlim(1, 1));
await channelLock.WaitAsync();
// Perform export only if it hasn't been done before try
if (!File.Exists(filePath))
{ {
await new ExportChannelsCommand var fileName = channelId.ToString() + '.' + format.GetFileExtension();
var filePath = Path.Combine(DirPath, fileName);
// Perform export only if it hasn't been done before
if (!File.Exists(filePath))
{ {
Token = Secrets.DiscordToken, await new ExportChannelsCommand
ChannelIds = new[] { channelId }, {
ExportFormat = format, Token = Secrets.DiscordToken,
OutputPath = filePath ChannelIds = new[] { channelId },
}.ExecuteAsync(new FakeConsole()); ExportFormat = format,
OutputPath = filePath
}.ExecuteAsync(new FakeConsole());
}
return await File.ReadAllTextAsync(filePath);
}
finally
{
channelLock.Release();
} }
return await File.ReadAllTextAsync(filePath);
} }
public static async ValueTask<IHtmlDocument> ExportAsHtmlAsync(Snowflake channelId) => Html.Parse( public static async ValueTask<IHtmlDocument> ExportAsHtmlAsync(Snowflake channelId) => Html.Parse(

Loading…
Cancel
Save