Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0385a35
feat: improve redis lock management
paul-fresquet Apr 8, 2025
dab3623
feat: improve error management on YouJoinedSession
paul-fresquet Apr 9, 2025
15b295b
refactor: introduce EntityType & ICacheKeyFactory in Repositories System
paul-fresquet Apr 9, 2025
306e1be
refactor: cleanup
paul-fresquet Apr 9, 2025
8f2e56a
refactor: cleanup
paul-fresquet Apr 9, 2025
97737b6
refactor: cleanup
paul-fresquet Apr 9, 2025
291dee8
refactor: refactor BaseRepository / CacheRepository / RedisInfrastruc…
paul-fresquet Apr 10, 2025
ae9cd9a
refactor: cleanup
paul-fresquet Apr 10, 2025
8495595
tests: add unit tests
paul-fresquet Apr 10, 2025
a39cd2d
feat: fix AddCloudSession
paul-fresquet Apr 10, 2025
835d63d
test: add integration tests - ClientsRepositoryTests
paul-fresquet Apr 10, 2025
0efa4fd
tests: add integration tests - InventoryRepositoryTests
paul-fresquet Apr 10, 2025
2ac079b
test: add integration tests - SynchronizationRepositoryTests.cs
paul-fresquet Apr 10, 2025
33404ab
refactor: improve tests
paul-fresquet Apr 10, 2025
e7ab34d
test: improve tests
paul-fresquet Apr 10, 2025
93d4852
test: add integration tests - TrackingActionRepositoryTests
paul-fresquet Apr 10, 2025
6bc81c7
test: improve tests
paul-fresquet Apr 11, 2025
91aeaef
test: improve unit tests
paul-fresquet Apr 11, 2025
327fa3b
fix: various fixes
paul-fresquet Apr 11, 2025
1bc369e
feat: remove useless acquireLock
paul-fresquet Apr 11, 2025
3813ec3
Merge branch 'master' into feature/improve-redis-lock-management
paul-fresquet Apr 11, 2025
f34c728
refactor: refactor IRepository & TrackingActionRepository
paul-fresquet Apr 11, 2025
0d5d37f
refactor: improve IRepository
paul-fresquet Apr 11, 2025
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
@@ -1,10 +1,8 @@
using System.Threading.Tasks;
using ByteSync.Common.Business.Sessions.Cloud.Connections;
using ByteSync.Common.Business.Sessions.Cloud.Connections;
using ByteSync.Common.Business.Trust.Connections;
using ByteSync.Interfaces.Controls.Applications;
using ByteSync.Interfaces.Controls.Communications;
using ByteSync.Interfaces.Controls.Communications.Http;
using Serilog;

namespace ByteSync.Services.Communications;

Expand All @@ -15,28 +13,27 @@ public class DigitalSignaturesChecker : IDigitalSignaturesChecker
private readonly IDigitalSignaturesRepository _digitalSignaturesRepository;
private readonly ITrustApiClient _trustApiClient;
private readonly IDigitalSignatureComputer _digitalSignatureComputer;
private readonly ILogger<DigitalSignaturesChecker> _logger;

public DigitalSignaturesChecker(IEnvironmentService environmentService,
IPublicKeysManager publicKeysManager, IDigitalSignaturesRepository digitalSignaturesRepository,
ITrustApiClient trustApiClient, IDigitalSignatureComputer digitalSignatureComputer)
public DigitalSignaturesChecker(IEnvironmentService environmentService, IPublicKeysManager publicKeysManager,
IDigitalSignaturesRepository digitalSignaturesRepository, ITrustApiClient trustApiClient, IDigitalSignatureComputer digitalSignatureComputer,
ILogger<DigitalSignaturesChecker> logger)
{
_environmentService = environmentService;
_publicKeysManager = publicKeysManager;
_digitalSignaturesRepository = digitalSignaturesRepository;
_trustApiClient = trustApiClient;
_digitalSignatureComputer = digitalSignatureComputer;
_logger = logger;
}

public async Task<bool> CheckExistingMembersDigitalSignatures(string dataId, ICollection<string> clientInstanceIds)
{
// Tout le monde est trusté, on fait un Check Auth
var signatureCheckInfos = new List<DigitalSignatureCheckInfo>();

// On enlève, au cas où, le clientInstanceId du client actuel

clientInstanceIds.Remove(_environmentService.ClientInstanceId);
foreach (var memberInstanceId in clientInstanceIds)
{
// On calcule la signature d'authentification
var digitalSignatureCheckInfo = _digitalSignatureComputer
.BuildDigitalSignatureCheckInfo(dataId, memberInstanceId, true);

Expand Down Expand Up @@ -75,7 +72,7 @@ public async Task CheckDigitalSignature(DigitalSignatureCheckInfo digitalSignatu

if (isDataOK)
{
Log.Information("Digital Signature successfully checked for Client {ClientInstanceId} with Public Key {@PublicKeyInfo}",
_logger.LogInformation("Digital Signature successfully checked for Client {ClientInstanceId} with Public Key {@PublicKeyInfo}",
digitalSignatureCheckInfo.Issuer, otherPartyPublicKeyInfo);

await _digitalSignaturesRepository.SetDigitalSignatureChecked(digitalSignatureCheckInfo.DataId, digitalSignatureCheckInfo.Issuer);
Expand Down Expand Up @@ -108,17 +105,7 @@ public async Task CheckDigitalSignature(DigitalSignatureCheckInfo digitalSignatu
}
else
{
Log.Warning("Digital Signature check failed for Client {ClientInstanceId}", digitalSignatureCheckInfo.Issuer);
_logger.LogWarning("Digital Signature check failed for Client {ClientInstanceId}", digitalSignatureCheckInfo.Issuer);
}
}

// private void LogUnknownSessionReceived(string? sessionId, [CallerMemberName] string caller = "")
// {
// if (caller.IsNullOrEmpty())
// {
// caller = "UnknownCaller";
// }
//
// Log.Error("DigitalSignaturesChecker.{caller}: unknown sessionId received ({sessionId})", caller, sessionId);
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
using ByteSync.Interfaces.Controls.Communications.Http;
using ByteSync.Interfaces.Controls.Encryptions;
using ByteSync.Interfaces.Repositories;
using ByteSync.Interfaces.Services.Sessions;
using ByteSync.Interfaces.Services.Sessions.Connecting;
using ByteSync.Interfaces.Services.Sessions.Connecting.Joining;
using Serilog;

namespace ByteSync.Services.Sessions.Connecting;
namespace ByteSync.Services.Sessions.Connecting.Joining;

public class YouJoinedSessionService : IYouJoinedSessionService
{
Expand All @@ -23,17 +21,17 @@ public class YouJoinedSessionService : IYouJoinedSessionService
private readonly IDataEncrypter _dataEncrypter;
private readonly ICloudSessionApiClient _cloudSessionApiClient;
private readonly IPublicKeysManager _publicKeysManager;
private readonly ISessionService _sessionService;
private readonly IAfterJoinSessionService _afterJoinSessionService;
private readonly ICloudSessionConnectionService _cloudSessionConnectionService;
private readonly ILogger<YouJoinedSessionService> _logger;

private const string UNKNOWN_RECEIVED_SESSION_ID = "unknown received sessionId {sessionId}";
private const string PUBLIC_KEY_IS_NOT_TRUSTED = "Public key is not trusted";

public YouJoinedSessionService(ICloudSessionConnectionRepository cloudSessionConnectionRepository,
IEnvironmentService environmentService, IPublicKeysTruster publicKeysTruster, IDigitalSignaturesChecker digitalSignaturesChecker,
IDataEncrypter dataEncrypter, ICloudSessionApiClient cloudSessionApiClient, IPublicKeysManager publicKeysManager, ISessionService sessionService,
IAfterJoinSessionService afterJoinSessionService, ILogger<YouJoinedSessionService> logger)
IDataEncrypter dataEncrypter, ICloudSessionApiClient cloudSessionApiClient, IPublicKeysManager publicKeysManager,
IAfterJoinSessionService afterJoinSessionService, ICloudSessionConnectionService cloudSessionConnectionService, ILogger<YouJoinedSessionService> logger)
{
_cloudSessionConnectionRepository = cloudSessionConnectionRepository;
_environmentService = environmentService;
Expand All @@ -42,8 +40,8 @@ public YouJoinedSessionService(ICloudSessionConnectionRepository cloudSessionCon
_dataEncrypter = dataEncrypter;
_cloudSessionApiClient = cloudSessionApiClient;
_publicKeysManager = publicKeysManager;
_sessionService = sessionService;
_afterJoinSessionService = afterJoinSessionService;
_cloudSessionConnectionService = cloudSessionConnectionService;
_logger = logger;
}

Expand Down Expand Up @@ -138,24 +136,26 @@ public async Task Process(CloudSessionResult cloudSessionResult, ValidateJoinClo
var lobbySessionDetails = await _cloudSessionConnectionRepository
.GetTempLobbySessionDetails(cloudSessionResult.CloudSession.SessionId);

await _afterJoinSessionService.Process(
new AfterJoinSessionRequest(cloudSessionResult, lobbySessionDetails, false));

var afterJoinSessionRequest = new AfterJoinSessionRequest(cloudSessionResult, lobbySessionDetails, false);
await _afterJoinSessionService.Process(afterJoinSessionRequest);

await _cloudSessionConnectionRepository.SetJoinSessionResultReceived(cloudSessionResult.CloudSession.SessionId);

_cloudSessionConnectionRepository.SetConnectionStatus(SessionConnectionStatus.InSession);

// ReSharper disable once PossibleNullReferenceException
Log.Information("JoinSession: {CloudSession}", cloudSessionResult.SessionId);

_logger.LogInformation("JoinSession: {CloudSession}", cloudSessionResult.SessionId);
}
catch (Exception ex)
{
Log.Error(ex, "OnYouJoinedSession");
_logger.LogError(ex, "OnYouJoinedSession");

_sessionService.ClearCloudSession();
var joinSessionError = new JoinSessionError
{
Exception = ex,
Status = JoinSessionStatus.UnexpectedError
};

_cloudSessionConnectionRepository.SetConnectionStatus(SessionConnectionStatus.NoSession);
await _cloudSessionConnectionService.OnJoinSessionError(joinSessionError);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ private static void RegisterServerCommonAssembly(ContainerBuilder builder)
.Where(t => t.Name.EndsWith("Repository"))
.InstancePerLifetimeScope()
.AsImplementedInterfaces();

var genericRepositoryTypes = executingAssembly.GetTypes()
.Where(t => t.Name.Contains("Repository`") && t.IsGenericTypeDefinition && !t.IsInterface);

foreach (var genericType in genericRepositoryTypes)
{
builder.RegisterGeneric(genericType)
.AsImplementedInterfaces()
.AsSelf()
.InstancePerLifetimeScope();
}

builder.RegisterAssemblyTypes(executingAssembly)
.Where(t => t.Name.EndsWith("Service"))
Expand Down
12 changes: 12 additions & 0 deletions src/ByteSync.ServerCommon/Business/Repositories/CacheKey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using ByteSync.ServerCommon.Entities;

namespace ByteSync.ServerCommon.Business.Repositories;

public class CacheKey
{
public required EntityType EntityType { get; init; }

public required string EntityId { get; init; }

public required string Value { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ public class CreateSessionCommandHandler : IRequestHandler<CreateSessionRequest,
private readonly ICloudSessionsRepository _cloudSessionsRepository;
private readonly IClientsGroupsService _clientsGroupsService;
private readonly ICloudSessionsService _cloudSessionsService;
private readonly ICacheService _cacheService;
private readonly IRedisInfrastructureService _redisInfrastructureService;
private readonly ILogger<CreateSessionCommandHandler> _logger;

public CreateSessionCommandHandler(ICloudSessionsRepository cloudSessionsRepository, IClientsGroupsService clientsGroupsService,
IClientsRepository clientsRepository, ICloudSessionsService cloudSessionsService, ICacheService cacheService,
IClientsRepository clientsRepository, ICloudSessionsService cloudSessionsService, IRedisInfrastructureService redisInfrastructureService,
ILogger<CreateSessionCommandHandler> logger)
{
_cloudSessionsRepository = cloudSessionsRepository;
_clientsGroupsService = clientsGroupsService;
_cloudSessionsService = cloudSessionsService;
_cacheService = cacheService;
_redisInfrastructureService = redisInfrastructureService;
_logger = logger;
}

Expand All @@ -33,7 +33,7 @@ public async Task<CloudSessionResult> Handle(CreateSessionRequest request, Cance
var createCloudSessionParameters = request.CreateCloudSessionParameters;
var client = request.Client;

var transaction = _cacheService.OpenTransaction();
var transaction = _redisInfrastructureService.OpenTransaction();

CloudSessionData cloudSessionData;
SessionMemberData creatorData;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ByteSync.Common.Business.Sessions.Cloud.Connections;
using ByteSync.Common.Helpers;
using ByteSync.ServerCommon.Business.Sessions;
using ByteSync.ServerCommon.Entities;
using ByteSync.ServerCommon.Helpers;
using ByteSync.ServerCommon.Interfaces.Mappers;
using ByteSync.ServerCommon.Interfaces.Repositories;
Expand All @@ -17,18 +18,18 @@ public class FinalizeJoinCloudSessionCommandHandler : IRequestHandler<FinalizeJo
private readonly ISessionMemberMapper _sessionMemberMapper;
private readonly IInvokeClientsService _invokeClientsService;
private readonly IClientsGroupsService _clientsGroupsService;
private readonly ICacheService _cacheService;
private readonly IRedisInfrastructureService _redisInfrastructureService;
private readonly ILogger<FinalizeJoinCloudSessionCommandHandler> _logger;

public FinalizeJoinCloudSessionCommandHandler(ICloudSessionsRepository cloudSessionsRepository, ISessionMemberMapper sessionMemberMapper,
IInvokeClientsService invokeClientsService, IClientsGroupsService clientsGroupsService,
ICacheService cacheService, ILogger<FinalizeJoinCloudSessionCommandHandler> logger)
IRedisInfrastructureService redisInfrastructureService, ILogger<FinalizeJoinCloudSessionCommandHandler> logger)
{
_cloudSessionsRepository = cloudSessionsRepository;
_invokeClientsService = invokeClientsService;
_clientsGroupsService = clientsGroupsService;
_sessionMemberMapper = sessionMemberMapper;
_cacheService = cacheService;
_redisInfrastructureService = redisInfrastructureService;
_logger = logger;
}

Expand All @@ -40,8 +41,8 @@ public async Task<FinalizeJoinSessionResult> Handle(FinalizeJoinCloudSessionRequ
FinalizeJoinSessionStatuses? finalizeJoinSessionStatus = null;
SessionMemberData? joiner = null;

var transaction = _cacheService.OpenTransaction();

var transaction = _redisInfrastructureService.OpenTransaction();
var updateResult = await _cloudSessionsRepository.Update(parameters.SessionId, innerCloudSessionData =>
{
if (innerCloudSessionData.IsSessionRemoved)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ public class QuitSessionCommandHandler : IRequestHandler<QuitSessionRequest>
private readonly ICloudSessionsRepository _cloudSessionsRepository;
private readonly IInventoryRepository _inventoryRepository;
private readonly ISynchronizationRepository _synchronizationRepository;
private readonly ICacheService _cacheService;
private readonly IRedisInfrastructureService _redisInfrastructureService;
private readonly ISessionMemberMapper _sessionMemberMapper;
private readonly IClientsGroupsService _clientsGroupsService;
private readonly IInvokeClientsService _invokeClientsService;

public QuitSessionCommandHandler(ICloudSessionsRepository cloudSessionsRepository, IInventoryRepository inventoryRepository,
ISynchronizationRepository synchronizationRepository, ICacheService cacheService, ISessionMemberMapper sessionMemberMapper,
ISynchronizationRepository synchronizationRepository, IRedisInfrastructureService redisInfrastructureService, ISessionMemberMapper sessionMemberMapper,
IClientsGroupsService clientsGroupsService, IInvokeClientsService invokeClientsService)
{
_cloudSessionsRepository = cloudSessionsRepository;
_inventoryRepository = inventoryRepository;
_synchronizationRepository = synchronizationRepository;
_cacheService = cacheService;
_redisInfrastructureService = redisInfrastructureService;
_sessionMemberMapper = sessionMemberMapper;
_clientsGroupsService = clientsGroupsService;
_invokeClientsService = invokeClientsService;
Expand All @@ -37,7 +37,7 @@ public async Task Handle(QuitSessionRequest request, CancellationToken cancellat
CloudSessionData? innerCloudSessionData = null;
SessionMemberData? innerQuitter = null;

var transaction = _cacheService.OpenTransaction();
var transaction = _redisInfrastructureService.OpenTransaction();

var updateSessionResult = await _cloudSessionsRepository.Update(request.SessionId, cloudSessionData =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class UpdateSessionSettingsCommandHandler : IRequestHandler<UpdateSession


public UpdateSessionSettingsCommandHandler(ICloudSessionsRepository cloudSessionsRepository, IInventoryRepository inventoryRepository,
ISynchronizationRepository synchronizationRepository, ICacheService cacheService, ISessionMemberMapper sessionMemberMapper,
ISynchronizationRepository synchronizationRepository, IRedisInfrastructureService redisInfrastructureService, ISessionMemberMapper sessionMemberMapper,
IInvokeClientsService invokeClientsService, ILogger<UpdateSessionSettingsCommandHandler> logger)
{
_cloudSessionsRepository = cloudSessionsRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using ByteSync.Common.Business.Sessions;
using ByteSync.ServerCommon.Business.Repositories;
using ByteSync.ServerCommon.Business.Sessions;
using ByteSync.ServerCommon.Entities;
using ByteSync.ServerCommon.Interfaces.Repositories;
using ByteSync.ServerCommon.Interfaces.Services;
using ByteSync.ServerCommon.Interfaces.Services.Clients;
Expand All @@ -18,22 +19,22 @@ public class StartInventoryCommandHandler : IRequestHandler<StartInventoryReques
private readonly ICloudSessionsRepository _cloudSessionsRepository;
private readonly ISharedFilesService _sharedFilesService;
private readonly IInvokeClientsService _invokeClientsService;
private readonly ICacheService _cacheService;
private readonly IRedisInfrastructureService _redisInfrastructureService;
private readonly ILogger<StartInventoryCommandHandler> _logger;

public StartInventoryCommandHandler(
IInventoryRepository inventoryRepository,
ICloudSessionsRepository cloudSessionsRepository,
ISharedFilesService sharedFilesService,
IInvokeClientsService invokeClientsService,
ICacheService cacheService,
IRedisInfrastructureService redisInfrastructureService,
ILogger<StartInventoryCommandHandler> logger)
{
_inventoryRepository = inventoryRepository;
_cloudSessionsRepository = cloudSessionsRepository;
_sharedFilesService = sharedFilesService;
_invokeClientsService = invokeClientsService;
_cacheService = cacheService;
_redisInfrastructureService = redisInfrastructureService;
_logger = logger;
}

Expand All @@ -42,13 +43,11 @@ public async Task<StartInventoryResult> Handle(StartInventoryRequest request, Ca
var sessionId = request.SessionId;
var client = request.Client;

await using var sessionRedisLock = await _cacheService.AcquireLockAsync(_cloudSessionsRepository.ComputeCacheKey(_cloudSessionsRepository.ElementName,
sessionId));
await using var sessionRedisLock = await _redisInfrastructureService.AcquireLockAsync(EntityType.Session, sessionId);

await using var inventoryRedisLock = await _cacheService.AcquireLockAsync(_inventoryRepository.ComputeCacheKey(_inventoryRepository.ElementName,
sessionId));
await using var inventoryRedisLock = await _redisInfrastructureService.AcquireLockAsync(EntityType.Inventory, sessionId);

var transaction = _cacheService.OpenTransaction();
var transaction = _redisInfrastructureService.OpenTransaction();

UpdateEntityResult<InventoryData>? inventoryUpdateResult = null;

Expand Down
Loading