Skip to content

Remove sync-over-async where possible, consolidate blocking into helpers, add analyzers#1714

Merged
kevin-montrose merged 20 commits intomainfrom
users/kmontrose/asyncification
Apr 28, 2026
Merged

Remove sync-over-async where possible, consolidate blocking into helpers, add analyzers#1714
kevin-montrose merged 20 commits intomainfrom
users/kmontrose/asyncification

Conversation

@kevin-montrose
Copy link
Copy Markdown
Contributor

@kevin-montrose kevin-montrose commented Apr 17, 2026

Doing a pass through Garnet to remove blocking where possible, document where it's required, and prevent regression in the future.

There are broadly three places where blocking is still required:

  1. Startup
  2. Any of the "on the IO thread" command handling code, marked with Network prefix
  3. Callbacks during scan operations

Major changes:

  • All Task-like blocking operations in Garnet proper are moved to AsyncUtils
  • Task-like returning methods conform to .NET async naming rules now
  • .ConfigureAwait(false) added where missing
  • Where possible, blocking operations converted to async/await
  • Microsoft.VisualStudio.Threading analyzers added to flag future violations

Tsavorite and Garnet.client were not updated as aggressively to limit breaking changes.

TODO:

  • Consolidate .GetAwaiter().GetResult() calls into helpers that justify them
  • Get builds flagging naming (that is, missing Async suffix) violations
  • Get builds flagging blocking calls
  • dev targeting version - it's unlikely this can be cherry-picked cleanly, so it'll be non-trivial effort

dev version is #1730

@kevin-montrose kevin-montrose changed the title Remove blocking .Result & .GetResult() calls where possible Remove sync-over-async where possible, consolidate blocking into helpers, add analyzers Apr 21, 2026
@kevin-montrose kevin-montrose marked this pull request as ready for review April 23, 2026 20:12
Copilot AI review requested due to automatic review settings April 23, 2026 20:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes Garnet’s async usage by removing sync-over-async patterns where feasible, centralizing unavoidable blocking into a single helper, and adding analyzers/configuration to prevent regressions (notably around Async suffix rules and blocking waits).

Changes:

  • Introduces Garnet.common.AsyncUtils and replaces scattered .GetAwaiter().GetResult() / .Result / .Wait() with AsyncUtils.BlockingWait(...) in explicitly-justified synchronous contexts (e.g., network thread, disposal, startup).
  • Renames many async-returning APIs to follow .NET async naming conventions (adds Async suffix) and updates call sites/tests accordingly; adds missing .ConfigureAwait(false) in multiple places.
  • Adds Microsoft.VisualStudio.Threading.Analyzers across several projects and configures VSTHRD analyzer severities in .editorconfig.

Reviewed changes

Copilot reviewed 94 out of 94 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
test/Garnet.test/TaskManagerTests.cs Updates tests to use WaitAsync and async test methods.
test/Garnet.test/RespVectorSetTests.cs Converts recovery tests to async; updates commit waits to async.
test/Garnet.test/RespSortedSetTests.cs Switches AOF commit usage to async in recovery test.
test/Garnet.test/RespHashTests.cs Switches AOF commit usage to async in recovery test.
test/Garnet.test/RespAofTests.cs Converts many AOF tests to async and awaits commits.
test/Garnet.test/RespAofAzureTests.cs Converts Azure AOF tests to async and awaits commits.
test/Garnet.test/MultiDatabaseTests.cs Converts multi-db AOF recovery tests to async and awaits commits.
test/Garnet.test/GarnetJSON/JsonCommandsTest.cs Converts JSON AOF recovery test to async and awaits commit.
test/Garnet.test.cluster/ReplicationTests/ClusterReplicationBaseTests.cs Makes manual checkpointing test async; awaits commit calls.
modules/GarnetJSON/GarnetJSON.csproj Adds VS threading analyzers package reference.
metrics/HdrHistogram/Utilities/WriterReaderPhaser.cs Replaces Task-based yielding/delay with Thread.Yield/Sleep.
metrics/HdrHistogram/HdrHistogram.csproj Adds VS threading analyzers package reference.
main/GarnetServer/GarnetServer.csproj Adds VS threading analyzers package reference.
libs/storage/Tsavorite/cs/src/core/Device/RandomAccessLocalStorageDevice.cs Removes sync-over-async fast path; always awaits pool GetAsync().
libs/server/TaskManager/TaskType.cs Updates doc links to renamed StoreWrapper.*Async task implementations.
libs/server/TaskManager/TaskManager.cs Replaces blocking waits with AsyncUtils.BlockingWait; renames Cancel to CancelAsync; removes sync Wait.
libs/server/StoreWrapper.cs Renames checkpoint/task methods to *Async; removes sync AOF commit/wait helpers; adds ConfigureAwait(false) broadly.
libs/server/Servers/StoreApi.cs Removes sync AOF commit/wait; standardizes on CommitAOFAsync/WaitForCommitAsync.
libs/server/ServerConfig.cs Moves blocking index grow to AsyncUtils.BlockingWait on network thread; introduces HandleIndexSizeChangeAsync.
libs/server/Resp/Vector/VectorManager.Replication.cs Refactors replication replay tasks to pure async; removes sync waits in cancellation; adds blocking helper for disposal-only paths.
libs/server/Resp/Vector/VectorManager.cs Replaces .Wait() calls in Dispose with AsyncUtils.BlockingWait.
libs/server/Resp/RespServerSession.cs Uses AsyncUtils.BlockingWait for AOF commit waits on network thread.
libs/server/Resp/PubSubCommands.cs Switches cluster publish forwarding to async API + blocking helper on network thread.
libs/server/Resp/Objects/SortedSetCommands.cs Replaces .Result with AsyncUtils.BlockingWait for blocking pops on network thread.
libs/server/Resp/Objects/ListCommands.cs Replaces .Result with AsyncUtils.BlockingWait for blocking list operations on network thread.
libs/server/Resp/BasicCommands.cs Suppresses VSTHRD200 for NetworkGETAsync naming; removes ineffective ConfigureAwait(false) on Task.Run.
libs/server/Resp/AsyncProcessor.cs Renames AsyncGetProcessor to AsyncGetProcessorAsync.
libs/server/Resp/AdminCommands.cs Uses TakeCheckpointAsync and blocks via helper on network thread; switches COMMITAOF to async path.
libs/server/PubSub/SubscribeBroker.cs Renames broker loop to StartAsync and updates launcher.
libs/server/Objects/ItemBroker/CollectionItemBroker.cs Renames main loop Start -> StartAsync; adds ConfigureAwait(false) where needed.
libs/server/Metrics/GarnetServerMonitor.cs Switches monitor loop to Task-returning async method with forced async start.
libs/server/Garnet.server.csproj Adds VS threading analyzers package reference.
libs/server/Databases/SingleDatabaseManager.cs Makes checkpointing async end-to-end; removes sync continuations; updates index growth to async ValueTask.
libs/server/Databases/MultiDatabaseManager.cs Makes checkpointing async; converts index growth to async fan-out with Task.WhenAll.
libs/server/Databases/IDatabaseManager.cs Renames checkpoint and index-growth APIs to async signatures.
libs/server/Databases/DatabaseManagerBase.cs Converts index auto-grow to async flow; replaces async commits with sync Commit() in compaction path.
libs/server/Cluster/IClusterProvider.cs Switches publish API to ClusterPublishAsync (ValueTask).
libs/server/Auth/Aad/IssuerSigningTokenProvider.cs Centralizes blocking wait on OIDC config fetch via AsyncUtils.BlockingWait.
libs/server/AOF/AofProcessor.cs Uses blocking helper for checkpointing in replica replay path.
libs/host/Garnet.host.csproj Adds VS threading analyzers package reference.
libs/host/Configuration/Options.cs Removes sync-over-async for endpoint parsing by calling sync Format.TryCreateEndpoint.
libs/common/Networking/TcpNetworkHandlerBase.cs Simplifies override to return base task (no async state machine).
libs/common/Networking/TaskToApm.cs Uses AsyncUtils.BlockingWait for End methods; fixes ArgumentNullException parameter name.
libs/common/Networking/NetworkHandlerStream.cs Renames internal async read helper to ReadAsyncInternalAsync.
libs/common/Networking/NetworkHandler.cs Blocks client TLS auth in Start; uses blocking helper for completed SslStream.ReadAsync path.
libs/common/LightClient.cs Introduces sync socket connect path; uses sync network handler start.
libs/common/Garnet.common.csproj Adds VS threading analyzers package reference.
libs/common/Format.cs Splits endpoint creation into sync + async APIs; removes sync-over-async usages.
libs/common/ExceptionInjectionHelper.cs Renames WaitOnSet -> WaitOnSetAsync; adds sync WaitOnClear spin helper.
libs/common/AsyncUtils.cs Adds centralized blocking helper methods for Task/ValueTask.
libs/cluster/Session/RespClusterSlotManagementCommands.cs Uses blocking helper for epoch bump on network thread.
libs/cluster/Session/RespClusterReplicationCommands.cs Converts replication commands to async manager APIs but blocks on network thread.
libs/cluster/Session/RespClusterMigrateCommands.cs Removes ineffective ConfigureAwait(false) on Task.Run; uses discard pattern.
libs/cluster/Session/RespClusterFailoverCommands.cs Uses blocking helper for epoch transitions and replication offset wait on network thread.
libs/cluster/Session/ReplicaOfCommand.cs Renames network handler method; blocks on async epoch/task suspension appropriately.
libs/cluster/Session/MigrateCommand.cs Uses sync DNS resolve; converts start-migration to async API + blocking wait on network thread.
libs/cluster/Session/ClusterSession.cs Refactors unsafe usage boundaries; makes epoch bump transition async.
libs/cluster/Server/Replication/ReplicationManager.cs Renames replication offset wait to WaitForReplicationOffsetAsync; blocks on replication init path.
libs/cluster/Server/Replication/ReplicaOps/ReplicationReplicaAofSync.cs Updates replay task runner to async method.
libs/cluster/Server/Replication/ReplicaOps/ReplicaReplayTask.cs Converts replay loop from async void to Task; adds ConfigureAwait(false).
libs/cluster/Server/Replication/ReplicaOps/ReceiveCheckpointHandler.cs Replaces async clear-wait with sync spin wait for debug-only injection.
libs/cluster/Server/Replication/PrimaryOps/ReplicationPrimaryAofSync.cs Updates replica sync task invocation to async method.
libs/cluster/Server/Replication/PrimaryOps/ReplicaSyncSession.cs Renames checkpoint send/acquire and related helpers to async; uses ConfigureAwait(false) broadly.
libs/cluster/Server/Replication/PrimaryOps/PrimarySync.cs Converts primary sync entry points to async tuple-returning APIs (success + error payload).
libs/cluster/Server/Replication/PrimaryOps/DisklessReplication/ReplicationSyncManager.cs Renames driver/flush/snapshot helpers to async; adds ConfigureAwait(false) and async cancellation.
libs/cluster/Server/Replication/PrimaryOps/DisklessReplication/ReplicationSnapshotIterator.cs Uses blocking helper for flush waits in scan callbacks.
libs/cluster/Server/Replication/PrimaryOps/DisklessReplication/ReplicaSyncSession.cs Renames flush/sync methods to async; removes sync-over-async patterns in execute/flush.
libs/cluster/Server/Replication/PrimaryOps/AofSyncTaskInfo.cs Renames replica sync task to ReplicaSyncTaskAsync.
libs/cluster/Server/Migration/MigrationDriver.cs Makes migration task start and connection checks async.
libs/cluster/Server/Migration/MigrateSessionSlots.cs Refactors slot migration driver to async; removes unsafe+sync waiting patterns.
libs/cluster/Server/Migration/MigrateSessionKeys.cs Converts KEYS migration flow to async; avoids blocking inside unsafe blocks.
libs/cluster/Server/Migration/MigrateSessionKeyAccess.cs Converts config propagation waits to async-returning method.
libs/cluster/Server/Migration/MigrateSessionCommonUtils.cs Refactors send/flush/retry logic to async-friendly patterns.
libs/cluster/Server/Migration/MigrateSession.cs Makes connection/auth handling async; refactors connection checks.
libs/cluster/Server/Migration/MigrateOperation.cs Converts initialization/transmit flows to async.
libs/cluster/Server/Gossip/Gossip.cs Converts gossip loop and cluster publish forwarding to async APIs; introduces sync fast-path with async fallback.
libs/cluster/Server/Gossip/GarnetServerNode.cs Changes InitializeAsync to ValueTask; refactors gossip call to async implementation.
libs/cluster/Server/Gossip/GarnetClusterConnectionStore.cs Renames connection store methods to async; makes GetOrAddAsync return ValueTask.
libs/cluster/Server/Gossip/GarnetClientExtensions.cs Adds Async suffix to extension methods; adjusts publish parameter passing.
libs/cluster/Server/Failover/ReplicaFailoverSession.cs Renames and async-ifies failover steps; updates gossip and attach flows.
libs/cluster/Server/Failover/PrimaryFailoverSession.cs Renames and async-ifies replica sync checks and failover orchestration.
libs/cluster/Server/Failover/FailoverManager.cs Updates invocations to renamed async failover entry points.
libs/cluster/Server/ClusterProvider.cs Makes epoch bump/transition wait async.
libs/cluster/Server/ClusterManagerWorkerState.cs Converts TryAddReplica to async tuple-returning API; suspends tasks asynchronously.
libs/cluster/Server/ClusterManager.cs Renames cluster config flush background loop to async.
libs/cluster/Garnet.cluster.csproj Adds VS threading analyzers package reference.
libs/client/GarnetClientAPI/GarnetClientExecuteAPI.cs Removes ref Span<byte> parameters from no-response API surface.
libs/client/GarnetClient.cs Introduces sync socket connect path; blocks auth via AsyncUtils.BlockingWait; removes sync Reconnect.
libs/client/ClientSession/GarnetClientSession.cs Introduces sync socket connect path; moves auth to sync execute; adds async connect/reconnect APIs.
hosting/Windows/Garnet.worker/Garnet.worker.csproj Adds VS threading analyzers package reference.
Directory.Packages.props Pins Microsoft.VisualStudio.Threading.Analyzers version centrally.
.editorconfig Enables VSTHRD200 as error and configures related analyzer severities.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread libs/cluster/Server/Migration/MigrateSessionCommonUtils.cs Outdated
Comment thread libs/server/Resp/Vector/VectorManager.Replication.cs
Comment thread libs/cluster/Server/Gossip/Gossip.cs
Comment thread test/Garnet.test/RespVectorSetTests.cs
Comment thread libs/cluster/Session/RespClusterSlotManagementCommands.cs Outdated
Comment thread libs/common/AsyncUtils.cs Outdated
Comment thread hosting/Windows/Garnet.worker/Garnet.worker.csproj Outdated
Comment thread libs/common/Networking/NetworkHandler.cs
@kevin-montrose kevin-montrose requested a review from badrishc April 27, 2026 16:36
@kevin-montrose kevin-montrose merged commit 6481a20 into main Apr 28, 2026
34 checks passed
@kevin-montrose kevin-montrose deleted the users/kmontrose/asyncification branch April 28, 2026 16:30
yuseok-kim-edushare added a commit to yuseok-kim-edushare/garnet that referenced this pull request May 2, 2026
- CI failure about VSTHRD002 with related PR microsoft#1714
yuseok-kim-edushare added a commit to yuseok-kim-edushare/garnet that referenced this pull request May 2, 2026
- To reflect microsoft#1714 PR's Code Changes
: TakeCheckpoint replaced with TakeCheckpointAsync
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants