From 98005933debc804f483a53b0e53ed6bf7186d09d Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 19 Jun 2025 09:34:34 +0100 Subject: [PATCH 1/3] Remove DistinctBy as we don't use it (#342) --- src/Speckle.Sdk.Dependencies/Collections.cs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/Speckle.Sdk.Dependencies/Collections.cs b/src/Speckle.Sdk.Dependencies/Collections.cs index b4c910da..aa622c83 100644 --- a/src/Speckle.Sdk.Dependencies/Collections.cs +++ b/src/Speckle.Sdk.Dependencies/Collections.cs @@ -22,23 +22,4 @@ public static class Collections public static class EnumerableExtensions { public static IEnumerable RangeFrom(int from, int to) => Enumerable.Range(from, to - from + 1); - -#if NETSTANDARD2_0 - public static IEnumerable DistinctBy( - this IEnumerable source, - Func keySelector - ) - { - var keys = new HashSet(); - foreach (var element in source) - { - if (keys.Contains(keySelector(element))) - { - continue; - } - keys.Add(keySelector(element)); - yield return element; - } - } -#endif } From b97702adb14213f3cf700190274f60bdd88eeb1e Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 30 Jun 2025 11:37:30 +0100 Subject: [PATCH 2/3] Small fixes to SDK (#347) * Increase channel capacity to make things more performant * Avoid logging send cancellation exceptions, caller did it * Try to avoid collection modified errors when cancelling by more aggressive checks * oops, rethrow, don't catch --- .../Serialization/ChannelLoader.cs | 2 +- .../Serialization/ChannelSaver.cs | 2 +- .../Api/Operations/Operations.Send.cs | 5 +++++ .../Serialisation/V2/Send/SerializeProcess.cs | 18 +++++++++++++----- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Speckle.Sdk.Dependencies/Serialization/ChannelLoader.cs b/src/Speckle.Sdk.Dependencies/Serialization/ChannelLoader.cs index a05b7d7f..43f49e5d 100644 --- a/src/Speckle.Sdk.Dependencies/Serialization/ChannelLoader.cs +++ b/src/Speckle.Sdk.Dependencies/Serialization/ChannelLoader.cs @@ -5,7 +5,7 @@ namespace Speckle.Sdk.Dependencies.Serialization; public abstract class ChannelLoader(CancellationToken cancellationToken) { - private const int RECEIVE_CAPACITY = 5000; + private const int RECEIVE_CAPACITY = 10000; private const int HTTP_GET_CHUNK_SIZE = 500; private const int MAX_PARALLELISM_HTTP = 4; diff --git a/src/Speckle.Sdk.Dependencies/Serialization/ChannelSaver.cs b/src/Speckle.Sdk.Dependencies/Serialization/ChannelSaver.cs index 37d1b999..b688f3a2 100644 --- a/src/Speckle.Sdk.Dependencies/Serialization/ChannelSaver.cs +++ b/src/Speckle.Sdk.Dependencies/Serialization/ChannelSaver.cs @@ -8,7 +8,7 @@ namespace Speckle.Sdk.Dependencies.Serialization; public abstract class ChannelSaver where T : IHasByteSize { - private const int SEND_CAPACITY = 1000; + private const int SEND_CAPACITY = 10000; private const int HTTP_SEND_CHUNK_SIZE = 25_000_000; //bytes private static readonly TimeSpan HTTP_BATCH_TIMEOUT = TimeSpan.FromSeconds(2); private const int MAX_PARALLELISM_HTTP = 4; diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs index 18ac48bb..eaad0b18 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs @@ -47,6 +47,11 @@ public partial class Operations receiveActivity?.SetStatus(SdkActivityStatusCode.Ok); return results; } + catch (OperationCanceledException) + { + //this is handled by the caller + throw; + } catch (Exception ex) { receiveActivity?.SetStatus(SdkActivityStatusCode.Error); diff --git a/src/Speckle.Sdk/Serialisation/V2/Send/SerializeProcess.cs b/src/Speckle.Sdk/Serialisation/V2/Send/SerializeProcess.cs index 0254921d..759ffa19 100644 --- a/src/Speckle.Sdk/Serialisation/V2/Send/SerializeProcess.cs +++ b/src/Speckle.Sdk/Serialisation/V2/Send/SerializeProcess.cs @@ -226,9 +226,17 @@ public sealed class SerializeProcess( var childClosures = _childClosurePool.Get(); foreach (var childClosure in taskClosures) { + if (_processSource.Token.IsCancellationRequested) + { + return EMPTY_CLOSURES; + } foreach (var kvp in childClosure) { childClosures[kvp.Key] = kvp.Value; + if (_processSource.Token.IsCancellationRequested) + { + return EMPTY_CLOSURES; + } } _currentClosurePool.Return(childClosure); @@ -253,13 +261,13 @@ public sealed class SerializeProcess( progress?.Report(new(ProgressEvent.FromCacheOrSerialized, _objectCount, Math.Max(_objectCount, _objectsFound))); foreach (var item in items) { + if (_processSource.Token.IsCancellationRequested) + { + return EMPTY_CLOSURES; + } + if (item.NeedsStorage) { - if (_processSource.Token.IsCancellationRequested) - { - return EMPTY_CLOSURES; - } - Interlocked.Increment(ref _objectsSerialized); await objectSaver.SaveAsync(item).ConfigureAwait(false); } From 33c2e6e1a48334cc06fbf697f4719d45e4f476c5 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 30 Jun 2025 11:54:44 +0100 Subject: [PATCH 3/3] Better handle graphql commit errors (#343) * Better handle graphql commit errors * add graphql error test --- src/Speckle.Sdk/Api/Exceptions.cs | 11 +++++++++++ src/Speckle.Sdk/Api/GraphQL/GraphQLErrorHandler.cs | 1 + .../Speckle.Sdk.Tests.Unit/Api/GraphQLErrorHandler.cs | 1 + 3 files changed, 13 insertions(+) diff --git a/src/Speckle.Sdk/Api/Exceptions.cs b/src/Speckle.Sdk/Api/Exceptions.cs index b7267df9..94833754 100644 --- a/src/Speckle.Sdk/Api/Exceptions.cs +++ b/src/Speckle.Sdk/Api/Exceptions.cs @@ -126,3 +126,14 @@ public sealed class WorkspacePermissionException : SpeckleGraphQLException public WorkspacePermissionException(string? message, Exception? innerException) : base(message, innerException) { } } + +public sealed class CannotCreateCommitException : SpeckleGraphQLException +{ + public CannotCreateCommitException() { } + + public CannotCreateCommitException(string? message) + : base(message) { } + + public CannotCreateCommitException(string? message, Exception? innerException) + : base(message, innerException) { } +} diff --git a/src/Speckle.Sdk/Api/GraphQL/GraphQLErrorHandler.cs b/src/Speckle.Sdk/Api/GraphQL/GraphQLErrorHandler.cs index 4fa7d9f5..14e902e6 100644 --- a/src/Speckle.Sdk/Api/GraphQL/GraphQLErrorHandler.cs +++ b/src/Speckle.Sdk/Api/GraphQL/GraphQLErrorHandler.cs @@ -33,6 +33,7 @@ internal static class GraphQLErrorHandler "BAD_USER_INPUT" => new SpeckleGraphQLBadInputException(message), "INTERNAL_SERVER_ERROR" => new SpeckleGraphQLInternalErrorException(message), "WORKSPACES_MODULE_DISABLED_ERROR" => new SpeckleGraphQLWorkspaceNotEnabledException(message), + "COMMIT_CREATE_ERROR" => new CannotCreateCommitException(message), _ => new SpeckleGraphQLException(message), }; exceptions.Add(ex); diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/GraphQLErrorHandler.cs b/tests/Speckle.Sdk.Tests.Unit/Api/GraphQLErrorHandler.cs index f3adbcb8..2aa0b3bc 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/GraphQLErrorHandler.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/GraphQLErrorHandler.cs @@ -23,6 +23,7 @@ public class GraphQLErrorHandlerTests ]; yield return [typeof(SpeckleGraphQLException), new Map { { "foo", "bar" } }]; yield return [typeof(SpeckleGraphQLException), new Map { { "code", "CUSTOM_THING" } }]; + yield return [typeof(CannotCreateCommitException), new Map { { "code", "COMMIT_CREATE_ERROR" } }]; } [Theory]