Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger progress updates for frozen downloads #4052

Merged
merged 1 commit into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ bld/
# Don't ignore the root bin folder
!/bin/

.config/
.mypy_cache/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
Expand Down
33 changes: 29 additions & 4 deletions Core/Extensions/IOExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using Timer = System.Timers.Timer;

namespace CKAN.Extensions
{
Expand Down Expand Up @@ -64,15 +65,37 @@ public static DriveInfo GetDrive(this DirectoryInfo dir)
/// <param name="src">Stream from which to copy</param>
/// <param name="dest">Stream to which to copy</param>
/// <param name="progress">Callback to notify as we traverse the input, called with count of bytes received</param>
public static void CopyTo(this Stream src, Stream dest, IProgress<long> progress, CancellationToken cancelToken = default)
/// <param name="idleInterval">Maximum timespand to elapse between progress updates, will synthesize extra updates as needed</param>
public static void CopyTo(this Stream src,
Stream dest,
IProgress<long> progress,
TimeSpan? idleInterval = null,
CancellationToken cancelToken = default)
{
// CopyTo says its default buffer is 81920, but we want more than 1 update for a 100 KiB file
const int bufSize = 16384;
var buffer = new byte[bufSize];
long total = 0;
var lastProgressTime = DateTime.Now;
// Sometimes a server just freezes and times out, send extra updates if requested
Timer timer = null;
if (idleInterval.HasValue)
{
timer = new Timer(idleInterval.Value > minProgressInterval
? idleInterval.Value.TotalMilliseconds
: minProgressInterval.TotalMilliseconds)
{
AutoReset = true,
};
timer.Elapsed += (sender, args) =>
{
progress.Report(total);
lastProgressTime = DateTime.Now;
};
timer.Start();
}
// Make sure we get an initial progress notification at the start
progress.Report(total);
var lastProgressTime = DateTime.Now;
while (true)
{
var bytesRead = src.Read(buffer, 0, bufSize);
Expand All @@ -84,8 +107,10 @@ public static void CopyTo(this Stream src, Stream dest, IProgress<long> progress
total += bytesRead;
cancelToken.ThrowIfCancellationRequested();
var now = DateTime.Now;
if (now - lastProgressTime >= progressInterval)
if (now - lastProgressTime >= minProgressInterval)
{
timer?.Stop();
timer?.Start();
progress.Report(total);
lastProgressTime = now;
}
Expand All @@ -103,6 +128,6 @@ public static IEnumerable<byte> BytesFromStream(this Stream s)
}
}

private static readonly TimeSpan progressInterval = TimeSpan.FromMilliseconds(200);
private static readonly TimeSpan minProgressInterval = TimeSpan.FromMilliseconds(200);
}
}
1 change: 1 addition & 0 deletions Core/Net/ResumingWebClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ protected override void OnOpenReadCompleted(OpenReadCompletedEventArgs e)
DownloadProgress?.Invoke((int)(100 * bytesDownloaded / contentLength),
bytesDownloaded, contentLength);
}),
TimeSpan.FromSeconds(5),
cancelTokenSrc.Token);
// Make sure caller knows we've finished
DownloadProgress?.Invoke(100, contentLength, contentLength);
Expand Down
Loading