From 3bb0860d140844d983c99ad9576d0bed18e3fbd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinhagen?= <88777268+bjoernsteinhagen@users.noreply.github.com> Date: Wed, 8 Apr 2026 12:27:22 +0200 Subject: [PATCH] feat(connectors): disable cache config (#1349) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(all): adds disable cache functionality * feat(connectors): prevents StoreSendResult if cache disabled * fix(connectors): restores IsBypassed state * Explicit flag instead implicit * Delete unused flag * Add packfile support --------- Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com> Co-authored-by: oguzhankoral Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com> --- .../Operations/Send/SendAsyncComponent.cs | 11 ++++++- .../Operations/Send/SendComponent.cs | 2 +- .../Bindings/SendOperationManager.cs | 21 ++++++++---- .../Settings/ConfigStore.cs | 2 ++ .../Operations/SendOperation.cs | 32 +++++++++++++------ 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendAsyncComponent.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendAsyncComponent.cs index bd45a382c..b2d15c7b5 100644 --- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendAsyncComponent.cs +++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendAsyncComponent.cs @@ -505,7 +505,16 @@ public class SendComponentWorker : WorkerInstance using var scope = PriorityLoader.CreateScopeForActiveDocument(); var sendOperation = scope.ServiceProvider.GetRequiredService>(); (SendOperationResult result, string versionId, string? ingestionId) = await sendOperation - .Send([rootCollectionWrapper], sendInfo, fileName, fileBytes, Parent.VersionMessage, progress, CancellationToken) + .Send( + [rootCollectionWrapper], + sendInfo, + fileName, + fileBytes, + Parent.VersionMessage, + progress, + true, + CancellationToken + ) .ConfigureAwait(false); if (ingestionId != null) diff --git a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendComponent.cs b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendComponent.cs index e4ebd5077..eb1d785f2 100644 --- a/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendComponent.cs +++ b/Connectors/Rhino/Speckle.Connectors.GrasshopperShared/Components/Operations/Send/SendComponent.cs @@ -283,7 +283,7 @@ public class SendComponent : SpeckleTaskCapableComponent> gatherObjects, string? fileName, long? fileSizeBytes - ) - { + ) => await Process( commands, modelCardId, @@ -48,7 +49,6 @@ public sealed class SendOperationManager( fileName, fileSizeBytes ); - } public async Task Process( ISendBindingUICommands commands, @@ -57,8 +57,7 @@ public sealed class SendOperationManager( Func>> gatherObjects, string? fileName, long? fileSizeBytes - ) - { + ) => await Process( commands, modelCardId, @@ -67,7 +66,6 @@ public sealed class SendOperationManager( fileName, fileSizeBytes ); - } public async Task Process( ISendBindingUICommands commands, @@ -79,6 +77,7 @@ public sealed class SendOperationManager( ) { using var activity = activityFactory.Start(); + var sendConversionCache = serviceScope.ServiceProvider.GetRequiredService(); try { if (store.GetModelById(modelCardId) is not SenderModelCard modelCard) @@ -86,6 +85,7 @@ public sealed class SendOperationManager( // Handle as GLOBAL ERROR at BrowserBridge throw new InvalidOperationException("No publish model card was found."); } + using SendInfo sendInfo = GetSendInfo(modelCard); using var userScope = UserActivityScope.AddUserScope(sendInfo.Account); @@ -93,6 +93,14 @@ public sealed class SendOperationManager( initializeScope(serviceScope.ServiceProvider, modelCard); + // if user has disabled cache, wipe the in-memory cache before gathering and building objects + var configStore = serviceScope.ServiceProvider.GetRequiredService(); + var isCacheDisabled = configStore.GetConnectorConfig().DisableCache; + if (isCacheDisabled) + { + sendConversionCache.ClearCache(); // clear whatever is currently in there to ensure 0% cache hits + } + var progress = operationProgressManager.CreateOperationProgressEventHandler( commands.Bridge, modelCardId, @@ -116,6 +124,7 @@ public sealed class SendOperationManager( fileSizeBytes, null, progress, + saveToCache: !isCacheDisabled, cancellationItem.Token ); diff --git a/DUI3/Speckle.Connectors.DUI/Settings/ConfigStore.cs b/DUI3/Speckle.Connectors.DUI/Settings/ConfigStore.cs index 79c7da47e..5ae4befa8 100644 --- a/DUI3/Speckle.Connectors.DUI/Settings/ConfigStore.cs +++ b/DUI3/Speckle.Connectors.DUI/Settings/ConfigStore.cs @@ -165,6 +165,8 @@ public sealed class ConnectorConfig { public bool DarkTheme { get; init; } = true; + public bool DisableCache { get; init; } + /// /// Only used by Revit Connector !! /// We're exposing some settings to disable event listening inorder to debug app crash issues caused by Revit event handlers diff --git a/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs b/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs index cbd415dd3..a5340e46f 100644 --- a/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs +++ b/Sdk/Speckle.Connectors.Common/Operations/SendOperation.cs @@ -45,6 +45,7 @@ public sealed class SendOperation( long? fileSizeBytes, string? versionMessage, IProgress uiProgress, + bool saveToCache, CancellationToken cancellationToken ) { @@ -62,6 +63,7 @@ public sealed class SendOperation( fileSizeBytes, versionMessage, uiProgress, + saveToCache, cancellationToken ); } @@ -72,12 +74,13 @@ public sealed class SendOperation( fileSizeBytes, versionMessage, uiProgress, + saveToCache, cancellationToken ); } else { - return await SendViaVersionCreate(objects, sendInfo, versionMessage, uiProgress, cancellationToken); + return await SendViaVersionCreate(objects, sendInfo, versionMessage, uiProgress, saveToCache, cancellationToken); } } @@ -90,6 +93,7 @@ public sealed class SendOperation( string? versionMessage, #pragma warning restore IDE0060 IProgress uiProgress, + bool saveToCache, CancellationToken cancellationToken ) { @@ -136,8 +140,10 @@ public sealed class SendOperation( ); buildResult.RootObject["version"] = 3; - - WriteReferencesToCache(buildResult.ConversionResults, sendInfo.ProjectId); + if (saveToCache) + { + WriteReferencesToCache(buildResult.ConversionResults, sendInfo.ProjectId); + } SendOperationResult result = new(buildResult.RootObject.id!, new Dictionary(), buildResult.ConversionResults); @@ -175,6 +181,7 @@ public sealed class SendOperation( long? fileSizeBytes, string? versionMessage, IProgress uiProgress, + bool saveToCache, CancellationToken cancellationToken ) { @@ -199,7 +206,7 @@ public sealed class SendOperation( AggregateProgress progress = new(ingestionProgress, uiProgress); try { - SendOperationResult result = await ConvertAndSend(objects, sendInfo, progress, cancellationToken); + SendOperationResult result = await ConvertAndSend(objects, sendInfo, progress, saveToCache, cancellationToken); string createdVersionId = await sendInfo.Client.Ingestion.Complete( new(ingestion.id, sendInfo.ProjectId, result.RootObjId, versionMessage), @@ -234,10 +241,11 @@ public sealed class SendOperation( SendInfo sendInfo, string? versionMessage, IProgress progress, + bool saveToCache, CancellationToken cancellationToken ) { - SendOperationResult result = await ConvertAndSend(objects, sendInfo, progress, cancellationToken); + SendOperationResult result = await ConvertAndSend(objects, sendInfo, progress, saveToCache, cancellationToken); Version version = await sendInfo.Client.Version.Create( new( @@ -256,10 +264,11 @@ public sealed class SendOperation( IReadOnlyList objects, SendInfo sendInfo, IProgress onOperationProgressed, - CancellationToken ct = default + bool saveToCache, + CancellationToken cancellationToken ) { - var buildResult = await Build(objects, sendInfo.ProjectId, onOperationProgressed, ct); + var buildResult = await Build(objects, sendInfo.ProjectId, onOperationProgressed, cancellationToken); // base object handler is separated, so we can do some testing on non-production databases // exact interface may want to be tweaked when we implement this var results = await threadContext.RunOnWorkerAsync(async () => @@ -269,7 +278,8 @@ public sealed class SendOperation( sendInfo.ProjectId, sendInfo.Account, onOperationProgressed, - ct + saveToCache, + cancellationToken ); return results; @@ -296,6 +306,7 @@ public sealed class SendOperation( string projectId, Account account, IProgress onOperationProgressed, + bool saveToCache, CancellationToken cancellationToken ) { @@ -314,7 +325,10 @@ public sealed class SendOperation( cancellationToken ); - sendConversionCache.StoreSendResult(projectId, sendResult.ConvertedReferences); + if (saveToCache) + { + sendConversionCache.StoreSendResult(projectId, sendResult.ConvertedReferences); + } cancellationToken.ThrowIfCancellationRequested();