duplicati/Duplicati/Library/Main/Backend/BackendManager.ProgressHandler.cs
Kenneth Skovhede c8b9fb5c73 Websocket subscriptions
This PR adds the ability to subscribe to messages over a websocket.

To prevent polling data, the server can now push messages through the websocket, so the client can instantly update when new data is available.

The change is backwards compatible, still serving the status updates over the socket. If the client is providing the authentication token, it is auto-subscried to the legacy status message.

If the client is using the new authentication message, it needs to subscribe to get the status updates (and any other services it needs).

The event system has been extended to support new, and more accurate, events. This is the first step towards removing the general status update and the long-poll mechanism.

This also re-introduces the blocking marker, so the client can know if the operation is halted due to too many pending transfers.

Some endpoints have been moved to service implementations, to allow serving the exact same data from both endpoints and websocket.

This PR also updates the way the progress is handled, so that all transfers are returned to the client, and the transfer speeds for each transfer is calculated based on a small sample buffer, so the values are more accurate even if the program is paused during transfers.
2025-05-27 12:13:07 +02:00

50 lines
No EOL
1.7 KiB
C#

using Duplicati.Library.Main.Operation.Common;
using Duplicati.Library.Utility;
namespace Duplicati.Library.Main.Backend;
#nullable enable
partial class BackendManager
{
/// <summary>
/// Handles the progress of file transfers for the backend
/// </summary>
private sealed record ProgressHandler(IBackendWriter Stats, ITaskReader TaskReader)
{
/// <summary>
/// Handles the progress of a stream
/// </summary>
/// <param name="pg">The progress</param>
/// <param name="filename">The filename</param>
public void HandleProgress(long pg, string filename)
{
// This pauses and throws on cancellation, but ignores stop
TaskReader.TransferRendevouz().Await();
Stats.BackendProgressUpdater.UpdateProgress(filename, pg);
}
/// <summary>
/// Begins the transfer of a file
/// </summary>
/// <param name="filename">The filename</param>
public void BeginTransfer(BackendActionType type, long size, string filename)
=> Stats.BackendProgressUpdater.StartAction(type, filename, size);
/// <summary>
/// Ends the transfer of a file
/// </summary>
/// <param name="type">The type of action</param>
/// <param name="filename">The filename</param>
public void EndTransfer(BackendActionType type, string filename)
=> Stats.BackendProgressUpdater.EndAction(type, filename);
/// <summary>
/// Sets whether the backend is blocking
/// </summary>
/// <param name="blocking">True if blocking, false otherwise</param>
public void SetIsBlocking(bool blocking)
=> Stats.BackendProgressUpdater.SetBlocking(blocking);
}
}