diff --git a/src/Speckle.Sdk.Dependencies/Serialization/ChannelSaver.cs b/src/Speckle.Sdk.Dependencies/Serialization/ChannelSaver.cs index b2e09329..94e5202c 100644 --- a/src/Speckle.Sdk.Dependencies/Serialization/ChannelSaver.cs +++ b/src/Speckle.Sdk.Dependencies/Serialization/ChannelSaver.cs @@ -68,9 +68,9 @@ public Task Start(CancellationToken cancellationToken) => ); public async ValueTask Save(T item, CancellationToken cancellationToken) => - await _checkCacheChannel.Writer.WriteAsync(item, cancellationToken).ConfigureAwait(true); + await _checkCacheChannel.Writer.WriteAsync(item, cancellationToken).ConfigureAwait(false); - public async Task> SendToServer(IMemoryOwner batch) + private async Task> SendToServer(IMemoryOwner batch) { await SendToServer((Batch)batch).ConfigureAwait(false); return batch; @@ -78,11 +78,17 @@ public async Task> SendToServer(IMemoryOwner batch) public abstract Task SendToServer(Batch batch); - public void DoneTraversing() => _checkCacheChannel.Writer.TryComplete(); + public abstract void SaveToCache(List item); + + public Task DoneTraversing() + { + _checkCacheChannel.Writer.TryComplete(); + return Task.CompletedTask; + } public async Task DoneSaving() { - await _checkCacheChannel.Reader.Completion.ConfigureAwait(true); + await _checkCacheChannel.Reader.Completion.ConfigureAwait(false); lock (_exceptions) { if (_exceptions.Count > 0) @@ -103,6 +109,4 @@ public async Task DoneSaving() } } } - - public abstract void SaveToCache(List item); } diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs index a05ba4c3..0c1ba2d7 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs @@ -21,16 +21,15 @@ CancellationToken cancellationToken metricsFactory.CreateCounter("Receive").Add(1); receiveActivity?.SetTag("objectId", objectId); - + var process = serializeProcessFactory.CreateDeserializeProcess( + url, + streamId, + authorizationToken, + onProgressAction, + cancellationToken + ); try { - using var process = serializeProcessFactory.CreateDeserializeProcess( - url, - streamId, - authorizationToken, - onProgressAction, - cancellationToken - ); var result = await process.Deserialize(objectId).ConfigureAwait(false); receiveActivity?.SetStatus(SdkActivityStatusCode.Ok); return result; @@ -41,6 +40,10 @@ CancellationToken cancellationToken receiveActivity?.RecordException(ex); throw; } + finally + { + await process.DisposeAsync().ConfigureAwait(false); + } } /// diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs index 68ee9438..785f20a6 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs @@ -23,15 +23,15 @@ CancellationToken cancellationToken using var receiveActivity = activityFactory.Start("Operations.Send"); metricsFactory.CreateCounter("Send").Add(1); + var process = serializeProcessFactory.CreateSerializeProcess( + url, + streamId, + authorizationToken, + onProgressAction, + cancellationToken + ); try { - using var process = serializeProcessFactory.CreateSerializeProcess( - url, - streamId, - authorizationToken, - onProgressAction, - cancellationToken - ); var results = await process.Serialize(value).ConfigureAwait(false); receiveActivity?.SetStatus(SdkActivityStatusCode.Ok); @@ -43,6 +43,10 @@ CancellationToken cancellationToken receiveActivity?.RecordException(ex); throw; } + finally + { + await process.DisposeAsync().ConfigureAwait(false); + } } /// diff --git a/src/Speckle.Sdk/Serialisation/V2/PriorityScheduler.cs b/src/Speckle.Sdk/Serialisation/V2/PriorityScheduler.cs index 6e3b0167..7741cfbc 100644 --- a/src/Speckle.Sdk/Serialisation/V2/PriorityScheduler.cs +++ b/src/Speckle.Sdk/Serialisation/V2/PriorityScheduler.cs @@ -85,4 +85,23 @@ protected override void QueueTask(Task task) } protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) => false; // we might not want to execute task that should schedule as high or low priority inline + + public Task WaitForCompletion() + { + _tasks.CompleteAdding(); + return Task + .Factory.StartNew( + async () => + { + while (_threads != null && _threads.Any(x => x.IsAlive)) + { + await Task.Delay(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false); + } + }, + CancellationToken.None, + TaskCreationOptions.AttachedToParent, + TaskScheduler.Default + ) + .Unwrap(); + } } diff --git a/src/Speckle.Sdk/Serialisation/V2/Receive/DeserializeProcess.cs b/src/Speckle.Sdk/Serialisation/V2/Receive/DeserializeProcess.cs index 33000d26..cbe8feac 100644 --- a/src/Speckle.Sdk/Serialisation/V2/Receive/DeserializeProcess.cs +++ b/src/Speckle.Sdk/Serialisation/V2/Receive/DeserializeProcess.cs @@ -4,6 +4,7 @@ using Speckle.Sdk.Dependencies; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation.Utilities; +using Speckle.Sdk.SQLite; using Speckle.Sdk.Transports; namespace Speckle.Sdk.Serialisation.V2.Receive; @@ -16,24 +17,47 @@ public record DeserializeProcessOptions( bool SkipServer = false ); -public partial interface IDeserializeProcess : IDisposable; +public partial interface IDeserializeProcess : IAsyncDisposable; [GenerateAutoInterface] public sealed class DeserializeProcess( - IProgress? progress, IObjectLoader objectLoader, + IProgress? progress, IBaseDeserializer baseDeserializer, ILoggerFactory loggerFactory, CancellationToken cancellationToken, DeserializeProcessOptions? options = null ) : IDeserializeProcess { + public DeserializeProcess( + ISqLiteJsonCacheManager sqLiteJsonCacheManager, + IServerObjectManager serverObjectManager, + IProgress? progress, + IBaseDeserializer baseDeserializer, + ILoggerFactory loggerFactory, + CancellationToken cancellationToken, + DeserializeProcessOptions? options = null + ) + : +#pragma warning disable CA2000 + this( + new ObjectLoader(sqLiteJsonCacheManager, serverObjectManager, progress, cancellationToken), + progress, + baseDeserializer, + loggerFactory, + cancellationToken, + options + ) +#pragma warning restore CA2000 + { } + private readonly PriorityScheduler _belowNormal = new( loggerFactory.CreateLogger(), ThreadPriority.BelowNormal, Environment.ProcessorCount * 2, cancellationToken ); + private readonly DeserializeProcessOptions _options = options ?? new(); private readonly ConcurrentDictionary)> _closures = new(); @@ -44,10 +68,11 @@ public sealed class DeserializeProcess( public long Total { get; private set; } [AutoInterfaceIgnore] - public void Dispose() + public async ValueTask DisposeAsync() { objectLoader.Dispose(); _belowNormal.Dispose(); + await _belowNormal.WaitForCompletion().ConfigureAwait(false); } /// @@ -57,9 +82,7 @@ public void Dispose() public async Task Deserialize(string rootId) { - var (rootJson, childrenIds) = await objectLoader - .GetAndCache(rootId, _options, cancellationToken) - .ConfigureAwait(false); + var (rootJson, childrenIds) = await objectLoader.GetAndCache(rootId, _options).ConfigureAwait(false); var root = new Id(rootId); //childrenIds is already frozen but need to just add root? _allIds = childrenIds.Concat([root]).Freeze(); @@ -68,6 +91,7 @@ public async Task Deserialize(string rootId) _closures.TryAdd(root, (rootJson, childrenIds)); progress?.Report(new(ProgressEvent.DeserializeObject, _baseCache.Count, childrenIds.Count)); await Traverse(root).ConfigureAwait(false); + await _belowNormal.WaitForCompletion().ConfigureAwait(false); return _baseCache[root]; } diff --git a/src/Speckle.Sdk/Serialisation/V2/Receive/ObjectLoader.cs b/src/Speckle.Sdk/Serialisation/V2/Receive/ObjectLoader.cs index 5d6aa2b5..a2de245c 100644 --- a/src/Speckle.Sdk/Serialisation/V2/Receive/ObjectLoader.cs +++ b/src/Speckle.Sdk/Serialisation/V2/Receive/ObjectLoader.cs @@ -15,7 +15,8 @@ public partial interface IObjectLoader : IDisposable; public sealed class ObjectLoader( ISqLiteJsonCacheManager sqLiteJsonCacheManager, IServerObjectManager serverObjectManager, - IProgress? progress + IProgress? progress, + CancellationToken cancellationToken ) : ChannelLoader, IObjectLoader { private int? _allChildrenCount; @@ -28,11 +29,7 @@ public sealed class ObjectLoader( [AutoInterfaceIgnore] public void Dispose() => sqLiteJsonCacheManager.Dispose(); - public async Task<(Json, IReadOnlyCollection)> GetAndCache( - string rootId, - DeserializeProcessOptions options, - CancellationToken cancellationToken - ) + public async Task<(Json, IReadOnlyCollection)> GetAndCache(string rootId, DeserializeProcessOptions options) { _options = options; string? rootJson; @@ -97,9 +94,14 @@ public override async Task> Download(List ids) { var toCache = new List(); await foreach ( - var (id, json) in serverObjectManager.DownloadObjects(ids.Select(x => x.NotNull()).ToList(), progress, default) + var (id, json) in serverObjectManager.DownloadObjects( + ids.Select(x => x.NotNull()).ToList(), + progress, + cancellationToken + ) ) { + cancellationToken.ThrowIfCancellationRequested(); Interlocked.Increment(ref _downloaded); progress?.Report(new(ProgressEvent.DownloadObjects, _downloaded, _totalToDownload)); toCache.Add(new(new(id), new(json), true, null)); @@ -119,6 +121,7 @@ public override void SaveToCache(List batch) { if (!_options.SkipCache) { + cancellationToken.ThrowIfCancellationRequested(); sqLiteJsonCacheManager.SaveObjects(batch.Select(x => (x.Id.Value, x.Json.Value))); Interlocked.Exchange(ref _cached, _cached + batch.Count); progress?.Report(new(ProgressEvent.CachedToLocal, _cached, _allChildrenCount)); diff --git a/src/Speckle.Sdk/Serialisation/V2/Send/SerializeProcess.cs b/src/Speckle.Sdk/Serialisation/V2/Send/SerializeProcess.cs index 08d0808e..21a2b10d 100644 --- a/src/Speckle.Sdk/Serialisation/V2/Send/SerializeProcess.cs +++ b/src/Speckle.Sdk/Serialisation/V2/Send/SerializeProcess.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Logging; using Speckle.InterfaceGenerator; using Speckle.Sdk.Common; @@ -22,7 +23,7 @@ public readonly record struct SerializeProcessResults( IReadOnlyDictionary ConvertedReferences ); -public partial interface ISerializeProcess : IDisposable; +public partial interface ISerializeProcess : IAsyncDisposable; [GenerateAutoInterface] public sealed class SerializeProcess( @@ -36,12 +37,17 @@ public sealed class SerializeProcess( SerializeProcessOptions? options = null ) : ChannelSaver, ISerializeProcess { + //async dispose + [SuppressMessage("Usage", "CA2213:Disposable fields should be disposed")] private readonly PriorityScheduler _highest = new( loggerFactory.CreateLogger(), ThreadPriority.Highest, 2, cancellationToken ); + + //async dispose + [SuppressMessage("Usage", "CA2213:Disposable fields should be disposed")] private readonly PriorityScheduler _belowNormal = new( loggerFactory.CreateLogger(), ThreadPriority.BelowNormal, @@ -67,11 +73,18 @@ public sealed class SerializeProcess( private long _cached; [AutoInterfaceIgnore] - public void Dispose() + public async ValueTask DisposeAsync() { _highest.Dispose(); _belowNormal.Dispose(); sqLiteJsonCacheManager.Dispose(); + await WaitForSchedulerCompletion().ConfigureAwait(false); + } + + private async Task WaitForSchedulerCompletion() + { + await _highest.WaitForCompletion().ConfigureAwait(false); + await _belowNormal.WaitForCompletion().ConfigureAwait(false); } public async Task Serialize(Base root) @@ -88,10 +101,13 @@ public async Task Serialize(Base root) _highest ); } - await Traverse(root).ConfigureAwait(true); - DoneTraversing(); - await Task.WhenAll(findTotalObjectsTask, channelTask).ConfigureAwait(true); - await DoneSaving().ConfigureAwait(true); + await Traverse(root).ConfigureAwait(false); + await DoneTraversing().ConfigureAwait(false); + await Task.WhenAll(findTotalObjectsTask, channelTask).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + await DoneSaving().ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + await WaitForSchedulerCompletion().ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); return new(root.id.NotNull(), baseSerializer.ObjectReferences.Freeze()); } @@ -116,7 +132,7 @@ private async Task> Traverse(Base obj) cancellationToken.ThrowIfCancellationRequested(); var t = Task .Factory.StartNew( - async () => await Traverse(tmp).ConfigureAwait(true), + async () => await Traverse(tmp).ConfigureAwait(false), cancellationToken, TaskCreationOptions.AttachedToParent | TaskCreationOptions.PreferFairness, _belowNormal @@ -128,7 +144,7 @@ private async Task> Traverse(Base obj) Dictionary[] taskClosures = []; if (tasks.Count > 0) { - taskClosures = await Task.WhenAll(tasks).ConfigureAwait(true); + taskClosures = await Task.WhenAll(tasks).ConfigureAwait(false); } var childClosures = _childClosurePool.Get(); foreach (var childClosure in taskClosures) @@ -150,7 +166,7 @@ private async Task> Traverse(Base obj) if (item.NeedsStorage) { Interlocked.Increment(ref _objectsSerialized); - await Save(item, cancellationToken).ConfigureAwait(true); + await Save(item, cancellationToken).ConfigureAwait(false); } if (!currentClosures.ContainsKey(item.Id)) diff --git a/src/Speckle.Sdk/Serialisation/V2/SerializeProcessFactory.cs b/src/Speckle.Sdk/Serialisation/V2/SerializeProcessFactory.cs index debf914e..863d7026 100644 --- a/src/Speckle.Sdk/Serialisation/V2/SerializeProcessFactory.cs +++ b/src/Speckle.Sdk/Serialisation/V2/SerializeProcessFactory.cs @@ -69,11 +69,14 @@ public IDeserializeProcess CreateDeserializeProcess( { var sqLiteJsonCacheManager = sqLiteJsonCacheManagerFactory.CreateFromStream(streamId); var serverObjectManager = serverObjectManagerFactory.Create(url, streamId, authorizationToken); - -#pragma warning disable CA2000 - //owned by process, refactor later - var objectLoader = new ObjectLoader(sqLiteJsonCacheManager, serverObjectManager, progress); -#pragma warning restore CA2000 - return new DeserializeProcess(progress, objectLoader, baseDeserializer, loggerFactory, cancellationToken, options); + return new DeserializeProcess( + sqLiteJsonCacheManager, + serverObjectManager, + progress, + baseDeserializer, + loggerFactory, + cancellationToken, + options + ); } } diff --git a/src/Speckle.Sdk/Serialisation/V2/ServerObjectManager.cs b/src/Speckle.Sdk/Serialisation/V2/ServerObjectManager.cs index c957087f..aa9fc00c 100644 --- a/src/Speckle.Sdk/Serialisation/V2/ServerObjectManager.cs +++ b/src/Speckle.Sdk/Serialisation/V2/ServerObjectManager.cs @@ -50,11 +50,9 @@ [EnumeratorCancellation] CancellationToken cancellationToken using var _ = _activityFactory.Start(); cancellationToken.ThrowIfCancellationRequested(); - using var childrenHttpMessage = new HttpRequestMessage - { - RequestUri = new Uri($"/api/getobjects/{_streamId}", UriKind.Relative), - Method = HttpMethod.Post, - }; + using var childrenHttpMessage = new HttpRequestMessage(); + childrenHttpMessage.RequestUri = new Uri($"/api/getobjects/{_streamId}", UriKind.Relative); + childrenHttpMessage.Method = HttpMethod.Post; Dictionary postParameters = new() { { "objects", JsonConvert.SerializeObject(objectIds) } }; string serializedPayload = JsonConvert.SerializeObject(postParameters); @@ -62,7 +60,7 @@ [EnumeratorCancellation] CancellationToken cancellationToken childrenHttpMessage.Headers.Add("Accept", "text/plain"); HttpResponseMessage childrenHttpResponse = await _client - .SendAsync(childrenHttpMessage, cancellationToken) + .SendAsync(childrenHttpMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); await foreach (var (id, json) in ResponseProgress(childrenHttpResponse, progress, false, cancellationToken)) @@ -84,14 +82,12 @@ CancellationToken cancellationToken cancellationToken.ThrowIfCancellationRequested(); // Get root object - using var rootHttpMessage = new HttpRequestMessage - { - RequestUri = new Uri($"/objects/{_streamId}/{objectId}/single", UriKind.Relative), - Method = HttpMethod.Get, - }; + using var rootHttpMessage = new HttpRequestMessage(); + rootHttpMessage.RequestUri = new Uri($"/objects/{_streamId}/{objectId}/single", UriKind.Relative); + rootHttpMessage.Method = HttpMethod.Get; HttpResponseMessage rootHttpResponse = await _client - .SendAsync(rootHttpMessage, HttpCompletionOption.ResponseContentRead, cancellationToken) + .SendAsync(rootHttpMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); var (_, json) = await ResponseProgress(rootHttpResponse, progress, true, cancellationToken) diff --git a/tests/Speckle.Sdk.Serialization.Testing/Program.cs b/tests/Speckle.Sdk.Serialization.Testing/Program.cs index 5493bb61..51b285eb 100644 --- a/tests/Speckle.Sdk.Serialization.Testing/Program.cs +++ b/tests/Speckle.Sdk.Serialization.Testing/Program.cs @@ -55,7 +55,7 @@ Console.ReadLine(); Console.WriteLine("Executing"); -using var process2 = factory.CreateSerializeProcess( +var process2 = factory.CreateSerializeProcess( new Uri(url), streamId, token, @@ -66,4 +66,5 @@ await process2.Serialize(@base).ConfigureAwait(false); Console.WriteLine("Detach"); Console.ReadLine(); +await process2.DisposeAsync().ConfigureAwait(false); #pragma warning restore CA1506 diff --git a/tests/Speckle.Sdk.Serialization.Tests/CancellationTests.cs b/tests/Speckle.Sdk.Serialization.Tests/CancellationTests.cs index d0ce9d8e..5e2995a0 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/CancellationTests.cs +++ b/tests/Speckle.Sdk.Serialization.Tests/CancellationTests.cs @@ -26,7 +26,7 @@ public async Task Cancellation_Serialize() var testClass = new TestClass() { RegularProperty = "Hello" }; using var cancellationSource = new CancellationTokenSource(); - using var serializeProcess = new SerializeProcess( + await using var serializeProcess = new SerializeProcess( null, new DummySqLiteSendManager(), new DummyServerObjectManager(), @@ -50,7 +50,7 @@ public async Task Cancellation_Save_Server() var testClass = new TestClass() { RegularProperty = "Hello" }; using var cancellationSource = new CancellationTokenSource(); - using var serializeProcess = new SerializeProcess( + await using var serializeProcess = new SerializeProcess( null, new DummySqLiteSendManager(), new CancellationServerObjectManager(cancellationSource), @@ -73,7 +73,7 @@ public async Task Cancellation_Save_Sqlite() var testClass = new TestClass() { RegularProperty = "Hello" }; using var cancellationSource = new CancellationTokenSource(); - using var serializeProcess = new SerializeProcess( + await using var serializeProcess = new SerializeProcess( null, new CancellationSqLiteSendManager(cancellationSource), new DummyServerObjectManager(), @@ -98,14 +98,10 @@ public async Task Cancellation_Receive_Cache(string fileName, string rootId, int closures.Count.Should().Be(oldCount); using var cancellationSource = new CancellationTokenSource(); - var o = new ObjectLoader( + await using var process = new DeserializeProcess( new CancellationSqLiteJsonCacheManager(cancellationSource), new DummyReceiveServerObjectManager(closures), - null - ); - using var process = new DeserializeProcess( null, - o, new BaseDeserializer(new ObjectDeserializerFactory()), new NullLoggerFactory(), cancellationSource.Token, @@ -129,14 +125,10 @@ public async Task Cancellation_Receive_Server(string fileName, string rootId, in closures.Count.Should().Be(oldCount); using var cancellationSource = new CancellationTokenSource(); - var o = new ObjectLoader( + await using var process = new DeserializeProcess( new DummyCancellationSqLiteSendManager(), new CancellationServerObjectManager(cancellationSource), - null - ); - using var process = new DeserializeProcess( null, - o, new BaseDeserializer(new ObjectDeserializerFactory()), new NullLoggerFactory(), cancellationSource.Token, @@ -160,14 +152,10 @@ public async Task Cancellation_Receive_Deserialize(string fileName, string rootI closures.Count.Should().Be(oldCount); using var cancellationSource = new CancellationTokenSource(); - var o = new ObjectLoader( + await using var process = new DeserializeProcess( new DummySqLiteReceiveManager(closures), new DummyReceiveServerObjectManager(closures), - null - ); - using var process = new DeserializeProcess( null, - o, new CancellationBaseDeserializer(cancellationSource), new NullLoggerFactory(), cancellationSource.Token, diff --git a/tests/Speckle.Sdk.Serialization.Tests/DetachedTests.cs b/tests/Speckle.Sdk.Serialization.Tests/DetachedTests.cs index 284223c8..add4126d 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/DetachedTests.cs +++ b/tests/Speckle.Sdk.Serialization.Tests/DetachedTests.cs @@ -32,7 +32,7 @@ public async Task CanSerialize_New_Detached() var objects = new Dictionary(); - using var process2 = new SerializeProcess( + await using var process2 = new SerializeProcess( null, new DummySendCacheManager(objects), new DummyServerObjectManager(), @@ -117,7 +117,7 @@ public async Task CanSerialize_New_Detached2() var objects = new Dictionary(); - using var process2 = new SerializeProcess( + await using var process2 = new SerializeProcess( null, new DummySendCacheManager(objects), new DummyServerObjectManager(), @@ -187,7 +187,7 @@ public async Task CanSerialize_New_Detached_With_DataChunks() var objects = new Dictionary(); - using var process2 = new SerializeProcess( + await using var process2 = new SerializeProcess( null, new DummySendCacheManager(objects), new DummyServerObjectManager(), @@ -222,7 +222,7 @@ public async Task CanSerialize_New_Detached_With_DataChunks2() var objects = new Dictionary(); - using var process2 = new SerializeProcess( + await using var process2 = new SerializeProcess( null, new DummySendCacheManager(objects), new DummyServerObjectManager(), diff --git a/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.cs b/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.cs index 7cdd2b89..b4f13242 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.cs +++ b/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.cs @@ -24,7 +24,7 @@ public async Task Test_Exceptions_Upload() var testClass = new TestClass() { RegularProperty = "Hello" }; var objects = new Dictionary(); - using var process2 = new SerializeProcess( + await using var process2 = new SerializeProcess( null, new DummySendCacheManager(objects), new ExceptionServerObjectManager(), @@ -45,7 +45,7 @@ public async Task Test_Exceptions_Cache() { var testClass = new TestClass() { RegularProperty = "Hello" }; - using var process2 = new SerializeProcess( + await using var process2 = new SerializeProcess( null, new ExceptionSendCacheManager(), new DummyServerObjectManager(), @@ -66,11 +66,12 @@ public async Task Test_Exceptions_Receive_Server_Skip_Both() var o = new ObjectLoader( new DummySqLiteReceiveManager(new Dictionary()), new ExceptionServerObjectManager(), - null - ); - using var process = new DeserializeProcess( null, + default + ); + await using var process = new DeserializeProcess( o, + null, new BaseDeserializer(new ObjectDeserializerFactory()), new NullLoggerFactory(), default, @@ -91,10 +92,10 @@ public async Task Test_Exceptions_Receive_Server(string fileName, string rootId, var closures = await TestFileManager.GetFileAsClosures(fileName); closures.Count.Should().Be(oldCount); - var o = new ObjectLoader(new DummySqLiteReceiveManager(closures), new ExceptionServerObjectManager(), null); - using var process = new DeserializeProcess( + await using var process = new DeserializeProcess( + new DummySqLiteReceiveManager(closures), + new ExceptionServerObjectManager(), null, - o, new BaseDeserializer(new ObjectDeserializerFactory()), new NullLoggerFactory(), default, @@ -116,14 +117,10 @@ public async Task Test_Exceptions_Receive_Cache(string fileName, string rootId, var closures = await TestFileManager.GetFileAsClosures(fileName); closures.Count.Should().Be(oldCount); - var o = new ObjectLoader( + await using var process = new DeserializeProcess( new ExceptionSendCacheManager(hasObject), new DummyReceiveServerObjectManager(closures), - null - ); - using var process = new DeserializeProcess( null, - o, new BaseDeserializer(new ObjectDeserializerFactory()), new NullLoggerFactory(), default, diff --git a/tests/Speckle.Sdk.Serialization.Tests/ExplicitInterfaceTests.cs b/tests/Speckle.Sdk.Serialization.Tests/ExplicitInterfaceTests.cs index bf347fc4..0bd05a14 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/ExplicitInterfaceTests.cs +++ b/tests/Speckle.Sdk.Serialization.Tests/ExplicitInterfaceTests.cs @@ -19,7 +19,7 @@ public async Task Test_Json() var testClass = new TestClass() { RegularProperty = "Hello" }; var objects = new Dictionary(); - using var process2 = new SerializeProcess( + await using var process2 = new SerializeProcess( null, new DummySendCacheManager(objects), new DummyServerObjectManager(), diff --git a/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs b/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs index 4d6f9e9f..64db5cb9 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs +++ b/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs @@ -19,13 +19,9 @@ public class SerializationTests { private class TestLoader(string json) : IObjectLoader { - public Task<(Json, IReadOnlyCollection)> GetAndCache( - string rootId, - DeserializeProcessOptions? options, - CancellationToken cancellationToken - ) + public Task<(Json, IReadOnlyCollection)> GetAndCache(string rootId, DeserializeProcessOptions? options) { - var childrenIds = ClosureParser.GetChildrenIds(new(json), cancellationToken).Select(x => new Id(x)).ToList(); + var childrenIds = ClosureParser.GetChildrenIds(new(json), default).Select(x => new Id(x)).ToList(); return Task.FromResult<(Json, IReadOnlyCollection)>((new(json), childrenIds)); } @@ -49,11 +45,7 @@ public async Task RunTest2(string fileName) public class TestObjectLoader(IReadOnlyDictionary idToObject) : IObjectLoader { - public Task<(Json, IReadOnlyCollection)> GetAndCache( - string rootId, - DeserializeProcessOptions? options, - CancellationToken cancellationToken - ) + public Task<(Json, IReadOnlyCollection)> GetAndCache(string rootId, DeserializeProcessOptions? options) { var json = idToObject.GetValueOrDefault(rootId); if (json == null) @@ -61,7 +53,7 @@ CancellationToken cancellationToken throw new KeyNotFoundException("Root not found"); } - var allChildren = ClosureParser.GetChildrenIds(json, cancellationToken).Select(x => new Id(x)).ToList(); + var allChildren = ClosureParser.GetChildrenIds(json, default).Select(x => new Id(x)).ToList(); return Task.FromResult<(Json, IReadOnlyCollection)>((new(json), allChildren)); } @@ -115,9 +107,9 @@ public async Task Basic_Namespace_Validation(string fileName) public async Task Basic_Namespace_Validation_New(string fileName) { var closures = await TestFileManager.GetFileAsClosures(fileName); - using var process = new DeserializeProcess( - null, + await using var process = new DeserializeProcess( new TestObjectLoader(closures), + null, new BaseDeserializer(new ObjectDeserializerFactory()), new NullLoggerFactory(), default @@ -210,25 +202,31 @@ public async Task Roundtrip_Test_New(string fileName, string rootId, int oldCoun var closures = await TestFileManager.GetFileAsClosures(fileName); closures.Count.Should().Be(oldCount); - var o = new ObjectLoader( - new DummySqLiteReceiveManager(closures), - new DummyReceiveServerObjectManager(closures), - null - ); - using var process = new DeserializeProcess( - null, - o, - new BaseDeserializer(new ObjectDeserializerFactory()), - new NullLoggerFactory(), - default, - new(true) - ); - var root = await process.Deserialize(rootId); - process.BaseCache.Count.Should().Be(oldCount); - process.Total.Should().Be(oldCount); + Base root; + using ( + var o = new ObjectLoader( + new DummySqLiteReceiveManager(closures), + new DummyReceiveServerObjectManager(closures), + null, + default + ) + ) + { + await using var process = new DeserializeProcess( + o, + null, + new BaseDeserializer(new ObjectDeserializerFactory()), + new NullLoggerFactory(), + default, + new(true) + ); + root = await process.Deserialize(rootId); + process.BaseCache.Count.Should().Be(oldCount); + process.Total.Should().Be(oldCount); + } var newIdToJson = new ConcurrentDictionary(); - using ( + await using ( var serializeProcess = new SerializeProcess( null, new DummySqLiteSendManager(), @@ -244,8 +242,6 @@ public async Task Roundtrip_Test_New(string fileName, string rootId, int oldCoun var (rootId2, _) = await serializeProcess.Serialize(root); rootId2.Should().Be(root.id); } - //ensures threads are done? - await Task.Delay(TimeSpan.FromSeconds(2)); newIdToJson.Count.Should().Be(newCount); foreach (var newKvp in newIdToJson) diff --git a/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs b/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs index 3b1a4fc2..e6cc814a 100644 --- a/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs +++ b/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs @@ -56,10 +56,10 @@ public async Task RunTest_New() streamId, null ); - var o = new ObjectLoader(sqlite, serverObjects, null); - using var process = new DeserializeProcess( + await using var process = new DeserializeProcess( + sqlite, + serverObjects, null, - o, new BaseDeserializer(new ObjectDeserializerFactory()), default, new(skipCache)