49 lines
1.3 KiB
C#
49 lines
1.3 KiB
C#
using System.Collections.Concurrent;
|
|
|
|
namespace LightlessSync.WebAPI.Files;
|
|
|
|
public readonly record struct DownloadClaim(bool IsOwner, Task<bool> Completion);
|
|
|
|
public sealed class FileDownloadDeduplicator
|
|
{
|
|
private readonly ConcurrentDictionary<string, TaskCompletionSource<bool>> _inFlight =
|
|
new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
public DownloadClaim Claim(string hash)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(hash))
|
|
{
|
|
return new DownloadClaim(false, Task.FromResult(true));
|
|
}
|
|
|
|
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
var existing = _inFlight.GetOrAdd(hash, tcs);
|
|
var isOwner = ReferenceEquals(existing, tcs);
|
|
return new DownloadClaim(isOwner, existing.Task);
|
|
}
|
|
|
|
public void Complete(string hash, bool success)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(hash))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_inFlight.TryRemove(hash, out var tcs))
|
|
{
|
|
tcs.TrySetResult(success);
|
|
}
|
|
}
|
|
|
|
public void CompleteAll(bool success)
|
|
{
|
|
foreach (var entry in _inFlight.ToArray())
|
|
{
|
|
if (_inFlight.TryRemove(entry.Key, out var tcs))
|
|
{
|
|
tcs.TrySetResult(success);
|
|
}
|
|
}
|
|
}
|
|
}
|