diff --git a/.github/workflows/blauhaus.yml b/.github/workflows/blauhaus.yml
index 9830a67..af4201e 100644
--- a/.github/workflows/blauhaus.yml
+++ b/.github/workflows/blauhaus.yml
@@ -30,6 +30,7 @@ jobs:
dotnet pack ./src/Blauhaus.Sync.TestHelpers.Orleans/Blauhaus.Sync.TestHelpers.Orleans.csproj -p:PackageVersion=${VERSION_NAME} --no-build --output ./ --configuration Release
dotnet pack ./src/Blauhaus.Sync.TestHelpers.EfCore/Blauhaus.Sync.TestHelpers.EfCore.csproj -p:PackageVersion=${VERSION_NAME} --no-build --output ./ --configuration Release
dotnet pack ./src/Blauhaus.Sync.TestHelpers.Sqlite/Blauhaus.Sync.TestHelpers.Sqlite.csproj -p:PackageVersion=${VERSION_NAME} --no-build --output ./ --configuration Release
+ dotnet pack ./src/Blauhaus.Sync.Server.Orleans/Blauhaus.Sync.Server.Orleans.csproj -p:PackageVersion=${VERSION_NAME} --no-build --output ./ --configuration Release
- name: Deploy NuGet Package
run: |
dotnet nuget push /home/runner/work/Blauhaus.Sync/Blauhaus.Sync/Blauhaus.Sync.Abstractions.${VERSION_NAME}.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
@@ -38,6 +39,7 @@ jobs:
dotnet nuget push /home/runner/work/Blauhaus.Sync/Blauhaus.Sync/Blauhaus.Sync.TestHelpers.${VERSION_NAME}.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
dotnet nuget push /home/runner/work/Blauhaus.Sync/Blauhaus.Sync/Blauhaus.Sync.Client.SignalR.${VERSION_NAME}.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
dotnet nuget push /home/runner/work/Blauhaus.Sync/Blauhaus.Sync/Blauhaus.Sync.Server.EfCore.${VERSION_NAME}.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
+ dotnet nuget push /home/runner/work/Blauhaus.Sync/Blauhaus.Sync/Blauhaus.Sync.Server.Orleans.${VERSION_NAME}.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
dotnet nuget push /home/runner/work/Blauhaus.Sync/Blauhaus.Sync/Blauhaus.Sync.TestHelpers.Orleans.${VERSION_NAME}.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
dotnet nuget push /home/runner/work/Blauhaus.Sync/Blauhaus.Sync/Blauhaus.Sync.TestHelpers.EfCore.${VERSION_NAME}.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
dotnet nuget push /home/runner/work/Blauhaus.Sync/Blauhaus.Sync/Blauhaus.Sync.TestHelpers.Sqlite.${VERSION_NAME}.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json
diff --git a/src/Blauhaus.Sync.Abstractions/Blauhaus.Sync.Abstractions.csproj b/src/Blauhaus.Sync.Abstractions/Blauhaus.Sync.Abstractions.csproj
index 40d8fde..2b2e764 100644
--- a/src/Blauhaus.Sync.Abstractions/Blauhaus.Sync.Abstractions.csproj
+++ b/src/Blauhaus.Sync.Abstractions/Blauhaus.Sync.Abstractions.csproj
@@ -1,15 +1,15 @@
- netstandard2.0;net6.0
+ netstandard2.0
9
enable
-
-
-
+
+
+
diff --git a/src/Blauhaus.Sync.Client.SignalR/Blauhaus.Sync.Client.SignalR.csproj b/src/Blauhaus.Sync.Client.SignalR/Blauhaus.Sync.Client.SignalR.csproj
index 8545377..5f16300 100644
--- a/src/Blauhaus.Sync.Client.SignalR/Blauhaus.Sync.Client.SignalR.csproj
+++ b/src/Blauhaus.Sync.Client.SignalR/Blauhaus.Sync.Client.SignalR.csproj
@@ -1,7 +1,7 @@
- netstandard2.0;net6.0
+ netstandard2.0
9
enable
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Blauhaus.Sync.Client.Sqlite/Blauhaus.Sync.Client.Sqlite.csproj b/src/Blauhaus.Sync.Client.Sqlite/Blauhaus.Sync.Client.Sqlite.csproj
index e159429..badcab5 100644
--- a/src/Blauhaus.Sync.Client.Sqlite/Blauhaus.Sync.Client.Sqlite.csproj
+++ b/src/Blauhaus.Sync.Client.Sqlite/Blauhaus.Sync.Client.Sqlite.csproj
@@ -1,7 +1,7 @@
- netstandard2.0;net6.0
+ netstandard2.0
9
enable
@@ -16,9 +16,9 @@
-
-
-
+
+
+
diff --git a/src/Blauhaus.Sync.Client/Blauhaus.Sync.Client.csproj b/src/Blauhaus.Sync.Client/Blauhaus.Sync.Client.csproj
index 319117d..c2692c4 100644
--- a/src/Blauhaus.Sync.Client/Blauhaus.Sync.Client.csproj
+++ b/src/Blauhaus.Sync.Client/Blauhaus.Sync.Client.csproj
@@ -1,7 +1,7 @@
- netstandard2.0;net6.0
+ netstandard2.0
9
enable
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Blauhaus.Sync.Server.EfCore/Blauhaus.Sync.Server.EfCore.csproj b/src/Blauhaus.Sync.Server.EfCore/Blauhaus.Sync.Server.EfCore.csproj
index 7dcbbc6..5bd2dd4 100644
--- a/src/Blauhaus.Sync.Server.EfCore/Blauhaus.Sync.Server.EfCore.csproj
+++ b/src/Blauhaus.Sync.Server.EfCore/Blauhaus.Sync.Server.EfCore.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Blauhaus.Sync.Server.Orleans/Abstractions/IDtoSyncGrain.cs b/src/Blauhaus.Sync.Server.Orleans/Abstractions/IDtoSyncGrain.cs
new file mode 100644
index 0000000..2ec1f58
--- /dev/null
+++ b/src/Blauhaus.Sync.Server.Orleans/Abstractions/IDtoSyncGrain.cs
@@ -0,0 +1,22 @@
+using Blauhaus.Domain.Abstractions.CommandHandlers;
+using Blauhaus.Orleans.Abstractions.Grains;
+using Blauhaus.Orleans.Abstractions.Handlers;
+using Blauhaus.SignalR.Abstractions.Auth;
+using System;
+using System.Threading.Tasks;
+using Blauhaus.Domain.Abstractions.Entities;
+using Blauhaus.Sync.Abstractions.Common;
+using Orleans.Concurrency;
+
+namespace Blauhaus.Sync.Server.Orleans.Abstractions
+{
+ public interface IDtoSyncGrain : IGrainSingleton, IConnectedUserHandler,
+ IAuthenticatedCommandHandler, DtoSyncCommand, IConnectedUser>
+ where TDto : IClientEntity
+ {
+ Task SetBatchSizeAsync(int batchSize);
+
+ [OneWay]
+ Task UpdateDtoAsync(TDto dto);
+ }
+}
\ No newline at end of file
diff --git a/src/Blauhaus.Sync.Server.Orleans/Blauhaus.Sync.Server.Orleans.csproj b/src/Blauhaus.Sync.Server.Orleans/Blauhaus.Sync.Server.Orleans.csproj
index d13c766..1cfdf15 100644
--- a/src/Blauhaus.Sync.Server.Orleans/Blauhaus.Sync.Server.Orleans.csproj
+++ b/src/Blauhaus.Sync.Server.Orleans/Blauhaus.Sync.Server.Orleans.csproj
@@ -1,15 +1,16 @@
-
+
net5.0
-
+
+
-
+
diff --git a/src/Blauhaus.Sync.Server.Orleans/Grains/BaseDtoSyncGrain.cs b/src/Blauhaus.Sync.Server.Orleans/Grains/BaseDtoSyncGrain.cs
new file mode 100644
index 0000000..237f148
--- /dev/null
+++ b/src/Blauhaus.Sync.Server.Orleans/Grains/BaseDtoSyncGrain.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using Blauhaus.Analytics.Abstractions.Service;
+using Blauhaus.Domain.Abstractions.DtoHandlers;
+using Blauhaus.Domain.Abstractions.Entities;
+using Blauhaus.Domain.Server.EFCore.Extensions;
+using Blauhaus.Domain.Server.Entities;
+using Blauhaus.Orleans.Abstractions.Resolver;
+using Blauhaus.Orleans.EfCore.Grains;
+using Blauhaus.Responses;
+using Blauhaus.SignalR.Abstractions.Auth;
+using Blauhaus.Sync.Abstractions.Common;
+using Blauhaus.Sync.Server.Orleans.Abstractions;
+using Blauhaus.Time.Abstractions;
+using Microsoft.EntityFrameworkCore;
+using EntityState = Blauhaus.Domain.Abstractions.Entities.EntityState;
+
+namespace Blauhaus.Sync.Server.Orleans.Grains
+{
+ public abstract class BaseDtoSyncGrain : BaseDbGrain, IDtoSyncGrain
+ where TDbContext : DbContext
+ where TDto : IClientEntity
+ where TGrainResolver : IGrainResolver
+ where TEntity : BaseServerEntity, IDtoOwner
+ {
+
+ protected readonly Dictionary UserConnections = new();
+ protected int BatchSize = 50;
+ protected Dictionary AllDtos = new();
+
+ protected BaseDtoSyncGrain(
+ Func dbContextFactory,
+ IAnalyticsService analyticsService,
+ ITimeService timeService,
+ TGrainResolver grainResolver)
+ : base(dbContextFactory, analyticsService, timeService, grainResolver)
+ {
+ }
+
+ public Task SetBatchSizeAsync(int batchSize)
+ {
+ BatchSize = batchSize;
+ return Task.CompletedTask;
+ }
+
+ public override async Task OnActivateAsync()
+ {
+ using var db = GetDbContext();
+
+ var query = Include(db.Set().AsQueryable());
+ query = await ModifySyncQueryAsync(query);
+ var allEntities = await query.ToArrayAsync();
+
+ foreach (var entity in allEntities)
+ {
+ AllDtos[entity.Id] =await entity.GetDtoAsync();
+ }
+ }
+
+ public Task>> HandleAsync(DtoSyncCommand command, IConnectedUser user)
+ {
+ var modifiedAfter = command.ModifiedAfterTicks;
+
+ Func filter;
+
+ if (command.IsFirstSync)
+ {
+ if (command.ModifiedAfterTicks > 0)
+ {
+ filter = dto =>
+ dto.ModifiedAtTicks > modifiedAfter &&
+ dto.EntityState == EntityState.Active;
+ }
+ else
+ {
+ filter = dto =>
+ dto.EntityState == EntityState.Active;
+ }
+ }
+ else
+ {
+ filter = dto => dto.ModifiedAtTicks > modifiedAfter;
+ }
+
+ //there is a problem when 2 entities have exactly the same modified and the first is the last one in a batch
+ //the next batch will ask for modified after the previous one so entity 2 is exclude. Unlikely to happen but could be nasty
+ //possible solutions - add any entities with exactly the same modified as the last one in the set?
+
+ var totalCount = AllDtos.Values
+ .Count(filter);
+
+ var dtoBatch = AllDtos.Values
+ .OrderBy(x => x.ModifiedAtTicks)
+ .Where(filter)
+ .Take(BatchSize).ToArray();
+
+ return Response.SuccessTask(totalCount == 0
+ ? DtoBatch.Empty()
+ : DtoBatch.Create(dtoBatch, Math.Max(0, totalCount - dtoBatch.Length)));
+ }
+
+ protected virtual IQueryable Include(IQueryable query)
+ {
+ return query;
+ }
+
+ protected virtual Task> ModifySyncQueryAsync(IQueryable query)
+ {
+ return Task.FromResult(query);
+ }
+
+
+ public Task UpdateDtoAsync(TDto dto)
+ {
+ //todo update connected users
+ AllDtos[dto.Id] = dto;
+ return Task.CompletedTask;
+ }
+
+
+
+ public async Task ConnectUserAsync(IConnectedUser user)
+ {
+ if (!UserConnections.TryGetValue(user.UniqueId, out _))
+ {
+ UserConnections[user.UniqueId] = user;
+ await HandleConnectedUserAsync(user);
+ }
+ }
+
+ public async Task DisconnectUserAsync(IConnectedUser user)
+ {
+ if (UserConnections.TryGetValue(user.UniqueId, out _))
+ {
+ UserConnections.Remove(user.UniqueId);
+ await HandleDisconnectedUserAsync(user);
+ }
+ }
+
+
+ protected virtual Task HandleConnectedUserAsync(IConnectedUser user)
+ {
+ return Task.CompletedTask;
+ }
+
+ protected virtual Task HandleDisconnectedUserAsync(IConnectedUser user)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Blauhaus.Sync.TestHelpers.EfCore/Blauhaus.Sync.TestHelpers.EfCore.csproj b/src/Blauhaus.Sync.TestHelpers.EfCore/Blauhaus.Sync.TestHelpers.EfCore.csproj
index 2eebfd6..13c7ac6 100644
--- a/src/Blauhaus.Sync.TestHelpers.EfCore/Blauhaus.Sync.TestHelpers.EfCore.csproj
+++ b/src/Blauhaus.Sync.TestHelpers.EfCore/Blauhaus.Sync.TestHelpers.EfCore.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Blauhaus.Sync.TestHelpers.Orleans/BaseGuidDtoSyncGrainTests.cs b/src/Blauhaus.Sync.TestHelpers.Orleans/BaseGuidDtoSyncGrainTests.cs
new file mode 100644
index 0000000..0159aa7
--- /dev/null
+++ b/src/Blauhaus.Sync.TestHelpers.Orleans/BaseGuidDtoSyncGrainTests.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Blauhaus.Domain.Abstractions.DtoHandlers;
+using Blauhaus.Domain.Abstractions.Entities;
+using Blauhaus.Domain.Server.Entities;
+using Blauhaus.Domain.TestHelpers.EntityBuilders;
+using Blauhaus.Orleans.Abstractions.Resolver;
+using Blauhaus.Orleans.TestHelpers.BaseTests;
+using Blauhaus.SignalR.Abstractions.Auth;
+using Blauhaus.Sync.Abstractions.Common;
+using Blauhaus.Sync.Server.Orleans.Grains;
+using Blauhaus.Sync.TestHelpers.EfCore;
+using Blauhaus.TestHelpers.Builders.Base;
+using Microsoft.EntityFrameworkCore;
+using NUnit.Framework;
+using EntityState = Blauhaus.Domain.Abstractions.Entities.EntityState;
+
+namespace Blauhaus.Sync.TestHelpers.Orleans
+{
+ public abstract class BaseGuidDtoSyncGrainTests : BaseDbGrainTest
+ where TDbContext : DbContext
+ where TSut : BaseDtoSyncGrain
+ where TGrainResolver : IGrainResolver
+ where TDto : IClientEntity
+ where TEntity : BaseServerEntity, IDtoOwner
+ where TEntityBuilder : BaseServerEntityBuilder
+ where TDtoBuilder : IBuilder, new()
+ {
+
+ protected EntitySyncSet EntitySet = null!;
+
+ public override void Setup()
+ {
+ base.Setup();
+
+ EntitySet = new EntitySyncSet(RunTime);
+ foreach (var baseServerEntityBuilder in EntitySet.Builders)
+ {
+ AddEntityBuilder(baseServerEntityBuilder);
+ }
+ }
+
+
+ [Test]
+ public async Task WHEN_IsFirstSync_SyncAllAsync_SHOULD_return_all_Active()
+ {
+ //Arrange
+ await Sut.SetBatchSizeAsync(1);
+
+ //Act
+ var result = await SyncAllAsync(0, User, Sut);
+
+ //Assert
+ Assert.That(result.Dtos.Count, Is.EqualTo(4));
+ Assert.That(result.DtoBatches.Count, Is.EqualTo(4));
+ Assert.That(result.Dtos.All(x => x.EntityState == EntityState.Active), Is.True);
+ Assert.That(result.Dtos[0].ModifiedAtTicks, Is.EqualTo(EntitySet.DistantPastTime.Ticks));
+ Assert.That(result.Dtos[1].ModifiedAtTicks, Is.EqualTo(EntitySet.PastTime.Ticks));
+ Assert.That(result.Dtos[2].ModifiedAtTicks, Is.EqualTo(EntitySet.PresentTime.Ticks));
+ Assert.That(result.Dtos[3].ModifiedAtTicks, Is.EqualTo(EntitySet.FutureTime.Ticks));
+ }
+
+ [Test]
+ public async Task WHEN_ModifiedAfter_is_given_SyncAllAsync_SHOULD_return_modified_including_Deleted()
+ {
+ //Arrange
+ await Sut.SetBatchSizeAsync(1);
+
+ //Act
+ var result = await SyncAllAsync(EntitySet.PastTime.Ticks, User, Sut);
+
+ //Assert
+ Assert.That(result.Dtos.Count, Is.EqualTo(3));
+ Assert.That(result.DtoBatches.Count, Is.EqualTo(3));
+ Assert.That(result.Dtos[0].ModifiedAtTicks, Is.EqualTo(EntitySet.PresentTime.Ticks));
+ Assert.That(result.Dtos[1].ModifiedAtTicks, Is.EqualTo(EntitySet.FutureTime.Ticks));
+ Assert.That(result.Dtos[2].ModifiedAtTicks, Is.EqualTo(EntitySet.FutureDeletedTime.Ticks));
+ }
+
+ [Test]
+ public async Task WHEN_there_are_no_modified_entities_SyncAllAsync_SHOULD_return_empty()
+ {
+ //Arrange
+ await Sut.SetBatchSizeAsync(1);
+
+ //Act
+ var result = await SyncAllAsync(EntitySet.FutureDeletedTime.Ticks, User, Sut);
+
+ //Assert
+ Assert.That(result.Dtos.Count, Is.EqualTo(0));
+ Assert.That(result.DtoBatches.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public async Task SyncAllAsync_SHOULD_apply_batch_size()
+ {
+ //Arrange
+ await Sut.SetBatchSizeAsync(2);
+
+ //Act
+ var result = await SyncAllAsync(0, User, Sut);
+
+ //Assert
+ Assert.That(result.Dtos.Count, Is.EqualTo(4));
+ Assert.That(result.DtoBatches.Count, Is.EqualTo(2));
+ Assert.That(result.Dtos.All(x => x.EntityState == EntityState.Active), Is.True);
+ Assert.That(result.Dtos[0].ModifiedAtTicks, Is.EqualTo(EntitySet.DistantPastTime.Ticks));
+ Assert.That(result.Dtos[1].ModifiedAtTicks, Is.EqualTo(EntitySet.PastTime.Ticks));
+ Assert.That(result.Dtos[2].ModifiedAtTicks, Is.EqualTo(EntitySet.PresentTime.Ticks));
+ Assert.That(result.Dtos[3].ModifiedAtTicks, Is.EqualTo(EntitySet.FutureTime.Ticks));
+ }
+
+ //todo
+ //there is a problem when 2 entities have exactly the same modified and the first is the last one in a batch
+ //the next batch will ask for modified after the previous one so entity 2 is exclude. Unlikely to happen but could be nasty
+ //possible solutions - add any entities with exactly the same modified as the last one in the set?
+ //vvv this test should passs when the problem is resolved vvv
+
+ //[Test]
+ //public async Task UpdateDtoAsync_SHOULD_add_dto_to_next_sync()
+ //{
+ // //Arrange
+ // await Sut.SetBatchSizeAsync(2);
+ // var dto = new TDtoBuilder()
+ // .With(x => x.Id, Guid.NewGuid())
+ // .With(x => x.EntityState, EntityState.Active)
+ // .With(x => x.ModifiedAtTicks, EntitySet.PastTime.Ticks).Object;
+
+ // //Act
+ // await Sut.UpdateDtoAsync(dto);
+ // var result = await SyncAllAsync(0, User, Sut);
+
+ // //Assert
+ // Assert.That(result.Dtos.Count, Is.EqualTo(5));
+ //}
+
+ [Test]
+ public async Task UpdateDtoAsync_SHOULD_add_dto_to_next_sync()
+ {
+ //Arrange
+ await Sut.SetBatchSizeAsync(2);
+ var dto = new TDtoBuilder()
+ .With(x => x.Id, Guid.NewGuid())
+ .With(x => x.EntityState, EntityState.Active)
+ .With(x => x.ModifiedAtTicks, EntitySet.PastTime.Ticks+1000).Object;
+
+ //Act
+ await Sut.UpdateDtoAsync(dto);
+ var result = await SyncAllAsync(0, User, Sut);
+
+ //Assert
+ Assert.That(result.Dtos.Count, Is.EqualTo(5));
+ }
+
+
+
+ protected async Task> SyncAllAsync(long lastModified, IConnectedUser user, TSut handler)
+ {
+ var results = new List>();
+
+ var syncCommand = DtoSyncCommand.Create(lastModified);
+ var syncResult = await handler.HandleAsync(syncCommand, user);
+ results.Add(syncResult.Value);
+
+ while (syncResult.Value.RemainingDtoCount > 0)
+ {
+ syncCommand = syncCommand.Update(syncResult.Value.BatchLastModifiedTicks);
+ syncResult = await handler.HandleAsync(syncCommand, user);
+ results.Add(syncResult.Value);
+ }
+
+ return new SyncTestResult(results);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Blauhaus.Sync.TestHelpers.Orleans/Blauhaus.Sync.TestHelpers.Orleans.csproj b/src/Blauhaus.Sync.TestHelpers.Orleans/Blauhaus.Sync.TestHelpers.Orleans.csproj
index 2003109..ff0695e 100644
--- a/src/Blauhaus.Sync.TestHelpers.Orleans/Blauhaus.Sync.TestHelpers.Orleans.csproj
+++ b/src/Blauhaus.Sync.TestHelpers.Orleans/Blauhaus.Sync.TestHelpers.Orleans.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Blauhaus.Sync.TestHelpers.Sqlite/Blauhaus.Sync.TestHelpers.Sqlite.csproj b/src/Blauhaus.Sync.TestHelpers.Sqlite/Blauhaus.Sync.TestHelpers.Sqlite.csproj
index 9588768..5ca888d 100644
--- a/src/Blauhaus.Sync.TestHelpers.Sqlite/Blauhaus.Sync.TestHelpers.Sqlite.csproj
+++ b/src/Blauhaus.Sync.TestHelpers.Sqlite/Blauhaus.Sync.TestHelpers.Sqlite.csproj
@@ -12,8 +12,8 @@
-
-
+
+
diff --git a/src/Blauhaus.Sync.TestHelpers/Blauhaus.Sync.TestHelpers.csproj b/src/Blauhaus.Sync.TestHelpers/Blauhaus.Sync.TestHelpers.csproj
index 1fa2ce3..eb21722 100644
--- a/src/Blauhaus.Sync.TestHelpers/Blauhaus.Sync.TestHelpers.csproj
+++ b/src/Blauhaus.Sync.TestHelpers/Blauhaus.Sync.TestHelpers.csproj
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/src/Blauhaus.Sync.Tests/TestObjects/MyDto.cs b/src/Blauhaus.Sync.Tests/.TestObjects/MyDto.cs
similarity index 100%
rename from src/Blauhaus.Sync.Tests/TestObjects/MyDto.cs
rename to src/Blauhaus.Sync.Tests/.TestObjects/MyDto.cs
diff --git a/src/Blauhaus.Sync.Tests/TestObjects/MyDtoBuilder.cs b/src/Blauhaus.Sync.Tests/.TestObjects/MyDtoBuilder.cs
similarity index 100%
rename from src/Blauhaus.Sync.Tests/TestObjects/MyDtoBuilder.cs
rename to src/Blauhaus.Sync.Tests/.TestObjects/MyDtoBuilder.cs
diff --git a/src/Blauhaus.Sync.Tests/TestObjects/User/MyUserDto.cs b/src/Blauhaus.Sync.Tests/.TestObjects/MyUserDto.cs
similarity index 100%
rename from src/Blauhaus.Sync.Tests/TestObjects/User/MyUserDto.cs
rename to src/Blauhaus.Sync.Tests/.TestObjects/MyUserDto.cs
diff --git a/src/Blauhaus.Sync.Tests/TestObjects/User/MyUserDtoBuilder.cs b/src/Blauhaus.Sync.Tests/.TestObjects/MyUserDtoBuilder.cs
similarity index 100%
rename from src/Blauhaus.Sync.Tests/TestObjects/User/MyUserDtoBuilder.cs
rename to src/Blauhaus.Sync.Tests/.TestObjects/MyUserDtoBuilder.cs
diff --git a/src/Blauhaus.Sync.Tests/Blauhaus.Sync.Tests.csproj b/src/Blauhaus.Sync.Tests/Blauhaus.Sync.Tests.csproj
index e6f774c..04e3828 100644
--- a/src/Blauhaus.Sync.Tests/Blauhaus.Sync.Tests.csproj
+++ b/src/Blauhaus.Sync.Tests/Blauhaus.Sync.Tests.csproj
@@ -2,13 +2,19 @@
net5.0
- 8
+ 9
enable
false
+
+
+
+
+
+
@@ -19,6 +25,8 @@
+
+
@@ -34,6 +42,8 @@
+
+
diff --git a/src/Blauhaus.Sync.Tests/Client/.Base/SqliteConfig.cs b/src/Blauhaus.Sync.Tests/Client/.Base/SqliteConfig.cs
index 9a4311f..dce5fb7 100644
--- a/src/Blauhaus.Sync.Tests/Client/.Base/SqliteConfig.cs
+++ b/src/Blauhaus.Sync.Tests/Client/.Base/SqliteConfig.cs
@@ -10,6 +10,7 @@
using System;
using System.Threading.Tasks;
using Blauhaus.Sync.TestHelpers.Sqlite;
+using Blauhaus.Sync.Tests.Client.TestObjects;
using Blauhaus.Sync.Tests.TestObjects;
using Blauhaus.Sync.Tests.TestObjects.User;
diff --git a/src/Blauhaus.Sync.Tests/TestObjects/MySyncedDtoEntity.cs b/src/Blauhaus.Sync.Tests/Client/.TestObjects/MySyncedDtoEntity.cs
similarity index 86%
rename from src/Blauhaus.Sync.Tests/TestObjects/MySyncedDtoEntity.cs
rename to src/Blauhaus.Sync.Tests/Client/.TestObjects/MySyncedDtoEntity.cs
index d88f9ba..0a43be4 100644
--- a/src/Blauhaus.Sync.Tests/TestObjects/MySyncedDtoEntity.cs
+++ b/src/Blauhaus.Sync.Tests/Client/.TestObjects/MySyncedDtoEntity.cs
@@ -1,12 +1,11 @@
using System;
-using Blauhaus.Domain.Abstractions.Entities;
using Blauhaus.Sync.Abstractions.Common;
-using Blauhaus.Sync.Client.Sqlite;
using Blauhaus.Sync.Client.Sqlite.Entities;
+using Blauhaus.Sync.Tests.TestObjects;
using Newtonsoft.Json;
using SQLite;
-namespace Blauhaus.Sync.Tests.TestObjects
+namespace Blauhaus.Sync.Tests.Client.TestObjects
{
public class MySyncedDtoEntity : BaseSyncClientEntity
{
diff --git a/src/Blauhaus.Sync.Tests/TestObjects/User/MySyncedUserDtoEntity.cs b/src/Blauhaus.Sync.Tests/Client/.TestObjects/MySyncedUserDtoEntity.cs
similarity index 100%
rename from src/Blauhaus.Sync.Tests/TestObjects/User/MySyncedUserDtoEntity.cs
rename to src/Blauhaus.Sync.Tests/Client/.TestObjects/MySyncedUserDtoEntity.cs
diff --git a/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/.Base/BaseSyncDtoCacheTest.cs b/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/.Base/BaseSyncDtoCacheTest.cs
index 3864a7e..1092f51 100644
--- a/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/.Base/BaseSyncDtoCacheTest.cs
+++ b/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/.Base/BaseSyncDtoCacheTest.cs
@@ -3,6 +3,7 @@
using Blauhaus.Sync.TestHelpers.Sqlite;
using Blauhaus.Sync.TestHelpers.Sqlite.Tests.BaseTests;
using Blauhaus.Sync.Tests.Client.Base;
+using Blauhaus.Sync.Tests.Client.TestObjects;
using Blauhaus.Sync.Tests.TestObjects;
using Blauhaus.TestHelpers.MockBuilders;
diff --git a/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/.Base/TestSyncDtoCache.cs b/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/.Base/TestSyncDtoCache.cs
index 5900ea2..7bcd1ff 100644
--- a/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/.Base/TestSyncDtoCache.cs
+++ b/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/.Base/TestSyncDtoCache.cs
@@ -5,6 +5,7 @@
using Blauhaus.Common.Abstractions;
using Blauhaus.Sync.Client.Sqlite;
using Blauhaus.Sync.Client.Sqlite.DtoCaches;
+using Blauhaus.Sync.Tests.Client.TestObjects;
using Blauhaus.Sync.Tests.TestObjects;
using SQLite;
diff --git a/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/SaveSyncedDtosAsyncTests.cs b/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/SaveSyncedDtosAsyncTests.cs
index 5f7bcf1..b2d08e1 100644
--- a/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/SaveSyncedDtosAsyncTests.cs
+++ b/src/Blauhaus.Sync.Tests/Client/SyncDtoCacheTests/SaveSyncedDtosAsyncTests.cs
@@ -4,6 +4,7 @@
using System.Threading.Tasks;
using Blauhaus.Sync.Abstractions.Common;
using Blauhaus.Sync.Tests.Client.SyncDtoCacheTests.Base;
+using Blauhaus.Sync.Tests.Client.TestObjects;
using Blauhaus.Sync.Tests.TestObjects;
using NUnit.Framework;
diff --git a/src/Blauhaus.Sync.Tests/Server/.TestObjects/MyDbContext.cs b/src/Blauhaus.Sync.Tests/Server/.TestObjects/MyDbContext.cs
new file mode 100644
index 0000000..4cb2343
--- /dev/null
+++ b/src/Blauhaus.Sync.Tests/Server/.TestObjects/MyDbContext.cs
@@ -0,0 +1,13 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace Blauhaus.Sync.Tests.Server.TestObjects
+{
+ public class MyDbContext : DbContext
+ {
+ public MyDbContext() { }
+
+ public MyDbContext(DbContextOptions options) : base(options) { }
+
+ public DbSet MyServerEntities { get; set; } = null!;
+ }
+}
\ No newline at end of file
diff --git a/src/Blauhaus.Sync.Tests/Server/.TestObjects/MyServerEntity.cs b/src/Blauhaus.Sync.Tests/Server/.TestObjects/MyServerEntity.cs
new file mode 100644
index 0000000..84a673a
--- /dev/null
+++ b/src/Blauhaus.Sync.Tests/Server/.TestObjects/MyServerEntity.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Threading.Tasks;
+using Blauhaus.Domain.Abstractions.DtoHandlers;
+using Blauhaus.Domain.Abstractions.Entities;
+using Blauhaus.Domain.Server.Entities;
+using Blauhaus.Sync.Tests.TestObjects;
+
+namespace Blauhaus.Sync.Tests.Server.TestObjects
+{
+ public class MyServerEntity : BaseServerEntity, IDtoOwner
+ {
+ public MyServerEntity()
+ {
+ }
+
+ public MyServerEntity(string name, DateTime createdAt, Guid id, EntityState entityState = EntityState.Active) : base(createdAt, id, entityState)
+ {
+ Name = name;
+ }
+
+ public string Name { get; private set; } = null!;
+
+
+ public Task GetDtoAsync()
+ {
+ return Task.FromResult(new MyDto
+ {
+ EntityState = EntityState,
+ Id = Id,
+ ModifiedAtTicks = ModifiedAt.Ticks,
+ Name = Name
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Blauhaus.Sync.sln b/src/Blauhaus.Sync.sln
index 26f4d7b..1dd765a 100644
--- a/src/Blauhaus.Sync.sln
+++ b/src/Blauhaus.Sync.sln
@@ -26,7 +26,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blauhaus.Sync.TestHelpers.O
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blauhaus.Sync.TestHelpers.EfCore", "Blauhaus.Sync.TestHelpers.EfCore\Blauhaus.Sync.TestHelpers.EfCore.csproj", "{187486F3-5A3F-4B86-9FE1-D415EBCCF345}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blauhaus.Sync.TestHelpers.Sqlite", "Blauhaus.Sync.TestHelpers.Sqlite\Blauhaus.Sync.TestHelpers.Sqlite.csproj", "{429E6227-4427-447C-99AD-A786206918AB}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blauhaus.Sync.TestHelpers.Sqlite", "Blauhaus.Sync.TestHelpers.Sqlite\Blauhaus.Sync.TestHelpers.Sqlite.csproj", "{429E6227-4427-447C-99AD-A786206918AB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blauhaus.Sync.Server.Orleans", "Blauhaus.Sync.Server.Orleans\Blauhaus.Sync.Server.Orleans.csproj", "{41534D03-1B5C-497B-996E-8B9F9AE8DA52}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -74,6 +76,10 @@ Global
{429E6227-4427-447C-99AD-A786206918AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{429E6227-4427-447C-99AD-A786206918AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{429E6227-4427-447C-99AD-A786206918AB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {41534D03-1B5C-497B-996E-8B9F9AE8DA52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {41534D03-1B5C-497B-996E-8B9F9AE8DA52}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {41534D03-1B5C-497B-996E-8B9F9AE8DA52}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {41534D03-1B5C-497B-996E-8B9F9AE8DA52}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE