Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ namespace ByteSync.Business.Communications.Transfers;

public class SliceUploadMetric
{
public int TaskId { get; set; }

public int PartNumber { get; set; }

public long Bytes { get; set; }
public long DurationMs { get; set; }
public double BandwidthKbps { get; set; }

public long ElapsedtimeMs { get; set; }

}


Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ public class UploadProgressState
public int TotalUploadedSlices { get; set; }
public int ConcurrentUploads { get; set; }
public int MaxConcurrentUploads { get; set; }
public Exception? LastException { get; set; }
public DateTimeOffset? StartTimeUtc { get; set; }
public DateTimeOffset? EndTimeUtc { get; set; }
public long TotalCreatedBytes { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ public async Task SliceAndEncryptAsync(SharedFileDefinition sharedFileDefinition
await _semaphoreSlim.WaitAsync();
try
{
progressState.LastException = ex;
progressState.Exceptions.Add(ex);
}
finally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public async Task ProcessUpload(SharedFileDefinition sharedFileDefinition, int?
_progressState.StartTimeUtc = DateTimeOffset.UtcNow;

// Start upload workers
for (var i = 0; i < 6; i++)
for (var i = 0; i < 2; i++)
{
_ = Task.Run(() => _fileUploadWorker.UploadAvailableSlicesAsync(_fileUploadCoordinator.AvailableSlices, _progressState));
}
Expand All @@ -60,11 +60,12 @@ await Task.Run(() => _fileSlicer.SliceAndEncryptAsync(sharedFileDefinition, _pro

_slicerEncrypter.Dispose();

if (_progressState.LastException != null)
if (_progressState.Exceptions != null && _progressState.Exceptions.Count > 0)
{
var source = _localFileToUpload ?? "a stream";
throw new Exception($"An error occured while uploading '{source}' / sharedFileDefinition.Id:{sharedFileDefinition.Id}",
_progressState.LastException);
var lastException = _progressState.Exceptions[_progressState.Exceptions.Count - 1];
throw new InvalidOperationException($"An error occured while uploading '{source}' / sharedFileDefinition.Id:{sharedFileDefinition.Id}",
lastException);
}

var totalCreatedSlices = GetTotalCreatedSlices();
Expand All @@ -83,7 +84,7 @@ await Task.Run(() => _fileSlicer.SliceAndEncryptAsync(sharedFileDefinition, _pro
totalBytes / 1024d,
_progressState.MaxConcurrentUploads,
bandwidthKbps,
_progressState.Exceptions.Count);
_progressState.Exceptions!.Count);
}

public int GetTotalCreatedSlices()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,14 @@ public async Task UploadAvailableSlicesAsync(Channel<FileUploaderSlice> availabl
var sliceBytes = slice.MemoryStream?.Length ?? 0L;
progressState.TotalUploadedBytes += sliceBytes;
var elapsedMs = sliceStart.ElapsedMilliseconds;
var kbps = elapsedMs > 0 ? (sliceBytes * 8.0) / elapsedMs : 0.0;
progressState.LastSliceUploadDurationMs = elapsedMs;
progressState.LastSliceUploadedBytes = sliceBytes;
progressState.SliceMetrics.Add(new SliceUploadMetric
{
TaskId = Environment.CurrentManagedThreadId,
PartNumber = slice.PartNumber,
Bytes = sliceBytes,
DurationMs = elapsedMs,
BandwidthKbps = kbps
ElapsedtimeMs = elapsedMs,
});
}
finally
Expand Down Expand Up @@ -127,7 +126,6 @@ public async Task UploadAvailableSlicesAsync(Channel<FileUploaderSlice> availabl
await _semaphoreSlim.WaitAsync();
try
{
progressState.LastException = ex;
progressState.Exceptions.Add(ex);
}
finally
Expand Down
21 changes: 11 additions & 10 deletions src/ByteSync.Client/Services/Encryptions/SlicerEncrypter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Threading;
using ByteSync.Business.Communications.Transfers;
using ByteSync.Common.Business.SharedFiles;
using ByteSync.Interfaces.Controls.Encryptions;
Expand All @@ -22,8 +22,7 @@ public SlicerEncrypter(ICloudSessionConnectionRepository cloudSessionConnectionR
_logger = logger;

BufferSize = 4096;
MaxSliceLength = 64 * 1024 * 1024; // 64 Mo
MaxSliceLength = 4 * 1024 * 1024; // 4 Mo
MaxSliceLength = 1024 * 1024; // 1 Mb
}

public void Initialize(FileInfo fileToEncrypt, SharedFileDefinition sharedFileDefinition)
Expand Down Expand Up @@ -83,7 +82,7 @@ public int MaxSliceLength

public async Task<FileUploaderSlice?> SliceAndEncrypt()
{
CryptoStream? cryptoSteam = null;
CryptoStream? cryptoStream = null;
FileUploaderSlice? fileUploaderSlice = null;

var bytes = InReader.ReadBytes(BufferSize);
Expand All @@ -93,19 +92,19 @@ public int MaxSliceLength
var canContinue = TotalGeneratedFiles == 0 || readBytes > 0;
while (canContinue)
{
if (cryptoSteam == null)
if (cryptoStream == null)
{
TotalGeneratedFiles += 1;

var memoryStream = new MemoryStream();
var encryptor = Aes.CreateEncryptor(Aes.Key, Aes.IV);
cryptoSteam = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write, true);
cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write, true);

fileUploaderSlice = new FileUploaderSlice(TotalGeneratedFiles, memoryStream);
}

await cryptoSteam.WriteAsync(bytes, 0, readBytes);

await cryptoStream.WriteAsync(bytes.AsMemory(0, readBytes), CancellationToken.None);
var sizeToRead = BufferSize;
if (thisSessionReadBytes + sizeToRead > MaxSliceLength)
{
Expand All @@ -129,7 +128,7 @@ public int MaxSliceLength
}
}

cryptoSteam?.Dispose();
cryptoStream?.Dispose();

return fileUploaderSlice;
}
Expand All @@ -139,5 +138,7 @@ public void Dispose()
InStream?.Dispose();
InReader?.Dispose();
Aes?.Dispose();

GC.SuppressFinalize(this);
}
}
21 changes: 15 additions & 6 deletions src/ByteSync.Client/Services/Themes/ThemeFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ private ColorScheme BuildColorScheme(Theme theme, ThemeColor themeColor, double
colorScheme.MainWindowTopColor = colorScheme.VeryLightGray;
colorScheme.MainWindowBottomColor = Color.FromArgb(0xFF, 0x04, 0x04, 0x04);

ComputeSecondaryColors(colorScheme, secondaryColorHue);
ComputeSecondaryColors(colorScheme, secondaryColorHue, themeMode);

colorScheme.StatusMainBackGroundBrush = new SolidColorBrush(colorScheme.StatusMainBackGround.AvaloniaColor);
colorScheme.StatusSecondaryBackGroundBrush = new SolidColorBrush(colorScheme.StatusSecondaryBackGround.AvaloniaColor);
Expand Down Expand Up @@ -213,7 +213,7 @@ private ColorScheme BuildColorScheme(Theme theme, ThemeColor themeColor, double
colorScheme.MainWindowTopColor = Color.FromArgb(0xFF, 0xFA, 0xFA, 0xFA);
colorScheme.MainWindowBottomColor = Color.FromArgb(0xFF, 0xEF, 0xEF, 0xEF);

ComputeSecondaryColors(colorScheme, secondaryColorHue);
ComputeSecondaryColors(colorScheme, secondaryColorHue, themeMode);

colorScheme.StatusMainBackGroundBrush = new SolidColorBrush(colorScheme.StatusMainBackGround.AvaloniaColor);
colorScheme.StatusSecondaryBackGroundBrush = new SolidColorBrush(colorScheme.StatusSecondaryBackGround.AvaloniaColor);
Expand All @@ -227,7 +227,7 @@ private ColorScheme BuildColorScheme(Theme theme, ThemeColor themeColor, double
return colorScheme;
}

private void ComputeSecondaryColors(ColorScheme colorScheme, double secondaryColorHue)
private void ComputeSecondaryColors(ColorScheme colorScheme, double secondaryColorHue, ThemeModes themeMode)
{
for (int i = 1; i <= 3; i++)
{
Expand All @@ -241,9 +241,18 @@ private void ComputeSecondaryColors(ColorScheme colorScheme, double secondaryCol

colorScheme.OtherMemberSecondaryBackGround = colorScheme.OtherMemberBackGround
.WithHue(secondaryColorHue);

colorScheme.StatusSecondaryBackGround = colorScheme.StatusMainBackGround
.WithHue(secondaryColorHue);

if (themeMode == ThemeModes.Dark)
{
colorScheme.StatusSecondaryBackGround = colorScheme.StatusMainBackGround
.WithHue(secondaryColorHue)
.AdjustSaturationValue(0, +0.20);
}
else
{
colorScheme.StatusSecondaryBackGround = colorScheme.StatusMainBackGround
.WithHue(secondaryColorHue);
}
}

private static void ComputeAttenuations(ColorScheme colorScheme)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using ByteSync.ServerCommon.Interfaces.Repositories;
using ByteSync.ServerCommon.Interfaces.Services;
using MediatR;
using Microsoft.Extensions.Logging;

namespace ByteSync.ServerCommon.Commands.Synchronizations;

public abstract class ActionCompletedHandlerBase<TRequest> : IRequestHandler<TRequest>
where TRequest : IActionCompletedRequest
{
protected readonly ITrackingActionRepository _trackingActionRepository;
protected readonly ISynchronizationStatusCheckerService _synchronizationStatusCheckerService;
protected readonly ISynchronizationProgressService _synchronizationProgressService;
protected readonly ISynchronizationService _synchronizationService;
protected readonly ILogger _logger;

protected ActionCompletedHandlerBase(
ITrackingActionRepository trackingActionRepository,
ISynchronizationStatusCheckerService synchronizationStatusCheckerService,
ISynchronizationProgressService synchronizationProgressService,
ISynchronizationService synchronizationService,
ILogger logger)
{
_trackingActionRepository = trackingActionRepository;
_synchronizationStatusCheckerService = synchronizationStatusCheckerService;
_synchronizationProgressService = synchronizationProgressService;
_synchronizationService = synchronizationService;
_logger = logger;
}

protected abstract string EmptyIdsLog { get; }
protected abstract string DoneLogTemplate { get; }

public async Task Handle(TRequest request, CancellationToken cancellationToken)
{
if (request.ActionsGroupIds.Count == 0)
{
_logger.LogInformation(EmptyIdsLog);
return;
}

var needSendSynchronizationUpdated = false;

var result = await _trackingActionRepository.AddOrUpdate(request.SessionId, request.ActionsGroupIds, (trackingAction, synchronization) =>
{
if (!_synchronizationStatusCheckerService.CheckSynchronizationCanBeUpdated(synchronization))
{
return false;
}

var wasTrackingActionFinished = trackingAction.IsFinished;

trackingAction.AddSuccessOnTarget(request.Client.ClientInstanceId);

if (!wasTrackingActionFinished && trackingAction.IsFinished)
{
synchronization.Progress.FinishedActionsCount += 1;
}

needSendSynchronizationUpdated = _synchronizationService.CheckSynchronizationIsFinished(synchronization);

return true;
});

if (result.IsSuccess)
{
await _synchronizationProgressService.UpdateSynchronizationProgress(result, needSendSynchronizationUpdated);
}

_logger.LogInformation(DoneLogTemplate, request.SessionId, request.ActionsGroupIds.Count);
}
}


Original file line number Diff line number Diff line change
@@ -1,69 +1,21 @@
using ByteSync.ServerCommon.Interfaces.Repositories;
using ByteSync.ServerCommon.Interfaces.Services;
using MediatR;
using Microsoft.Extensions.Logging;

namespace ByteSync.ServerCommon.Commands.Synchronizations;

public class DateIsCopiedCommandHandler : IRequestHandler<DateIsCopiedRequest>
public class DateIsCopiedCommandHandler : ActionCompletedHandlerBase<DateIsCopiedRequest>
{
private readonly ITrackingActionRepository _trackingActionRepository;
private readonly ISynchronizationStatusCheckerService _synchronizationStatusCheckerService;
private readonly ISynchronizationProgressService _synchronizationProgressService;
private readonly ISynchronizationService _synchronizationService;
private readonly ILogger<DateIsCopiedCommandHandler> _logger;
protected override string EmptyIdsLog => "DateIsCopied: no action group IDs were provided for the operation";
protected override string DoneLogTemplate => "Date is copied for session {SessionId} with {ActionCount} actions";

public DateIsCopiedCommandHandler(
ITrackingActionRepository trackingActionRepository,
ISynchronizationStatusCheckerService synchronizationStatusCheckerService,
ISynchronizationProgressService synchronizationProgressService,
ISynchronizationService synchronizationService,
ILogger<DateIsCopiedCommandHandler> logger)
: base(trackingActionRepository, synchronizationStatusCheckerService, synchronizationProgressService, synchronizationService, logger)
{
_trackingActionRepository = trackingActionRepository;
_synchronizationStatusCheckerService = synchronizationStatusCheckerService;
_synchronizationProgressService = synchronizationProgressService;
_synchronizationService = synchronizationService;
_logger = logger;
}

public async Task Handle(DateIsCopiedRequest request, CancellationToken cancellationToken)
{
if (request.ActionsGroupIds.Count == 0)
{
_logger.LogInformation("DateIsCopied: no action group IDs were provided for the operation");
return;
}

bool needSendSynchronizationUpdated = false;

var result = await _trackingActionRepository.AddOrUpdate(request.SessionId, request.ActionsGroupIds, (trackingAction, synchronization) =>
{
if (!_synchronizationStatusCheckerService.CheckSynchronizationCanBeUpdated(synchronization))
{
return false;
}

bool wasTrackingActionFinished = trackingAction.IsFinished;

trackingAction.AddSuccessOnTarget(request.Client.ClientInstanceId);

if (!wasTrackingActionFinished && trackingAction.IsFinished)
{
synchronization.Progress.FinishedActionsCount += 1;
}

needSendSynchronizationUpdated = _synchronizationService.CheckSynchronizationIsFinished(synchronization);

return true;
});

if (result.IsSuccess)
{
await _synchronizationProgressService.UpdateSynchronizationProgress(result, needSendSynchronizationUpdated);
}

_logger.LogInformation("Date is copied for session {SessionId} with {ActionCount} actions",
request.SessionId, request.ActionsGroupIds.Count);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using ByteSync.ServerCommon.Business.Auth;
using MediatR;

namespace ByteSync.ServerCommon.Commands.Synchronizations;

public class DateIsCopiedRequest : IRequest
public class DateIsCopiedRequest : IActionCompletedRequest
{
public DateIsCopiedRequest(string sessionId, Client client, List<string> actionsGroupIds)
{
Expand Down
Loading
Loading