Skip to content

Add command flags - #97

Merged
thomhurst merged 14 commits into
mainfrom
agent/command-options
Aug 10, 2026
Merged

thomhurst merged 14 commits into
mainfrom
agent/command-options

Conversation

@thomhurst

@thomhurst thomhurst commented Aug 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add RespireCommandFlags with NoRedirect support for raw, catalog, and interpolated command execution
  • add explicit raw and catalog fire-and-forget APIs that discard replies without returning a RespireResult
  • cover cluster no-redirect behavior, fire-and-forget reply discard, and command catalog routing tests

Validation

  • dotnet run --project tests\Respire.Tests\Respire.Tests.csproj --framework net10.0 -- --timeout 120s --maximum-failed-tests 1 --maximum-parallel-tests 1
  • dotnet run --project tests\Respire.Tests\Respire.Tests.csproj --framework net8.0 -- --timeout 120s --maximum-failed-tests 1

Summary by CodeRabbit

  • New Features
    • Added command execution flags for fire-and-forget operations and redirect control.
    • Added cancellation support for raw, catalog, and interpolated commands.
    • Added fire-and-forget execution for raw and catalog commands.
    • Added validation for unsupported command and flag combinations.
    • Improved clustered routing, redirects, shutdown handling, write completion, and telemetry.
  • Tests
    • Expanded coverage for cancellation, blocking commands, redirects, cluster behavior, connection handling, and telemetry.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@thomhurst, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 15 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6c698176-6f5d-40ce-933b-13a6350dbcbe

📥 Commits

Reviewing files that changed from the base of the PR and between 7a1f0f3 and 92a2e77.

📒 Files selected for processing (3)
  • src/Respire/RespireClient.cs
  • tests/Respire.Tests/Networking/CommandCatalogTests.cs
  • tests/Respire.Tests/TelemetryTests.cs
📝 Walkthrough

Walkthrough

The client adds execution flags, fire-and-forget APIs, cancellation overloads, command validation, improved blocking detection, cluster redirect control, telemetry handling, and integration coverage.

Changes

Command execution policies

Layer / File(s) Summary
Command policy contracts
src/Respire/RespireCommandFlags.cs, src/Respire/IRespireClient.cs, src/Respire/RespireCommand.cs, src/Respire/Commands/CommandStructs.cs
Defines execution flags, adds client overloads, and classifies blocking, connection-closing, and script commands.
Flagged command APIs
src/Respire/RespireClient.cs
Adds flag-aware catalog, raw, and interpolated execution. Centralizes parsing, command construction, validation, routing, and fire-and-forget dispatch.
Fire-and-forget write completion
src/Respire/Networking/WriteBuffer.cs, src/Respire/Networking/RespireConnection.cs
Tracks fire-and-forget writes and completes or fails them after transmission, cancellation, or connection abort.
Execution validation and integration tests
tests/Respire.Tests/Networking/*, tests/Respire.Tests/TelemetryTests.cs, tests/Respire.Extensions.Caching.Tests/RespireDistributedCacheTests.cs
Tests redirects, rejected commands, cancellation, reply suppression, connection closure, API forwarding, write completion, and telemetry.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant RespireClient
  participant RedisCluster
  participant RedisNode
  Client->>RespireClient: Execute command with flags
  RespireClient->>RedisCluster: Route command
  RedisCluster->>RedisNode: Send command
  RedisNode-->>RedisCluster: Reply, MOVED, or connection close
  RedisCluster-->>RespireClient: Complete, redirect, or error
  RespireClient-->>Client: Return task result
Loading

Possibly related PRs

Poem

A rabbit sends commands with care,
Flags guide each one everywhere.
Redirects stop when requested so,
Writes complete before they go.
Clusters route and tests approve—
Hop, hop, the new paths move!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding command flags, including NoRedirect support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/command-options

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net8.0)

ℹ️ Execution Details

  • Framework: net8.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: failure
  • Timestamp: 2026-08-09T23:46:13.533Z

Automated integration testing with Redis containers using TUnit

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net10.0)

ℹ️ Execution Details

  • Framework: net10.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: failure
  • Timestamp: 2026-08-09T23:46:30.879Z

Automated integration testing with Redis containers using TUnit

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d3dd065b6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Respire/RespireClient.cs Outdated
return;
}

await SendFireAndForgetAsync(commandValue, cancellationToken).ConfigureAwait(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject blocking raw fire-and-forget commands

When the raw command is an indefinitely blocking verb such as BLPOP key 0, this path bypasses the catalog API's IsBlocking rejection and queues it on a shared multiplexed connection. The fire-and-forget call then completes immediately, while the server blocks the socket; with the default single connection and disabled response watchdog, every subsequent command stalls indefinitely. Reject known blocking raw commands or route them through a cancelable dedicated connection.

Useful? React with 👍 / 👎.

Reject known blocking raw fire-and-forget commands before they reach shared multiplexed connections. Update the IRespireClient test double so the expanded command-options surface builds in all test projects.
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net10.0)

ℹ️ Execution Details

  • Framework: net10.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T00:15:12.625Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net8.0)

ℹ️ Execution Details

  • Framework: net8.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T00:15:28.630Z

Automated integration testing with Redis containers using TUnit

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29ac6ed7d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Respire/RespireClient.cs Outdated
CancellationToken cancellationToken)
{
var (operation, _, commandValue) = CreateRawCommand(command, args);
if (RespireCommand.IsBlocking(operation, commandValue.Arguments))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject raw commands that suppress connection replies

When a raw fire-and-forget command such as CLIENT REPLY OFF or CLIENT REPLY SKIP reaches this check, it is accepted because it is not classified as blocking, even though it changes whether the shared connection emits replies. OFF leaves the connection permanently unable to complete later commands, while SKIP shifts the FIFO reply association after the skipped response, potentially delivering replies to the wrong callers or hanging them. Raw fire-and-forget execution should reject connection-scoped commands just as catalog execution does.

Useful? React with 👍 / 👎.

Comment thread src/Respire/RespireClient.cs Outdated
{
var slot = command.TryGetClusterSlot(out var commandSlot) ? commandSlot : (int?)null;
var connection = await cluster.GetConnectionAsync(slot, cancellationToken).ConfigureAwait(false);
await connection.SendFireAndForgetAsync(in command, cancellationToken).ConfigureAwait(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Process cluster redirects for fire-and-forget commands

When the cached slot owner is stale during cluster migration or resharding, this sends the command to the old node and installs a discard sentinel for its MOVED or ASK reply. Because the router never observes that reply, the command is not retried on the redirected node and the route is not updated, so writes can be silently lost—and repeated fire-and-forget calls can continue going to the wrong node until an ordinary command refreshes the route. The reply should still be processed internally for redirect handling even though no result is returned to the caller.

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net10.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 172.4 μs 11.21 μs 0.61 μs 171.9 μs 173.1 μs 172.2 μs 173.0 μs 1.00 0.00 184 B 1.00
StackExchange_Ping 175.9 μs 8.70 μs 0.48 μs 175.6 μs 176.4 μs 175.6 μs 176.4 μs 1.02 0.00 408 B 2.22
Respire_Set_Small 172.5 μs 9.18 μs 0.50 μs 172.1 μs 173.1 μs 172.3 μs 173.0 μs 1.00 0.00 175 B 0.95
StackExchange_Set_Small 177.4 μs 34.98 μs 1.92 μs 176.2 μs 179.6 μs 176.3 μs 179.3 μs 1.03 0.01 416 B 2.26
Respire_Set_Medium 175.6 μs 13.71 μs 0.75 μs 175.1 μs 176.5 μs 175.3 μs 176.4 μs 1.02 0.00 176 B 0.96
StackExchange_Set_Medium 181.5 μs 31.05 μs 1.70 μs 180.3 μs 183.4 μs 180.6 μs 183.2 μs 1.05 0.01 416 B 2.26
Respire_Set_Large 178.4 μs 15.29 μs 0.84 μs 177.6 μs 179.3 μs 178.3 μs 179.2 μs 1.03 0.01 176 B 0.96
StackExchange_Set_Large 187.0 μs 15.43 μs 0.85 μs 186.1 μs 187.7 μs 187.2 μs 187.7 μs 1.08 0.01 416 B 2.26
Respire_Get 172.3 μs 27.87 μs 1.53 μs 170.6 μs 173.4 μs 173.0 μs 173.3 μs 1.00 0.01 224 B 1.22
StackExchange_Get 175.3 μs 12.37 μs 0.68 μs 174.6 μs 175.9 μs 175.3 μs 175.8 μs 1.02 0.00 424 B 2.30
StackExchange_MGet 177.3 μs 24.72 μs 1.36 μs 176.4 μs 178.8 μs 176.6 μs 178.6 μs 1.03 0.01 656 B 3.57
StackExchange_Pipeline_5_Sets 196.6 μs 47.25 μs 2.59 μs 193.7 μs 198.6 μs 197.5 μs 198.5 μs 1.14 0.01 2888 B 15.70
Respire_Exists 172.3 μs 5.23 μs 0.29 μs 172.1 μs 172.7 μs 172.3 μs 172.6 μs 1.00 0.00 176 B 0.96
StackExchange_Exists 176.2 μs 20.89 μs 1.15 μs 175.1 μs 177.4 μs 176.3 μs 177.3 μs 1.02 0.01 400 B 2.17
Respire_Del 329.9 μs 99.97 μs 5.48 μs 326.4 μs 336.2 μs 327.1 μs 335.3 μs 1.91 0.03 200 B 1.09
StackExchange_Del 339.2 μs 44.88 μs 2.46 μs 336.8 μs 341.7 μs 339.0 μs 341.4 μs 1.97 0.01 648 B 3.52
Respire_Incr 173.8 μs 14.66 μs 0.80 μs 172.9 μs 174.4 μs 174.1 μs 174.4 μs 1.01 0.01 184 B 1.00
StackExchange_Incr 177.0 μs 19.03 μs 1.04 μs 176.3 μs 178.2 μs 176.5 μs 178.0 μs 1.03 0.01 400 B 2.17
Respire_Transaction_2 178.3 μs 17.11 μs 0.94 μs 177.5 μs 179.3 μs 178.0 μs 179.2 μs 1.03 0.01 1064 B 5.78
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error    | StdDev  | Min      | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|---------:|--------:|---------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 172.4 μs | 11.21 μs | 0.61 μs | 171.9 μs | 173.1 μs | 172.2 μs | 173.0 μs |  1.00 |    0.00 |     184 B |        1.00 |
StackExchange_Ping            | 175.9 μs |  8.70 μs | 0.48 μs | 175.6 μs | 176.4 μs | 175.6 μs | 176.4 μs |  1.02 |    0.00 |     408 B |        2.22 |
Respire_Set_Small             | 172.5 μs |  9.18 μs | 0.50 μs | 172.1 μs | 173.1 μs | 172.3 μs | 173.0 μs |  1.00 |    0.00 |     175 B |        0.95 |
StackExchange_Set_Small       | 177.4 μs | 34.98 μs | 1.92 μs | 176.2 μs | 179.6 μs | 176.3 μs | 179.3 μs |  1.03 |    0.01 |     416 B |        2.26 |
Respire_Set_Medium            | 175.6 μs | 13.71 μs | 0.75 μs | 175.1 μs | 176.5 μs | 175.3 μs | 176.4 μs |  1.02 |    0.00 |     176 B |        0.96 |
StackExchange_Set_Medium      | 181.5 μs | 31.05 μs | 1.70 μs | 180.3 μs | 183.4 μs | 180.6 μs | 183.2 μs |  1.05 |    0.01 |     416 B |        2.26 |
Respire_Set_Large             | 178.4 μs | 15.29 μs | 0.84 μs | 177.6 μs | 179.3 μs | 178.3 μs | 179.2 μs |  1.03 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Large       | 187.0 μs | 15.43 μs | 0.85 μs | 186.1 μs | 187.7 μs | 187.2 μs | 187.7 μs |  1.08 |    0.01 |     416 B |        2.26 |
Respire_Get                   | 172.3 μs | 27.87 μs | 1.53 μs | 170.6 μs | 173.4 μs | 173.0 μs | 173.3 μs |  1.00 |    0.01 |     224 B |        1.22 |
StackExchange_Get             | 175.3 μs | 12.37 μs | 0.68 μs | 174.6 μs | 175.9 μs | 175.3 μs | 175.8 μs |  1.02 |    0.00 |     424 B |        2.30 |
StackExchange_MGet            | 177.3 μs | 24.72 μs | 1.36 μs | 176.4 μs | 178.8 μs | 176.6 μs | 178.6 μs |  1.03 |    0.01 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 196.6 μs | 47.25 μs | 2.59 μs | 193.7 μs | 198.6 μs | 197.5 μs | 198.5 μs |  1.14 |    0.01 |    2888 B |       15.70 |
Respire_Exists                | 172.3 μs |  5.23 μs | 0.29 μs | 172.1 μs | 172.7 μs | 172.3 μs | 172.6 μs |  1.00 |    0.00 |     176 B |        0.96 |
StackExchange_Exists          | 176.2 μs | 20.89 μs | 1.15 μs | 175.1 μs | 177.4 μs | 176.3 μs | 177.3 μs |  1.02 |    0.01 |     400 B |        2.17 |
Respire_Del                   | 329.9 μs | 99.97 μs | 5.48 μs | 326.4 μs | 336.2 μs | 327.1 μs | 335.3 μs |  1.91 |    0.03 |     200 B |        1.09 |
StackExchange_Del             | 339.2 μs | 44.88 μs | 2.46 μs | 336.8 μs | 341.7 μs | 339.0 μs | 341.4 μs |  1.97 |    0.01 |     648 B |        3.52 |
Respire_Incr                  | 173.8 μs | 14.66 μs | 0.80 μs | 172.9 μs | 174.4 μs | 174.1 μs | 174.4 μs |  1.01 |    0.01 |     184 B |        1.00 |
StackExchange_Incr            | 177.0 μs | 19.03 μs | 1.04 μs | 176.3 μs | 178.2 μs | 176.5 μs | 178.0 μs |  1.03 |    0.01 |     400 B |        2.17 |
Respire_Transaction_2         | 178.3 μs | 17.11 μs | 0.94 μs | 177.5 μs | 179.3 μs | 178.0 μs | 179.2 μs |  1.03 |    0.01 |    1064 B |        5.78 |

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net8.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 80.90 μs 145.03 μs 7.949 μs 72.72 μs 88.60 μs 81.36 μs 87.88 μs 1.01 0.12 169 B 1.00
StackExchange_Ping 76.49 μs 57.58 μs 3.156 μs 73.59 μs 79.86 μs 76.03 μs 79.47 μs 0.95 0.09 383 B 2.27
Respire_Set_Small 93.98 μs 67.66 μs 3.708 μs 89.82 μs 96.93 μs 95.19 μs 96.76 μs 1.17 0.11 163 B 0.96
StackExchange_Set_Small 77.64 μs 25.60 μs 1.403 μs 76.41 μs 79.17 μs 77.36 μs 78.99 μs 0.97 0.08 384 B 2.27
Respire_Set_Medium 103.77 μs 34.54 μs 1.893 μs 102.02 μs 105.78 μs 103.50 μs 105.55 μs 1.29 0.11 169 B 1.00
StackExchange_Set_Medium 85.14 μs 65.82 μs 3.608 μs 80.98 μs 87.41 μs 87.03 μs 87.37 μs 1.06 0.10 402 B 2.38
Respire_Set_Large 113.38 μs 18.06 μs 0.990 μs 112.44 μs 114.41 μs 113.29 μs 114.30 μs 1.41 0.12 174 B 1.03
StackExchange_Set_Large 112.01 μs 17.75 μs 0.973 μs 110.89 μs 112.64 μs 112.49 μs 112.63 μs 1.39 0.12 410 B 2.43
Respire_Get 96.17 μs 80.54 μs 4.415 μs 91.07 μs 98.75 μs 98.68 μs 98.74 μs 1.20 0.11 207 B 1.22
StackExchange_Get 86.78 μs 19.70 μs 1.080 μs 85.66 μs 87.82 μs 86.87 μs 87.72 μs 1.08 0.09 394 B 2.33
StackExchange_MGet 82.92 μs 69.28 μs 3.798 μs 79.15 μs 86.75 μs 82.85 μs 86.36 μs 1.03 0.10 630 B 3.73
StackExchange_Pipeline_5_Sets 120.47 μs 43.42 μs 2.380 μs 118.16 μs 122.91 μs 120.35 μs 122.66 μs 1.50 0.13 2885 B 17.07
Respire_Exists 93.64 μs 77.41 μs 4.243 μs 88.79 μs 96.67 μs 95.46 μs 96.55 μs 1.17 0.11 171 B 1.01
StackExchange_Exists 83.44 μs 57.58 μs 3.156 μs 80.14 μs 86.43 μs 83.73 μs 86.16 μs 1.04 0.10 385 B 2.28
Respire_Del 187.25 μs 69.06 μs 3.785 μs 183.53 μs 191.10 μs 187.12 μs 190.70 μs 2.33 0.21 199 B 1.18
StackExchange_Del 164.70 μs 39.20 μs 2.148 μs 162.33 μs 166.53 μs 165.24 μs 166.40 μs 2.05 0.18 642 B 3.80
Respire_Incr 99.81 μs 145.80 μs 7.992 μs 92.01 μs 107.98 μs 99.44 μs 107.13 μs 1.24 0.14 182 B 1.08
StackExchange_Incr 82.87 μs 111.37 μs 6.105 μs 75.84 μs 86.82 μs 85.95 μs 86.73 μs 1.03 0.11 373 B 2.21
Respire_Transaction_2 101.11 μs 131.33 μs 7.198 μs 96.26 μs 109.38 μs 97.68 μs 108.21 μs 1.26 0.13 1056 B 6.25
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean      | Error     | StdDev   | Min       | Max       | Median    | P95       | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |----------:|----------:|---------:|----------:|----------:|----------:|----------:|------:|--------:|----------:|------------:|
Respire_Ping                  |  80.90 μs | 145.03 μs | 7.949 μs |  72.72 μs |  88.60 μs |  81.36 μs |  87.88 μs |  1.01 |    0.12 |     169 B |        1.00 |
StackExchange_Ping            |  76.49 μs |  57.58 μs | 3.156 μs |  73.59 μs |  79.86 μs |  76.03 μs |  79.47 μs |  0.95 |    0.09 |     383 B |        2.27 |
Respire_Set_Small             |  93.98 μs |  67.66 μs | 3.708 μs |  89.82 μs |  96.93 μs |  95.19 μs |  96.76 μs |  1.17 |    0.11 |     163 B |        0.96 |
StackExchange_Set_Small       |  77.64 μs |  25.60 μs | 1.403 μs |  76.41 μs |  79.17 μs |  77.36 μs |  78.99 μs |  0.97 |    0.08 |     384 B |        2.27 |
Respire_Set_Medium            | 103.77 μs |  34.54 μs | 1.893 μs | 102.02 μs | 105.78 μs | 103.50 μs | 105.55 μs |  1.29 |    0.11 |     169 B |        1.00 |
StackExchange_Set_Medium      |  85.14 μs |  65.82 μs | 3.608 μs |  80.98 μs |  87.41 μs |  87.03 μs |  87.37 μs |  1.06 |    0.10 |     402 B |        2.38 |
Respire_Set_Large             | 113.38 μs |  18.06 μs | 0.990 μs | 112.44 μs | 114.41 μs | 113.29 μs | 114.30 μs |  1.41 |    0.12 |     174 B |        1.03 |
StackExchange_Set_Large       | 112.01 μs |  17.75 μs | 0.973 μs | 110.89 μs | 112.64 μs | 112.49 μs | 112.63 μs |  1.39 |    0.12 |     410 B |        2.43 |
Respire_Get                   |  96.17 μs |  80.54 μs | 4.415 μs |  91.07 μs |  98.75 μs |  98.68 μs |  98.74 μs |  1.20 |    0.11 |     207 B |        1.22 |
StackExchange_Get             |  86.78 μs |  19.70 μs | 1.080 μs |  85.66 μs |  87.82 μs |  86.87 μs |  87.72 μs |  1.08 |    0.09 |     394 B |        2.33 |
StackExchange_MGet            |  82.92 μs |  69.28 μs | 3.798 μs |  79.15 μs |  86.75 μs |  82.85 μs |  86.36 μs |  1.03 |    0.10 |     630 B |        3.73 |
StackExchange_Pipeline_5_Sets | 120.47 μs |  43.42 μs | 2.380 μs | 118.16 μs | 122.91 μs | 120.35 μs | 122.66 μs |  1.50 |    0.13 |    2885 B |       17.07 |
Respire_Exists                |  93.64 μs |  77.41 μs | 4.243 μs |  88.79 μs |  96.67 μs |  95.46 μs |  96.55 μs |  1.17 |    0.11 |     171 B |        1.01 |
StackExchange_Exists          |  83.44 μs |  57.58 μs | 3.156 μs |  80.14 μs |  86.43 μs |  83.73 μs |  86.16 μs |  1.04 |    0.10 |     385 B |        2.28 |
Respire_Del                   | 187.25 μs |  69.06 μs | 3.785 μs | 183.53 μs | 191.10 μs | 187.12 μs | 190.70 μs |  2.33 |    0.21 |     199 B |        1.18 |
StackExchange_Del             | 164.70 μs |  39.20 μs | 2.148 μs | 162.33 μs | 166.53 μs | 165.24 μs | 166.40 μs |  2.05 |    0.18 |     642 B |        3.80 |
Respire_Incr                  |  99.81 μs | 145.80 μs | 7.992 μs |  92.01 μs | 107.98 μs |  99.44 μs | 107.13 μs |  1.24 |    0.14 |     182 B |        1.08 |
StackExchange_Incr            |  82.87 μs | 111.37 μs | 6.105 μs |  75.84 μs |  86.82 μs |  85.95 μs |  86.73 μs |  1.03 |    0.11 |     373 B |        2.21 |
Respire_Transaction_2         | 101.11 μs | 131.33 μs | 7.198 μs |  96.26 μs | 109.38 μs |  97.68 μs | 108.21 μs |  1.26 |    0.13 |    1056 B |        6.25 |

Reject connection-affinity raw commands before they reach shared connections. In cluster mode, consume replies through the redirect loop before discarding them so MOVED and ASK writes reach the correct node.
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net10.0)

ℹ️ Execution Details

  • Framework: net10.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T00:26:53.056Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net8.0)

ℹ️ Execution Details

  • Framework: net8.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T00:27:06.603Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net8.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 121.7 μs 130.86 μs 7.17 μs 113.52 μs 127.1 μs 124.4 μs 126.8 μs 1.00 0.07 175 B 1.00
StackExchange_Ping 112.1 μs 56.11 μs 3.08 μs 109.16 μs 115.3 μs 111.9 μs 115.0 μs 0.92 0.05 398 B 2.27
Respire_Set_Small 131.7 μs 4.17 μs 0.23 μs 131.50 μs 132.0 μs 131.7 μs 131.9 μs 1.09 0.06 174 B 0.99
StackExchange_Set_Small 121.9 μs 49.66 μs 2.72 μs 119.90 μs 125.0 μs 120.7 μs 124.5 μs 1.00 0.06 409 B 2.34
Respire_Set_Medium 128.5 μs 135.79 μs 7.44 μs 120.85 μs 135.7 μs 129.1 μs 135.0 μs 1.06 0.08 173 B 0.99
StackExchange_Set_Medium 121.6 μs 151.90 μs 8.33 μs 113.59 μs 130.2 μs 121.0 μs 129.3 μs 1.00 0.08 404 B 2.31
Respire_Set_Large 148.9 μs 28.18 μs 1.54 μs 147.41 μs 150.5 μs 148.8 μs 150.3 μs 1.23 0.07 175 B 1.00
StackExchange_Set_Large 141.5 μs 46.01 μs 2.52 μs 138.71 μs 143.5 μs 142.4 μs 143.4 μs 1.17 0.06 414 B 2.37
Respire_Get 133.2 μs 33.28 μs 1.82 μs 131.38 μs 135.0 μs 133.2 μs 134.8 μs 1.10 0.06 209 B 1.19
StackExchange_Get 111.8 μs 207.83 μs 11.39 μs 99.24 μs 121.5 μs 114.7 μs 120.8 μs 0.92 0.09 418 B 2.39
StackExchange_MGet 119.9 μs 170.60 μs 9.35 μs 112.24 μs 130.3 μs 117.2 μs 129.0 μs 0.99 0.08 644 B 3.68
StackExchange_Pipeline_5_Sets 162.0 μs 56.49 μs 3.10 μs 158.52 μs 164.5 μs 162.9 μs 164.3 μs 1.33 0.07 2887 B 16.50
Respire_Exists 136.4 μs 22.04 μs 1.21 μs 135.33 μs 137.7 μs 136.1 μs 137.5 μs 1.12 0.06 170 B 0.97
StackExchange_Exists 110.8 μs 153.49 μs 8.41 μs 103.27 μs 119.9 μs 109.3 μs 118.8 μs 0.91 0.08 385 B 2.20
Respire_Del 250.0 μs 146.80 μs 8.05 μs 243.07 μs 258.8 μs 248.2 μs 257.8 μs 2.06 0.12 199 B 1.14
StackExchange_Del 219.9 μs 164.73 μs 9.03 μs 209.96 μs 227.6 μs 222.2 μs 227.0 μs 1.81 0.12 644 B 3.68
Respire_Incr 131.4 μs 149.86 μs 8.21 μs 122.20 μs 138.0 μs 134.1 μs 137.6 μs 1.08 0.08 181 B 1.03
StackExchange_Incr 108.3 μs 195.57 μs 10.72 μs 95.97 μs 115.1 μs 113.9 μs 115.0 μs 0.89 0.09 382 B 2.18
Respire_Transaction_2 140.3 μs 101.73 μs 5.58 μs 135.23 μs 146.3 μs 139.5 μs 145.6 μs 1.16 0.07 1056 B 6.03
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error     | StdDev   | Min       | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|----------:|---------:|----------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 121.7 μs | 130.86 μs |  7.17 μs | 113.52 μs | 127.1 μs | 124.4 μs | 126.8 μs |  1.00 |    0.07 |     175 B |        1.00 |
StackExchange_Ping            | 112.1 μs |  56.11 μs |  3.08 μs | 109.16 μs | 115.3 μs | 111.9 μs | 115.0 μs |  0.92 |    0.05 |     398 B |        2.27 |
Respire_Set_Small             | 131.7 μs |   4.17 μs |  0.23 μs | 131.50 μs | 132.0 μs | 131.7 μs | 131.9 μs |  1.09 |    0.06 |     174 B |        0.99 |
StackExchange_Set_Small       | 121.9 μs |  49.66 μs |  2.72 μs | 119.90 μs | 125.0 μs | 120.7 μs | 124.5 μs |  1.00 |    0.06 |     409 B |        2.34 |
Respire_Set_Medium            | 128.5 μs | 135.79 μs |  7.44 μs | 120.85 μs | 135.7 μs | 129.1 μs | 135.0 μs |  1.06 |    0.08 |     173 B |        0.99 |
StackExchange_Set_Medium      | 121.6 μs | 151.90 μs |  8.33 μs | 113.59 μs | 130.2 μs | 121.0 μs | 129.3 μs |  1.00 |    0.08 |     404 B |        2.31 |
Respire_Set_Large             | 148.9 μs |  28.18 μs |  1.54 μs | 147.41 μs | 150.5 μs | 148.8 μs | 150.3 μs |  1.23 |    0.07 |     175 B |        1.00 |
StackExchange_Set_Large       | 141.5 μs |  46.01 μs |  2.52 μs | 138.71 μs | 143.5 μs | 142.4 μs | 143.4 μs |  1.17 |    0.06 |     414 B |        2.37 |
Respire_Get                   | 133.2 μs |  33.28 μs |  1.82 μs | 131.38 μs | 135.0 μs | 133.2 μs | 134.8 μs |  1.10 |    0.06 |     209 B |        1.19 |
StackExchange_Get             | 111.8 μs | 207.83 μs | 11.39 μs |  99.24 μs | 121.5 μs | 114.7 μs | 120.8 μs |  0.92 |    0.09 |     418 B |        2.39 |
StackExchange_MGet            | 119.9 μs | 170.60 μs |  9.35 μs | 112.24 μs | 130.3 μs | 117.2 μs | 129.0 μs |  0.99 |    0.08 |     644 B |        3.68 |
StackExchange_Pipeline_5_Sets | 162.0 μs |  56.49 μs |  3.10 μs | 158.52 μs | 164.5 μs | 162.9 μs | 164.3 μs |  1.33 |    0.07 |    2887 B |       16.50 |
Respire_Exists                | 136.4 μs |  22.04 μs |  1.21 μs | 135.33 μs | 137.7 μs | 136.1 μs | 137.5 μs |  1.12 |    0.06 |     170 B |        0.97 |
StackExchange_Exists          | 110.8 μs | 153.49 μs |  8.41 μs | 103.27 μs | 119.9 μs | 109.3 μs | 118.8 μs |  0.91 |    0.08 |     385 B |        2.20 |
Respire_Del                   | 250.0 μs | 146.80 μs |  8.05 μs | 243.07 μs | 258.8 μs | 248.2 μs | 257.8 μs |  2.06 |    0.12 |     199 B |        1.14 |
StackExchange_Del             | 219.9 μs | 164.73 μs |  9.03 μs | 209.96 μs | 227.6 μs | 222.2 μs | 227.0 μs |  1.81 |    0.12 |     644 B |        3.68 |
Respire_Incr                  | 131.4 μs | 149.86 μs |  8.21 μs | 122.20 μs | 138.0 μs | 134.1 μs | 137.6 μs |  1.08 |    0.08 |     181 B |        1.03 |
StackExchange_Incr            | 108.3 μs | 195.57 μs | 10.72 μs |  95.97 μs | 115.1 μs | 113.9 μs | 115.0 μs |  0.89 |    0.09 |     382 B |        2.18 |
Respire_Transaction_2         | 140.3 μs | 101.73 μs |  5.58 μs | 135.23 μs | 146.3 μs | 139.5 μs | 145.6 μs |  1.16 |    0.07 |    1056 B |        6.03 |

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net10.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 183.0 μs 45.45 μs 2.49 μs 180.8 μs 185.7 μs 182.6 μs 185.4 μs 1.00 0.02 184 B 1.00
StackExchange_Ping 185.3 μs 48.40 μs 2.65 μs 182.7 μs 188.0 μs 185.3 μs 187.7 μs 1.01 0.02 408 B 2.22
Respire_Set_Small 183.2 μs 5.38 μs 0.29 μs 182.9 μs 183.4 μs 183.3 μs 183.4 μs 1.00 0.01 176 B 0.96
StackExchange_Set_Small 184.3 μs 46.90 μs 2.57 μs 181.6 μs 186.7 μs 184.5 μs 186.5 μs 1.01 0.02 416 B 2.26
Respire_Set_Medium 183.2 μs 25.64 μs 1.41 μs 181.6 μs 184.2 μs 183.8 μs 184.1 μs 1.00 0.01 176 B 0.96
StackExchange_Set_Medium 189.0 μs 19.99 μs 1.10 μs 188.1 μs 190.2 μs 188.7 μs 190.1 μs 1.03 0.01 416 B 2.26
Respire_Set_Large 192.1 μs 32.45 μs 1.78 μs 191.0 μs 194.2 μs 191.3 μs 193.9 μs 1.05 0.01 176 B 0.96
StackExchange_Set_Large 197.0 μs 24.85 μs 1.36 μs 195.6 μs 198.4 μs 197.1 μs 198.2 μs 1.08 0.01 416 B 2.26
Respire_Get 182.3 μs 14.93 μs 0.82 μs 181.5 μs 183.1 μs 182.2 μs 183.0 μs 1.00 0.01 224 B 1.22
StackExchange_Get 184.6 μs 32.48 μs 1.78 μs 183.2 μs 186.6 μs 184.0 μs 186.3 μs 1.01 0.01 421 B 2.29
StackExchange_MGet 188.6 μs 11.38 μs 0.62 μs 188.0 μs 189.2 μs 188.4 μs 189.2 μs 1.03 0.01 656 B 3.57
StackExchange_Pipeline_5_Sets 226.4 μs 346.72 μs 19.01 μs 211.3 μs 247.8 μs 220.2 μs 245.0 μs 1.24 0.09 2888 B 15.70
Respire_Exists 181.1 μs 19.37 μs 1.06 μs 179.9 μs 181.7 μs 181.7 μs 181.7 μs 0.99 0.01 176 B 0.96
StackExchange_Exists 185.0 μs 23.83 μs 1.31 μs 183.5 μs 186.1 μs 185.3 μs 186.0 μs 1.01 0.01 399 B 2.17
Respire_Del 354.2 μs 9.77 μs 0.54 μs 353.6 μs 354.6 μs 354.4 μs 354.6 μs 1.94 0.02 200 B 1.09
StackExchange_Del 360.4 μs 42.34 μs 2.32 μs 357.8 μs 362.1 μs 361.4 μs 362.0 μs 1.97 0.03 648 B 3.52
Respire_Incr 182.0 μs 6.16 μs 0.34 μs 181.6 μs 182.2 μs 182.1 μs 182.2 μs 0.99 0.01 184 B 1.00
StackExchange_Incr 184.7 μs 7.56 μs 0.41 μs 184.2 μs 185.0 μs 184.8 μs 185.0 μs 1.01 0.01 399 B 2.17
Respire_Transaction_2 188.1 μs 38.88 μs 2.13 μs 185.7 μs 189.7 μs 189.0 μs 189.6 μs 1.03 0.02 1064 B 5.78
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error     | StdDev   | Min      | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|----------:|---------:|---------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 183.0 μs |  45.45 μs |  2.49 μs | 180.8 μs | 185.7 μs | 182.6 μs | 185.4 μs |  1.00 |    0.02 |     184 B |        1.00 |
StackExchange_Ping            | 185.3 μs |  48.40 μs |  2.65 μs | 182.7 μs | 188.0 μs | 185.3 μs | 187.7 μs |  1.01 |    0.02 |     408 B |        2.22 |
Respire_Set_Small             | 183.2 μs |   5.38 μs |  0.29 μs | 182.9 μs | 183.4 μs | 183.3 μs | 183.4 μs |  1.00 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Small       | 184.3 μs |  46.90 μs |  2.57 μs | 181.6 μs | 186.7 μs | 184.5 μs | 186.5 μs |  1.01 |    0.02 |     416 B |        2.26 |
Respire_Set_Medium            | 183.2 μs |  25.64 μs |  1.41 μs | 181.6 μs | 184.2 μs | 183.8 μs | 184.1 μs |  1.00 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Medium      | 189.0 μs |  19.99 μs |  1.10 μs | 188.1 μs | 190.2 μs | 188.7 μs | 190.1 μs |  1.03 |    0.01 |     416 B |        2.26 |
Respire_Set_Large             | 192.1 μs |  32.45 μs |  1.78 μs | 191.0 μs | 194.2 μs | 191.3 μs | 193.9 μs |  1.05 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Large       | 197.0 μs |  24.85 μs |  1.36 μs | 195.6 μs | 198.4 μs | 197.1 μs | 198.2 μs |  1.08 |    0.01 |     416 B |        2.26 |
Respire_Get                   | 182.3 μs |  14.93 μs |  0.82 μs | 181.5 μs | 183.1 μs | 182.2 μs | 183.0 μs |  1.00 |    0.01 |     224 B |        1.22 |
StackExchange_Get             | 184.6 μs |  32.48 μs |  1.78 μs | 183.2 μs | 186.6 μs | 184.0 μs | 186.3 μs |  1.01 |    0.01 |     421 B |        2.29 |
StackExchange_MGet            | 188.6 μs |  11.38 μs |  0.62 μs | 188.0 μs | 189.2 μs | 188.4 μs | 189.2 μs |  1.03 |    0.01 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 226.4 μs | 346.72 μs | 19.01 μs | 211.3 μs | 247.8 μs | 220.2 μs | 245.0 μs |  1.24 |    0.09 |    2888 B |       15.70 |
Respire_Exists                | 181.1 μs |  19.37 μs |  1.06 μs | 179.9 μs | 181.7 μs | 181.7 μs | 181.7 μs |  0.99 |    0.01 |     176 B |        0.96 |
StackExchange_Exists          | 185.0 μs |  23.83 μs |  1.31 μs | 183.5 μs | 186.1 μs | 185.3 μs | 186.0 μs |  1.01 |    0.01 |     399 B |        2.17 |
Respire_Del                   | 354.2 μs |   9.77 μs |  0.54 μs | 353.6 μs | 354.6 μs | 354.4 μs | 354.6 μs |  1.94 |    0.02 |     200 B |        1.09 |
StackExchange_Del             | 360.4 μs |  42.34 μs |  2.32 μs | 357.8 μs | 362.1 μs | 361.4 μs | 362.0 μs |  1.97 |    0.03 |     648 B |        3.52 |
Respire_Incr                  | 182.0 μs |   6.16 μs |  0.34 μs | 181.6 μs | 182.2 μs | 182.1 μs | 182.2 μs |  0.99 |    0.01 |     184 B |        1.00 |
StackExchange_Incr            | 184.7 μs |   7.56 μs |  0.41 μs | 184.2 μs | 185.0 μs | 184.8 μs | 185.0 μs |  1.01 |    0.01 |     399 B |        2.17 |
Respire_Transaction_2         | 188.1 μs |  38.88 μs |  2.13 μs | 185.7 μs | 189.7 μs | 189.0 μs | 189.6 μs |  1.03 |    0.02 |    1064 B |        5.78 |

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c2d77f47ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +858 to +860
using var response = await SendClusterAsync(
operation, cluster, command, cancellationToken)
.ConfigureAwait(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don't await a reply from successful cluster SHUTDOWN

In cluster mode, fire-and-forget SHUTDOWN reaches this path because it is neither connection-scoped nor blocking, but a successful Redis shutdown closes the connection without returning a reply. Awaiting SendClusterAsync therefore completes with RespireConnectionException, which is not caught here, even though the command succeeded; the same fire-and-forget call in non-cluster mode completes after enqueueing. Handle no-reply commands such as SHUTDOWN without awaiting a response, or otherwise suppress their expected connection closure.

Useful? React with 👍 / 👎.

Keep SHUTDOWN on the enqueue-only cluster path because successful shutdown closes the socket without a reply. Ordinary fire-and-forget commands still consume replies for MOVED and ASK handling.
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net10.0)

ℹ️ Execution Details

  • Framework: net10.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T00:40:53.502Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net8.0)

ℹ️ Execution Details

  • Framework: net8.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T00:41:12.313Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net8.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio Allocated Alloc Ratio
Respire_Ping 170.9 μs 9.43 μs 0.52 μs 170.3 μs 171.2 μs 171.1 μs 171.2 μs 1.00 184 B 1.00
StackExchange_Ping 175.1 μs 19.38 μs 1.06 μs 174.4 μs 176.3 μs 174.5 μs 176.1 μs 1.02 408 B 2.22
Respire_Set_Small 171.8 μs 19.48 μs 1.07 μs 170.8 μs 172.9 μs 171.5 μs 172.8 μs 1.01 176 B 0.96
StackExchange_Set_Small 177.5 μs 21.46 μs 1.18 μs 176.2 μs 178.5 μs 177.7 μs 178.5 μs 1.04 416 B 2.26
Respire_Set_Medium 171.7 μs 30.12 μs 1.65 μs 169.8 μs 173.0 μs 172.3 μs 172.9 μs 1.00 176 B 0.96
StackExchange_Set_Medium 179.7 μs 33.98 μs 1.86 μs 177.7 μs 181.4 μs 180.1 μs 181.3 μs 1.05 416 B 2.26
Respire_Set_Large 176.7 μs 5.42 μs 0.30 μs 176.4 μs 176.9 μs 176.9 μs 176.9 μs 1.03 176 B 0.96
StackExchange_Set_Large 186.6 μs 6.84 μs 0.37 μs 186.4 μs 187.0 μs 186.4 μs 187.0 μs 1.09 414 B 2.25
Respire_Get 173.2 μs 9.70 μs 0.53 μs 172.7 μs 173.7 μs 173.0 μs 173.7 μs 1.01 224 B 1.22
StackExchange_Get 176.7 μs 33.83 μs 1.85 μs 174.6 μs 178.0 μs 177.4 μs 178.0 μs 1.03 424 B 2.30
StackExchange_MGet 177.4 μs 19.08 μs 1.05 μs 176.6 μs 178.6 μs 177.0 μs 178.4 μs 1.04 656 B 3.57
StackExchange_Pipeline_5_Sets 195.5 μs 40.64 μs 2.23 μs 193.9 μs 198.1 μs 194.7 μs 197.7 μs 1.14 2888 B 15.70
Respire_Exists 170.3 μs 6.98 μs 0.38 μs 169.8 μs 170.6 μs 170.3 μs 170.6 μs 1.00 176 B 0.96
StackExchange_Exists 175.7 μs 4.95 μs 0.27 μs 175.4 μs 176.0 μs 175.8 μs 176.0 μs 1.03 400 B 2.17
Respire_Del 327.9 μs 35.05 μs 1.92 μs 325.7 μs 329.2 μs 328.7 μs 329.2 μs 1.92 200 B 1.09
StackExchange_Del 334.6 μs 15.94 μs 0.87 μs 333.7 μs 335.4 μs 334.8 μs 335.4 μs 1.96 648 B 3.52
Respire_Incr 170.6 μs 24.47 μs 1.34 μs 169.2 μs 171.8 μs 170.8 μs 171.7 μs 1.00 184 B 1.00
StackExchange_Incr 177.2 μs 19.97 μs 1.09 μs 176.1 μs 178.3 μs 177.1 μs 178.2 μs 1.04 400 B 2.17
Respire_Transaction_2 174.6 μs 30.12 μs 1.65 μs 172.9 μs 176.2 μs 174.7 μs 176.0 μs 1.02 1064 B 5.78
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error    | StdDev  | Min      | Max      | Median   | P95      | Ratio | Allocated | Alloc Ratio |
------------------------------ |---------:|---------:|--------:|---------:|---------:|---------:|---------:|------:|----------:|------------:|
Respire_Ping                  | 170.9 μs |  9.43 μs | 0.52 μs | 170.3 μs | 171.2 μs | 171.1 μs | 171.2 μs |  1.00 |     184 B |        1.00 |
StackExchange_Ping            | 175.1 μs | 19.38 μs | 1.06 μs | 174.4 μs | 176.3 μs | 174.5 μs | 176.1 μs |  1.02 |     408 B |        2.22 |
Respire_Set_Small             | 171.8 μs | 19.48 μs | 1.07 μs | 170.8 μs | 172.9 μs | 171.5 μs | 172.8 μs |  1.01 |     176 B |        0.96 |
StackExchange_Set_Small       | 177.5 μs | 21.46 μs | 1.18 μs | 176.2 μs | 178.5 μs | 177.7 μs | 178.5 μs |  1.04 |     416 B |        2.26 |
Respire_Set_Medium            | 171.7 μs | 30.12 μs | 1.65 μs | 169.8 μs | 173.0 μs | 172.3 μs | 172.9 μs |  1.00 |     176 B |        0.96 |
StackExchange_Set_Medium      | 179.7 μs | 33.98 μs | 1.86 μs | 177.7 μs | 181.4 μs | 180.1 μs | 181.3 μs |  1.05 |     416 B |        2.26 |
Respire_Set_Large             | 176.7 μs |  5.42 μs | 0.30 μs | 176.4 μs | 176.9 μs | 176.9 μs | 176.9 μs |  1.03 |     176 B |        0.96 |
StackExchange_Set_Large       | 186.6 μs |  6.84 μs | 0.37 μs | 186.4 μs | 187.0 μs | 186.4 μs | 187.0 μs |  1.09 |     414 B |        2.25 |
Respire_Get                   | 173.2 μs |  9.70 μs | 0.53 μs | 172.7 μs | 173.7 μs | 173.0 μs | 173.7 μs |  1.01 |     224 B |        1.22 |
StackExchange_Get             | 176.7 μs | 33.83 μs | 1.85 μs | 174.6 μs | 178.0 μs | 177.4 μs | 178.0 μs |  1.03 |     424 B |        2.30 |
StackExchange_MGet            | 177.4 μs | 19.08 μs | 1.05 μs | 176.6 μs | 178.6 μs | 177.0 μs | 178.4 μs |  1.04 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 195.5 μs | 40.64 μs | 2.23 μs | 193.9 μs | 198.1 μs | 194.7 μs | 197.7 μs |  1.14 |    2888 B |       15.70 |
Respire_Exists                | 170.3 μs |  6.98 μs | 0.38 μs | 169.8 μs | 170.6 μs | 170.3 μs | 170.6 μs |  1.00 |     176 B |        0.96 |
StackExchange_Exists          | 175.7 μs |  4.95 μs | 0.27 μs | 175.4 μs | 176.0 μs | 175.8 μs | 176.0 μs |  1.03 |     400 B |        2.17 |
Respire_Del                   | 327.9 μs | 35.05 μs | 1.92 μs | 325.7 μs | 329.2 μs | 328.7 μs | 329.2 μs |  1.92 |     200 B |        1.09 |
StackExchange_Del             | 334.6 μs | 15.94 μs | 0.87 μs | 333.7 μs | 335.4 μs | 334.8 μs | 335.4 μs |  1.96 |     648 B |        3.52 |
Respire_Incr                  | 170.6 μs | 24.47 μs | 1.34 μs | 169.2 μs | 171.8 μs | 170.8 μs | 171.7 μs |  1.00 |     184 B |        1.00 |
StackExchange_Incr            | 177.2 μs | 19.97 μs | 1.09 μs | 176.1 μs | 178.3 μs | 177.1 μs | 178.2 μs |  1.04 |     400 B |        2.17 |
Respire_Transaction_2         | 174.6 μs | 30.12 μs | 1.65 μs | 172.9 μs | 176.2 μs | 174.7 μs | 176.0 μs |  1.02 |    1064 B |        5.78 |

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net10.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.59GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 182.3 μs 3.70 μs 0.20 μs 182.0 μs 182.4 μs 182.3 μs 182.4 μs 1.00 0.00 184 B 1.00
StackExchange_Ping 184.3 μs 32.32 μs 1.77 μs 182.7 μs 186.2 μs 184.0 μs 185.9 μs 1.01 0.01 408 B 2.22
Respire_Set_Small 183.1 μs 16.49 μs 0.90 μs 182.1 μs 183.8 μs 183.4 μs 183.8 μs 1.00 0.00 176 B 0.96
StackExchange_Set_Small 186.4 μs 29.79 μs 1.63 μs 184.5 μs 187.5 μs 187.1 μs 187.5 μs 1.02 0.01 415 B 2.26
Respire_Set_Medium 184.1 μs 14.70 μs 0.81 μs 183.2 μs 184.6 μs 184.5 μs 184.6 μs 1.01 0.00 176 B 0.96
StackExchange_Set_Medium 188.8 μs 11.74 μs 0.64 μs 188.0 μs 189.2 μs 189.1 μs 189.2 μs 1.04 0.00 416 B 2.26
Respire_Set_Large 194.0 μs 9.22 μs 0.51 μs 193.6 μs 194.5 μs 193.8 μs 194.4 μs 1.06 0.00 176 B 0.96
StackExchange_Set_Large 196.3 μs 38.36 μs 2.10 μs 193.9 μs 197.5 μs 197.5 μs 197.5 μs 1.08 0.01 416 B 2.26
Respire_Get 182.9 μs 2.04 μs 0.11 μs 182.8 μs 183.0 μs 182.9 μs 183.0 μs 1.00 0.00 224 B 1.22
StackExchange_Get 187.5 μs 24.42 μs 1.34 μs 186.1 μs 188.7 μs 187.7 μs 188.6 μs 1.03 0.01 424 B 2.30
StackExchange_MGet 188.9 μs 26.81 μs 1.47 μs 187.4 μs 190.3 μs 188.9 μs 190.2 μs 1.04 0.01 656 B 3.57
StackExchange_Pipeline_5_Sets 230.5 μs 281.86 μs 15.45 μs 214.8 μs 245.7 μs 230.9 μs 244.2 μs 1.26 0.07 2888 B 15.70
Respire_Exists 181.2 μs 23.93 μs 1.31 μs 180.2 μs 182.7 μs 180.8 μs 182.5 μs 0.99 0.01 176 B 0.96
StackExchange_Exists 186.0 μs 29.56 μs 1.62 μs 184.2 μs 187.3 μs 186.6 μs 187.2 μs 1.02 0.01 400 B 2.17
Respire_Del 354.4 μs 11.23 μs 0.62 μs 353.8 μs 355.0 μs 354.4 μs 355.0 μs 1.94 0.00 200 B 1.09
StackExchange_Del 360.0 μs 39.17 μs 2.15 μs 358.7 μs 362.5 μs 358.9 μs 362.2 μs 1.98 0.01 648 B 3.52
Respire_Incr 182.6 μs 26.67 μs 1.46 μs 181.0 μs 183.9 μs 182.9 μs 183.8 μs 1.00 0.01 184 B 1.00
StackExchange_Incr 188.5 μs 40.56 μs 2.22 μs 186.4 μs 190.8 μs 188.3 μs 190.6 μs 1.03 0.01 400 B 2.17
Respire_Transaction_2 190.3 μs 40.18 μs 2.20 μs 187.7 μs 191.7 μs 191.4 μs 191.7 μs 1.04 0.01 1064 B 5.78
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.59GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error     | StdDev   | Min      | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|----------:|---------:|---------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 182.3 μs |   3.70 μs |  0.20 μs | 182.0 μs | 182.4 μs | 182.3 μs | 182.4 μs |  1.00 |    0.00 |     184 B |        1.00 |
StackExchange_Ping            | 184.3 μs |  32.32 μs |  1.77 μs | 182.7 μs | 186.2 μs | 184.0 μs | 185.9 μs |  1.01 |    0.01 |     408 B |        2.22 |
Respire_Set_Small             | 183.1 μs |  16.49 μs |  0.90 μs | 182.1 μs | 183.8 μs | 183.4 μs | 183.8 μs |  1.00 |    0.00 |     176 B |        0.96 |
StackExchange_Set_Small       | 186.4 μs |  29.79 μs |  1.63 μs | 184.5 μs | 187.5 μs | 187.1 μs | 187.5 μs |  1.02 |    0.01 |     415 B |        2.26 |
Respire_Set_Medium            | 184.1 μs |  14.70 μs |  0.81 μs | 183.2 μs | 184.6 μs | 184.5 μs | 184.6 μs |  1.01 |    0.00 |     176 B |        0.96 |
StackExchange_Set_Medium      | 188.8 μs |  11.74 μs |  0.64 μs | 188.0 μs | 189.2 μs | 189.1 μs | 189.2 μs |  1.04 |    0.00 |     416 B |        2.26 |
Respire_Set_Large             | 194.0 μs |   9.22 μs |  0.51 μs | 193.6 μs | 194.5 μs | 193.8 μs | 194.4 μs |  1.06 |    0.00 |     176 B |        0.96 |
StackExchange_Set_Large       | 196.3 μs |  38.36 μs |  2.10 μs | 193.9 μs | 197.5 μs | 197.5 μs | 197.5 μs |  1.08 |    0.01 |     416 B |        2.26 |
Respire_Get                   | 182.9 μs |   2.04 μs |  0.11 μs | 182.8 μs | 183.0 μs | 182.9 μs | 183.0 μs |  1.00 |    0.00 |     224 B |        1.22 |
StackExchange_Get             | 187.5 μs |  24.42 μs |  1.34 μs | 186.1 μs | 188.7 μs | 187.7 μs | 188.6 μs |  1.03 |    0.01 |     424 B |        2.30 |
StackExchange_MGet            | 188.9 μs |  26.81 μs |  1.47 μs | 187.4 μs | 190.3 μs | 188.9 μs | 190.2 μs |  1.04 |    0.01 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 230.5 μs | 281.86 μs | 15.45 μs | 214.8 μs | 245.7 μs | 230.9 μs | 244.2 μs |  1.26 |    0.07 |    2888 B |       15.70 |
Respire_Exists                | 181.2 μs |  23.93 μs |  1.31 μs | 180.2 μs | 182.7 μs | 180.8 μs | 182.5 μs |  0.99 |    0.01 |     176 B |        0.96 |
StackExchange_Exists          | 186.0 μs |  29.56 μs |  1.62 μs | 184.2 μs | 187.3 μs | 186.6 μs | 187.2 μs |  1.02 |    0.01 |     400 B |        2.17 |
Respire_Del                   | 354.4 μs |  11.23 μs |  0.62 μs | 353.8 μs | 355.0 μs | 354.4 μs | 355.0 μs |  1.94 |    0.00 |     200 B |        1.09 |
StackExchange_Del             | 360.0 μs |  39.17 μs |  2.15 μs | 358.7 μs | 362.5 μs | 358.9 μs | 362.2 μs |  1.98 |    0.01 |     648 B |        3.52 |
Respire_Incr                  | 182.6 μs |  26.67 μs |  1.46 μs | 181.0 μs | 183.9 μs | 182.9 μs | 183.8 μs |  1.00 |    0.01 |     184 B |        1.00 |
StackExchange_Incr            | 188.5 μs |  40.56 μs |  2.22 μs | 186.4 μs | 190.8 μs | 188.3 μs | 190.6 μs |  1.03 |    0.01 |     400 B |        2.17 |
Respire_Transaction_2         | 190.3 μs |  40.18 μs |  2.20 μs | 187.7 μs | 191.7 μs | 191.4 μs | 191.7 μs |  1.04 |    0.01 |    1064 B |        5.78 |

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Respire/RespireClient.cs (1)

181-187: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

The cluster-wide path drops flags.

ExecuteCatalogAsync validates flags and then forwards them to the blocking, ordinary, and stored-procedure paths. The cluster-wide branch calls SendClusterWideAsync without flags. ExecuteRawAsync at Lines 282-288 and ExecuteInterpolatedAsync at Lines 353-359 have the same gap.

A caller who passes RespireCommandFlags.NoRedirect for a cluster-wide mutation gets no error and no effect. Either forward flags to SendClusterWideAsync, or reject NoRedirect for cluster-wide mutations so the policy is never silently ignored.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Respire/RespireClient.cs` around lines 181 - 187, Update the cluster-wide
mutation branches in ExecuteCatalogAsync, ExecuteRawAsync, and
ExecuteInterpolatedAsync to preserve the validated flags when calling
SendClusterWideAsync; ensure RespireCommandFlags.NoRedirect is either forwarded
and honored or explicitly rejected rather than silently ignored.
🧹 Nitpick comments (6)
src/Respire/Commands/CommandStructs.cs (1)

223-223: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Arguments assumes a single-token verb.

DynamicCommand does not know how many leading tokens form the verb. CreateRawCommand in RespireClient.cs builds tokens as all verb words followed by the caller arguments. For a multi-word command such as "CONFIG SET", Arguments returns ["SET", ...args], so the span includes a verb word.

The only current consumer is ValidateRawFireAndForgetCommand, which scans for a BLOCK argument. No multi-word verb is currently classified as BlockingWhenRequested, so no defect is reachable today. The contract is still wrong and will break if a multi-word blocking verb is added, or if another consumer treats Arguments as caller-supplied arguments only.

Store the argument start index in DynamicCommand, or pass the argument span explicitly at the call site in ExecuteRawFireAndForgetAsync.

♻️ Proposed change: carry the argument start index
-internal readonly struct DynamicCommand(RespireValue[] tokens, int routingKeyIndex) : IRespCommand
+internal readonly struct DynamicCommand(RespireValue[] tokens, int routingKeyIndex, int firstArgumentIndex = 1) : IRespCommand
 {
-    internal ReadOnlySpan<RespireValue> Arguments => tokens.AsSpan(1);
+    internal ReadOnlySpan<RespireValue> Arguments => tokens.AsSpan(firstArgumentIndex);

Then pass words.Length from CreateRawCommand.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Respire/Commands/CommandStructs.cs` at line 223, Update DynamicCommand so
Arguments begins after the complete verb, not at a hardcoded single-token
offset. Carry the argument start index through DynamicCommand and pass
words.Length from CreateRawCommand in RespireClient, preserving caller-supplied
arguments only for ValidateRawFireAndForgetCommand and other consumers.
src/Respire/RespireClient.cs (3)

849-874: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the standalone and cluster latency difference.

For a standalone client, SendFireAndForgetAsync returns after the write. For a cluster client, this method awaits the full reply so it can follow MOVED and ASK redirects. The same public ExecuteFireAndForgetAsync call therefore has round-trip latency on a cluster and no round-trip latency on a standalone server.

The behavior is required for correct redirect handling. State it in the XML documentation on the public ExecuteFireAndForgetAsync overloads at Lines 156-167 and Lines 260-271, so callers do not assume constant-time enqueue.

Also note that catch (RespireServerException) at Line 870 discards redirect-exhaustion errors together with ordinary command errors. Confirm that is intended.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Respire/RespireClient.cs` around lines 849 - 874, Update the XML
documentation for both public ExecuteFireAndForgetAsync overloads to state that
standalone execution returns after writing, while cluster execution awaits
replies to process MOVED and ASK redirects and therefore incurs round-trip
latency. Preserve the existing SendFireAndForgetClusterAsync behavior, and
confirm that its catch (RespireServerException) intentionally suppresses both
ordinary server errors and redirect-exhaustion errors.

816-836: 📐 Maintainability & Code Quality | 🔵 Trivial

Fire-and-forget sends bypass telemetry.

SendAsync reaches SendOnConnectionAsync, which starts a RespireTelemetry operation scope. SendFireAndForgetAsync calls connection.SendFireAndForgetAsync directly, so no operation is recorded. Fire-and-forget traffic becomes invisible in metrics and traces.

Consider emitting at least a counter for fire-and-forget dispatch, keyed by operation. The operation parameter is already available here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Respire/RespireClient.cs` around lines 816 - 836, Add telemetry for
fire-and-forget dispatches in SendFireAndForgetAsync, using the existing
operation parameter as the metric key. Ensure the counter is emitted for every
dispatch path, including cluster, post-connect, and direct connection sends,
without changing the existing send behavior.

303-321: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Validation runs after CreateRawCommand allocates.

ExecuteRawFireAndForgetAsync builds the full token array first, then rejects the command. The order is functionally correct, but it allocates for commands that always throw. ExecuteCatalogFireAndForgetAsync at Lines 216-221 validates before it builds CatalogCommand.

Validation needs commandValue.Arguments, so the current order is a deliberate tradeoff. See the separate comment on DynamicCommand.Arguments about the verb-token offset that this call site depends on.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Respire/RespireClient.cs` around lines 303 - 321, Rework
ExecuteRawFireAndForgetAsync so ValidateRawFireAndForgetCommand runs before
CreateRawCommand allocates the full token array, while still validating against
the correct command arguments and preserving the existing cluster-wide versus
regular dispatch behavior. Account for the DynamicCommand.Arguments verb-token
offset when obtaining the validation inputs, as noted in the related comment.
src/Respire/IRespireClient.cs (2)

75-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Adding members to a public interface breaks external implementers.

IRespireClient is public. These new members have no default implementation. Any type outside this repository that implements IRespireClient fails to compile after this change. The update required for ScriptInterceptingClient in RespireDistributedCacheTests.cs shows the same break.

If the package is already released, plan a major version bump, or give the new members default implementations that throw NotSupportedException. The existing ResolveKey member at Line 70 already uses the default-implementation pattern.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Respire/IRespireClient.cs` around lines 75 - 115, Update the newly added
members of IRespireClient to use default interface implementations that throw
NotSupportedException, matching the existing ResolveKey pattern, so external
implementers remain source-compatible. Apply this to the added ExecuteAsync and
ExecuteFireAndForgetAsync overloads without changing existing signatures or
behavior for implementations that support them.

87-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The string overload set omits a cancellation-only form.

The catalog set provides ExecuteAsync(RespireCommand, RespireValue[], CancellationToken) at Lines 78-79. The string set has no matching ExecuteAsync(string, RespireValue[], CancellationToken). A caller who wants cancellation on a raw string command must also pass RespireCommandFlags.None.

Add the missing overload for symmetry.

♻️ Proposed addition
     ValueTask<RespireResult> ExecuteAsync(
         string command, RespireCommandFlags flags, params RespireValue[] args);
 
+    ValueTask<RespireResult> ExecuteAsync(
+        string command, RespireValue[] args, CancellationToken cancellationToken);
+
     ValueTask<RespireResult> ExecuteAsync(
         string command,
         RespireValue[] args,
         RespireCommandFlags flags,
         CancellationToken cancellationToken);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Respire/IRespireClient.cs` around lines 87 - 96, Add the missing
cancellation-only string overload to IRespireClient alongside the existing
ExecuteAsync(string, ...) methods: declare ExecuteAsync(string command,
RespireValue[] args, CancellationToken cancellationToken), matching the catalog
overload and preserving RespireCommandFlags.None as implicit for callers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Respire/RespireClient.cs`:
- Around line 876-887: Update SendClusterWideFireAndForgetAsync to attempt
SendFireAndForgetAsync for every connection without aborting when an individual
send fails, matching the failure-handling behavior of SendClusterWideAsync.
Collect each send exception while continuing the fan-out, then aggregate and
propagate the failures after all master connections have been processed.

In `@tests/Respire.Tests/Networking/ClusterTests.cs`:
- Around line 86-92: In the cluster test’s fire-and-forget command flow, await
WaitForCommandsAsync(target, 2) after the second ExecuteFireAndForgetAsync call
and before asserting ReceivedCommands, ensuring the target has recorded both SET
commands before verification.

---

Outside diff comments:
In `@src/Respire/RespireClient.cs`:
- Around line 181-187: Update the cluster-wide mutation branches in
ExecuteCatalogAsync, ExecuteRawAsync, and ExecuteInterpolatedAsync to preserve
the validated flags when calling SendClusterWideAsync; ensure
RespireCommandFlags.NoRedirect is either forwarded and honored or explicitly
rejected rather than silently ignored.

---

Nitpick comments:
In `@src/Respire/Commands/CommandStructs.cs`:
- Line 223: Update DynamicCommand so Arguments begins after the complete verb,
not at a hardcoded single-token offset. Carry the argument start index through
DynamicCommand and pass words.Length from CreateRawCommand in RespireClient,
preserving caller-supplied arguments only for ValidateRawFireAndForgetCommand
and other consumers.

In `@src/Respire/IRespireClient.cs`:
- Around line 75-115: Update the newly added members of IRespireClient to use
default interface implementations that throw NotSupportedException, matching the
existing ResolveKey pattern, so external implementers remain source-compatible.
Apply this to the added ExecuteAsync and ExecuteFireAndForgetAsync overloads
without changing existing signatures or behavior for implementations that
support them.
- Around line 87-96: Add the missing cancellation-only string overload to
IRespireClient alongside the existing ExecuteAsync(string, ...) methods: declare
ExecuteAsync(string command, RespireValue[] args, CancellationToken
cancellationToken), matching the catalog overload and preserving
RespireCommandFlags.None as implicit for callers.

In `@src/Respire/RespireClient.cs`:
- Around line 849-874: Update the XML documentation for both public
ExecuteFireAndForgetAsync overloads to state that standalone execution returns
after writing, while cluster execution awaits replies to process MOVED and ASK
redirects and therefore incurs round-trip latency. Preserve the existing
SendFireAndForgetClusterAsync behavior, and confirm that its catch
(RespireServerException) intentionally suppresses both ordinary server errors
and redirect-exhaustion errors.
- Around line 816-836: Add telemetry for fire-and-forget dispatches in
SendFireAndForgetAsync, using the existing operation parameter as the metric
key. Ensure the counter is emitted for every dispatch path, including cluster,
post-connect, and direct connection sends, without changing the existing send
behavior.
- Around line 303-321: Rework ExecuteRawFireAndForgetAsync so
ValidateRawFireAndForgetCommand runs before CreateRawCommand allocates the full
token array, while still validating against the correct command arguments and
preserving the existing cluster-wide versus regular dispatch behavior. Account
for the DynamicCommand.Arguments verb-token offset when obtaining the validation
inputs, as noted in the related comment.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0a4d976e-abaa-49f7-9507-df81a74cce62

📥 Commits

Reviewing files that changed from the base of the PR and between 2a5cc36 and 810b427.

📒 Files selected for processing (9)
  • src/Respire/Commands/CommandStructs.cs
  • src/Respire/IRespireClient.cs
  • src/Respire/RespireClient.cs
  • src/Respire/RespireCommand.cs
  • src/Respire/RespireCommandFlags.cs
  • tests/Respire.Extensions.Caching.Tests/RespireDistributedCacheTests.cs
  • tests/Respire.Tests/Networking/ClusterTests.cs
  • tests/Respire.Tests/Networking/CommandCatalogTests.cs
  • tests/Respire.Tests/Networking/FakeRespServer.cs

Comment thread src/Respire/RespireClient.cs Resolved

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

if (arg.EqualsAsciiIgnoreCase("BLOCK"))
{
return true;

P2 Badge Parse BLOCK only in the command's option section

For XREAD STREAMS BLOCK $, BLOCK is a valid stream key rather than the blocking option, but scanning every argument classifies the command as blocking. The new fire-and-forget APIs consequently reject legitimate nonblocking reads whenever a key (or an XREADGROUP group/consumer/key) is named BLOCK; inspect the command grammar and only recognize BLOCK before the STREAMS section.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net10.0)

ℹ️ Execution Details

  • Framework: net10.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T02:30:38.269Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net8.0)

ℹ️ Execution Details

  • Framework: net8.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T02:31:12.846Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net10.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 187.0 μs 50.17 μs 2.75 μs 184.9 μs 190.1 μs 185.9 μs 189.7 μs 1.00 0.02 184 B 1.00
StackExchange_Ping 187.6 μs 38.27 μs 2.10 μs 185.3 μs 189.3 μs 188.3 μs 189.2 μs 1.00 0.02 408 B 2.22
Respire_Set_Small 188.5 μs 6.29 μs 0.34 μs 188.1 μs 188.8 μs 188.6 μs 188.8 μs 1.01 0.01 176 B 0.96
StackExchange_Set_Small 191.0 μs 23.51 μs 1.29 μs 189.6 μs 192.1 μs 191.3 μs 192.0 μs 1.02 0.01 416 B 2.26
Respire_Set_Medium 188.3 μs 59.98 μs 3.29 μs 186.1 μs 192.0 μs 186.6 μs 191.5 μs 1.01 0.02 176 B 0.96
StackExchange_Set_Medium 191.3 μs 5.98 μs 0.33 μs 190.9 μs 191.6 μs 191.3 μs 191.6 μs 1.02 0.01 416 B 2.26
Respire_Set_Large 199.8 μs 9.24 μs 0.51 μs 199.2 μs 200.2 μs 200.0 μs 200.2 μs 1.07 0.01 176 B 0.96
StackExchange_Set_Large 199.0 μs 26.17 μs 1.43 μs 197.6 μs 200.4 μs 199.0 μs 200.3 μs 1.06 0.02 416 B 2.26
Respire_Get 189.4 μs 9.51 μs 0.52 μs 188.7 μs 189.7 μs 189.6 μs 189.7 μs 1.01 0.01 224 B 1.22
StackExchange_Get 191.4 μs 3.75 μs 0.21 μs 191.3 μs 191.6 μs 191.3 μs 191.6 μs 1.02 0.01 424 B 2.30
StackExchange_MGet 193.7 μs 41.12 μs 2.25 μs 191.1 μs 195.1 μs 194.9 μs 195.1 μs 1.04 0.02 656 B 3.57
StackExchange_Pipeline_5_Sets 227.5 μs 302.78 μs 16.60 μs 214.2 μs 246.1 μs 222.2 μs 243.7 μs 1.22 0.08 2888 B 15.70
Respire_Exists 186.9 μs 29.41 μs 1.61 μs 185.3 μs 188.5 μs 186.9 μs 188.3 μs 1.00 0.01 176 B 0.96
StackExchange_Exists 186.2 μs 43.14 μs 2.36 μs 184.6 μs 189.0 μs 185.2 μs 188.6 μs 1.00 0.02 400 B 2.17
Respire_Del 364.2 μs 91.54 μs 5.02 μs 360.2 μs 369.8 μs 362.6 μs 369.1 μs 1.95 0.03 200 B 1.09
StackExchange_Del 362.1 μs 116.86 μs 6.41 μs 354.9 μs 367.3 μs 364.0 μs 367.0 μs 1.94 0.04 648 B 3.52
Respire_Incr 188.6 μs 11.45 μs 0.63 μs 187.9 μs 189.2 μs 188.7 μs 189.1 μs 1.01 0.01 184 B 1.00
StackExchange_Incr 191.2 μs 9.80 μs 0.54 μs 190.6 μs 191.7 μs 191.3 μs 191.6 μs 1.02 0.01 400 B 2.17
Respire_Transaction_2 198.5 μs 77.02 μs 4.22 μs 193.8 μs 201.8 μs 200.1 μs 201.6 μs 1.06 0.02 1064 B 5.78
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error     | StdDev   | Min      | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|----------:|---------:|---------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 187.0 μs |  50.17 μs |  2.75 μs | 184.9 μs | 190.1 μs | 185.9 μs | 189.7 μs |  1.00 |    0.02 |     184 B |        1.00 |
StackExchange_Ping            | 187.6 μs |  38.27 μs |  2.10 μs | 185.3 μs | 189.3 μs | 188.3 μs | 189.2 μs |  1.00 |    0.02 |     408 B |        2.22 |
Respire_Set_Small             | 188.5 μs |   6.29 μs |  0.34 μs | 188.1 μs | 188.8 μs | 188.6 μs | 188.8 μs |  1.01 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Small       | 191.0 μs |  23.51 μs |  1.29 μs | 189.6 μs | 192.1 μs | 191.3 μs | 192.0 μs |  1.02 |    0.01 |     416 B |        2.26 |
Respire_Set_Medium            | 188.3 μs |  59.98 μs |  3.29 μs | 186.1 μs | 192.0 μs | 186.6 μs | 191.5 μs |  1.01 |    0.02 |     176 B |        0.96 |
StackExchange_Set_Medium      | 191.3 μs |   5.98 μs |  0.33 μs | 190.9 μs | 191.6 μs | 191.3 μs | 191.6 μs |  1.02 |    0.01 |     416 B |        2.26 |
Respire_Set_Large             | 199.8 μs |   9.24 μs |  0.51 μs | 199.2 μs | 200.2 μs | 200.0 μs | 200.2 μs |  1.07 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Large       | 199.0 μs |  26.17 μs |  1.43 μs | 197.6 μs | 200.4 μs | 199.0 μs | 200.3 μs |  1.06 |    0.02 |     416 B |        2.26 |
Respire_Get                   | 189.4 μs |   9.51 μs |  0.52 μs | 188.7 μs | 189.7 μs | 189.6 μs | 189.7 μs |  1.01 |    0.01 |     224 B |        1.22 |
StackExchange_Get             | 191.4 μs |   3.75 μs |  0.21 μs | 191.3 μs | 191.6 μs | 191.3 μs | 191.6 μs |  1.02 |    0.01 |     424 B |        2.30 |
StackExchange_MGet            | 193.7 μs |  41.12 μs |  2.25 μs | 191.1 μs | 195.1 μs | 194.9 μs | 195.1 μs |  1.04 |    0.02 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 227.5 μs | 302.78 μs | 16.60 μs | 214.2 μs | 246.1 μs | 222.2 μs | 243.7 μs |  1.22 |    0.08 |    2888 B |       15.70 |
Respire_Exists                | 186.9 μs |  29.41 μs |  1.61 μs | 185.3 μs | 188.5 μs | 186.9 μs | 188.3 μs |  1.00 |    0.01 |     176 B |        0.96 |
StackExchange_Exists          | 186.2 μs |  43.14 μs |  2.36 μs | 184.6 μs | 189.0 μs | 185.2 μs | 188.6 μs |  1.00 |    0.02 |     400 B |        2.17 |
Respire_Del                   | 364.2 μs |  91.54 μs |  5.02 μs | 360.2 μs | 369.8 μs | 362.6 μs | 369.1 μs |  1.95 |    0.03 |     200 B |        1.09 |
StackExchange_Del             | 362.1 μs | 116.86 μs |  6.41 μs | 354.9 μs | 367.3 μs | 364.0 μs | 367.0 μs |  1.94 |    0.04 |     648 B |        3.52 |
Respire_Incr                  | 188.6 μs |  11.45 μs |  0.63 μs | 187.9 μs | 189.2 μs | 188.7 μs | 189.1 μs |  1.01 |    0.01 |     184 B |        1.00 |
StackExchange_Incr            | 191.2 μs |   9.80 μs |  0.54 μs | 190.6 μs | 191.7 μs | 191.3 μs | 191.6 μs |  1.02 |    0.01 |     400 B |        2.17 |
Respire_Transaction_2         | 198.5 μs |  77.02 μs |  4.22 μs | 193.8 μs | 201.8 μs | 200.1 μs | 201.6 μs |  1.06 |    0.02 |    1064 B |        5.78 |

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net8.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 174.9 μs 26.47 μs 1.45 μs 173.3 μs 176.1 μs 175.4 μs 176.0 μs 1.00 0.01 184 B 1.00
StackExchange_Ping 178.1 μs 17.41 μs 0.95 μs 177.2 μs 179.1 μs 178.1 μs 179.0 μs 1.02 0.01 406 B 2.21
Respire_Set_Small 177.4 μs 8.39 μs 0.46 μs 177.0 μs 177.9 μs 177.2 μs 177.8 μs 1.01 0.01 176 B 0.96
StackExchange_Set_Small 180.0 μs 29.40 μs 1.61 μs 178.2 μs 181.2 μs 180.7 μs 181.2 μs 1.03 0.01 416 B 2.26
Respire_Set_Medium 177.4 μs 23.02 μs 1.26 μs 176.0 μs 178.2 μs 178.1 μs 178.2 μs 1.01 0.01 176 B 0.96
StackExchange_Set_Medium 181.5 μs 12.77 μs 0.70 μs 180.7 μs 182.1 μs 181.6 μs 182.1 μs 1.04 0.01 416 B 2.26
Respire_Set_Large 180.5 μs 13.39 μs 0.73 μs 180.0 μs 181.4 μs 180.2 μs 181.3 μs 1.03 0.01 176 B 0.96
StackExchange_Set_Large 188.8 μs 29.24 μs 1.60 μs 187.1 μs 190.2 μs 189.0 μs 190.1 μs 1.08 0.01 416 B 2.26
Respire_Get 176.1 μs 17.78 μs 0.97 μs 175.3 μs 177.2 μs 175.9 μs 177.1 μs 1.01 0.01 224 B 1.22
StackExchange_Get 176.4 μs 29.61 μs 1.62 μs 174.7 μs 177.9 μs 176.5 μs 177.8 μs 1.01 0.01 424 B 2.30
StackExchange_MGet 182.8 μs 40.47 μs 2.22 μs 180.2 μs 184.1 μs 184.0 μs 184.1 μs 1.04 0.01 656 B 3.57
StackExchange_Pipeline_5_Sets 223.3 μs 359.73 μs 19.72 μs 201.3 μs 239.3 μs 229.5 μs 238.3 μs 1.28 0.10 2887 B 15.69
Respire_Exists 173.8 μs 9.58 μs 0.53 μs 173.5 μs 174.4 μs 173.5 μs 174.3 μs 0.99 0.01 176 B 0.96
StackExchange_Exists 178.7 μs 17.32 μs 0.95 μs 177.6 μs 179.5 μs 179.0 μs 179.4 μs 1.02 0.01 400 B 2.17
Respire_Del 338.6 μs 22.47 μs 1.23 μs 337.7 μs 340.0 μs 338.1 μs 339.8 μs 1.94 0.02 200 B 1.09
StackExchange_Del 345.8 μs 27.43 μs 1.50 μs 344.0 μs 346.8 μs 346.4 μs 346.8 μs 1.98 0.02 648 B 3.52
Respire_Incr 177.2 μs 25.75 μs 1.41 μs 176.2 μs 178.8 μs 176.7 μs 178.6 μs 1.01 0.01 184 B 1.00
StackExchange_Incr 178.4 μs 29.24 μs 1.60 μs 176.6 μs 179.8 μs 178.7 μs 179.7 μs 1.02 0.01 397 B 2.16
Respire_Transaction_2 180.5 μs 14.53 μs 0.80 μs 179.9 μs 181.4 μs 180.2 μs 181.3 μs 1.03 0.01 1064 B 5.78
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error     | StdDev   | Min      | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|----------:|---------:|---------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 174.9 μs |  26.47 μs |  1.45 μs | 173.3 μs | 176.1 μs | 175.4 μs | 176.0 μs |  1.00 |    0.01 |     184 B |        1.00 |
StackExchange_Ping            | 178.1 μs |  17.41 μs |  0.95 μs | 177.2 μs | 179.1 μs | 178.1 μs | 179.0 μs |  1.02 |    0.01 |     406 B |        2.21 |
Respire_Set_Small             | 177.4 μs |   8.39 μs |  0.46 μs | 177.0 μs | 177.9 μs | 177.2 μs | 177.8 μs |  1.01 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Small       | 180.0 μs |  29.40 μs |  1.61 μs | 178.2 μs | 181.2 μs | 180.7 μs | 181.2 μs |  1.03 |    0.01 |     416 B |        2.26 |
Respire_Set_Medium            | 177.4 μs |  23.02 μs |  1.26 μs | 176.0 μs | 178.2 μs | 178.1 μs | 178.2 μs |  1.01 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Medium      | 181.5 μs |  12.77 μs |  0.70 μs | 180.7 μs | 182.1 μs | 181.6 μs | 182.1 μs |  1.04 |    0.01 |     416 B |        2.26 |
Respire_Set_Large             | 180.5 μs |  13.39 μs |  0.73 μs | 180.0 μs | 181.4 μs | 180.2 μs | 181.3 μs |  1.03 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Large       | 188.8 μs |  29.24 μs |  1.60 μs | 187.1 μs | 190.2 μs | 189.0 μs | 190.1 μs |  1.08 |    0.01 |     416 B |        2.26 |
Respire_Get                   | 176.1 μs |  17.78 μs |  0.97 μs | 175.3 μs | 177.2 μs | 175.9 μs | 177.1 μs |  1.01 |    0.01 |     224 B |        1.22 |
StackExchange_Get             | 176.4 μs |  29.61 μs |  1.62 μs | 174.7 μs | 177.9 μs | 176.5 μs | 177.8 μs |  1.01 |    0.01 |     424 B |        2.30 |
StackExchange_MGet            | 182.8 μs |  40.47 μs |  2.22 μs | 180.2 μs | 184.1 μs | 184.0 μs | 184.1 μs |  1.04 |    0.01 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 223.3 μs | 359.73 μs | 19.72 μs | 201.3 μs | 239.3 μs | 229.5 μs | 238.3 μs |  1.28 |    0.10 |    2887 B |       15.69 |
Respire_Exists                | 173.8 μs |   9.58 μs |  0.53 μs | 173.5 μs | 174.4 μs | 173.5 μs | 174.3 μs |  0.99 |    0.01 |     176 B |        0.96 |
StackExchange_Exists          | 178.7 μs |  17.32 μs |  0.95 μs | 177.6 μs | 179.5 μs | 179.0 μs | 179.4 μs |  1.02 |    0.01 |     400 B |        2.17 |
Respire_Del                   | 338.6 μs |  22.47 μs |  1.23 μs | 337.7 μs | 340.0 μs | 338.1 μs | 339.8 μs |  1.94 |    0.02 |     200 B |        1.09 |
StackExchange_Del             | 345.8 μs |  27.43 μs |  1.50 μs | 344.0 μs | 346.8 μs | 346.4 μs | 346.8 μs |  1.98 |    0.02 |     648 B |        3.52 |
Respire_Incr                  | 177.2 μs |  25.75 μs |  1.41 μs | 176.2 μs | 178.8 μs | 176.7 μs | 178.6 μs |  1.01 |    0.01 |     184 B |        1.00 |
StackExchange_Incr            | 178.4 μs |  29.24 μs |  1.60 μs | 176.6 μs | 179.8 μs | 178.7 μs | 179.7 μs |  1.02 |    0.01 |     397 B |        2.16 |
Respire_Transaction_2         | 180.5 μs |  14.53 μs |  0.80 μs | 179.9 μs | 181.4 μs | 180.2 μs | 181.3 μs |  1.03 |    0.01 |    1064 B |        5.78 |

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f4957d007

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +175 to +176
/// Standalone execution returns after writing. Cluster execution may await replies to process
/// <c>MOVED</c> and <c>ASK</c> redirects, adding round-trip latency.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wait for the advertised socket write

When a caller awaits a standalone fire-and-forget command and then immediately disposes the client or exits, the command can still be dropped: RespireConnection.SendFireAndForgetAsync returns a completed task after enqueueing and scheduling the flush (RespireConnection.cs:573-580), while disposal aborts the connection before awaiting the flush loop (RespireConnection.cs:1524-1533). This contradicts the new guarantee that standalone execution returns after writing; either await completion of the socket write or document that completion only means the command was queued.

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net10.0)

ℹ️ Execution Details

  • Framework: net10.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T02:44:40.882Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net8.0)

ℹ️ Execution Details

  • Framework: net8.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T02:44:57.031Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net10.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio Allocated Alloc Ratio
Respire_Ping 179.5 μs 6.59 μs 0.36 μs 179.2 μs 179.9 μs 179.5 μs 179.8 μs 1.00 184 B 1.00
StackExchange_Ping 183.3 μs 49.20 μs 2.70 μs 180.2 μs 185.3 μs 184.3 μs 185.2 μs 1.02 408 B 2.22
Respire_Set_Small 181.0 μs 7.79 μs 0.43 μs 180.8 μs 181.5 μs 180.8 μs 181.5 μs 1.01 176 B 0.96
StackExchange_Set_Small 184.7 μs 47.15 μs 2.58 μs 182.9 μs 187.7 μs 183.6 μs 187.2 μs 1.03 416 B 2.26
Respire_Set_Medium 183.9 μs 11.87 μs 0.65 μs 183.3 μs 184.6 μs 184.0 μs 184.5 μs 1.02 176 B 0.96
StackExchange_Set_Medium 188.9 μs 11.13 μs 0.61 μs 188.3 μs 189.5 μs 188.9 μs 189.4 μs 1.05 416 B 2.26
Respire_Set_Large 192.6 μs 2.08 μs 0.11 μs 192.4 μs 192.6 μs 192.6 μs 192.6 μs 1.07 176 B 0.96
StackExchange_Set_Large 194.8 μs 41.93 μs 2.30 μs 192.4 μs 196.9 μs 195.2 μs 196.8 μs 1.09 416 B 2.26
Respire_Get 181.2 μs 11.48 μs 0.63 μs 180.8 μs 181.9 μs 181.0 μs 181.9 μs 1.01 224 B 1.22
StackExchange_Get 182.8 μs 26.42 μs 1.45 μs 181.9 μs 184.4 μs 181.9 μs 184.2 μs 1.02 424 B 2.30
StackExchange_MGet 186.7 μs 35.07 μs 1.92 μs 184.5 μs 188.1 μs 187.4 μs 188.1 μs 1.04 656 B 3.57
StackExchange_Pipeline_5_Sets 207.0 μs 42.62 μs 2.34 μs 204.6 μs 209.3 μs 207.1 μs 209.1 μs 1.15 2888 B 15.70
Respire_Exists 180.9 μs 27.80 μs 1.52 μs 179.2 μs 182.2 μs 181.1 μs 182.1 μs 1.01 176 B 0.96
StackExchange_Exists 185.7 μs 9.18 μs 0.50 μs 185.4 μs 186.2 μs 185.4 μs 186.2 μs 1.03 400 B 2.17
Respire_Del 347.9 μs 4.97 μs 0.27 μs 347.7 μs 348.2 μs 347.7 μs 348.1 μs 1.94 200 B 1.09
StackExchange_Del 351.6 μs 30.67 μs 1.68 μs 350.6 μs 353.6 μs 350.7 μs 353.3 μs 1.96 648 B 3.52
Respire_Incr 180.4 μs 6.45 μs 0.35 μs 180.0 μs 180.7 μs 180.6 μs 180.6 μs 1.01 184 B 1.00
StackExchange_Incr 181.2 μs 38.33 μs 2.10 μs 178.9 μs 183.1 μs 181.5 μs 183.0 μs 1.01 400 B 2.17
Respire_Transaction_2 187.6 μs 48.91 μs 2.68 μs 184.5 μs 189.2 μs 189.1 μs 189.2 μs 1.05 1072 B 5.83
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error    | StdDev  | Min      | Max      | Median   | P95      | Ratio | Allocated | Alloc Ratio |
------------------------------ |---------:|---------:|--------:|---------:|---------:|---------:|---------:|------:|----------:|------------:|
Respire_Ping                  | 179.5 μs |  6.59 μs | 0.36 μs | 179.2 μs | 179.9 μs | 179.5 μs | 179.8 μs |  1.00 |     184 B |        1.00 |
StackExchange_Ping            | 183.3 μs | 49.20 μs | 2.70 μs | 180.2 μs | 185.3 μs | 184.3 μs | 185.2 μs |  1.02 |     408 B |        2.22 |
Respire_Set_Small             | 181.0 μs |  7.79 μs | 0.43 μs | 180.8 μs | 181.5 μs | 180.8 μs | 181.5 μs |  1.01 |     176 B |        0.96 |
StackExchange_Set_Small       | 184.7 μs | 47.15 μs | 2.58 μs | 182.9 μs | 187.7 μs | 183.6 μs | 187.2 μs |  1.03 |     416 B |        2.26 |
Respire_Set_Medium            | 183.9 μs | 11.87 μs | 0.65 μs | 183.3 μs | 184.6 μs | 184.0 μs | 184.5 μs |  1.02 |     176 B |        0.96 |
StackExchange_Set_Medium      | 188.9 μs | 11.13 μs | 0.61 μs | 188.3 μs | 189.5 μs | 188.9 μs | 189.4 μs |  1.05 |     416 B |        2.26 |
Respire_Set_Large             | 192.6 μs |  2.08 μs | 0.11 μs | 192.4 μs | 192.6 μs | 192.6 μs | 192.6 μs |  1.07 |     176 B |        0.96 |
StackExchange_Set_Large       | 194.8 μs | 41.93 μs | 2.30 μs | 192.4 μs | 196.9 μs | 195.2 μs | 196.8 μs |  1.09 |     416 B |        2.26 |
Respire_Get                   | 181.2 μs | 11.48 μs | 0.63 μs | 180.8 μs | 181.9 μs | 181.0 μs | 181.9 μs |  1.01 |     224 B |        1.22 |
StackExchange_Get             | 182.8 μs | 26.42 μs | 1.45 μs | 181.9 μs | 184.4 μs | 181.9 μs | 184.2 μs |  1.02 |     424 B |        2.30 |
StackExchange_MGet            | 186.7 μs | 35.07 μs | 1.92 μs | 184.5 μs | 188.1 μs | 187.4 μs | 188.1 μs |  1.04 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 207.0 μs | 42.62 μs | 2.34 μs | 204.6 μs | 209.3 μs | 207.1 μs | 209.1 μs |  1.15 |    2888 B |       15.70 |
Respire_Exists                | 180.9 μs | 27.80 μs | 1.52 μs | 179.2 μs | 182.2 μs | 181.1 μs | 182.1 μs |  1.01 |     176 B |        0.96 |
StackExchange_Exists          | 185.7 μs |  9.18 μs | 0.50 μs | 185.4 μs | 186.2 μs | 185.4 μs | 186.2 μs |  1.03 |     400 B |        2.17 |
Respire_Del                   | 347.9 μs |  4.97 μs | 0.27 μs | 347.7 μs | 348.2 μs | 347.7 μs | 348.1 μs |  1.94 |     200 B |        1.09 |
StackExchange_Del             | 351.6 μs | 30.67 μs | 1.68 μs | 350.6 μs | 353.6 μs | 350.7 μs | 353.3 μs |  1.96 |     648 B |        3.52 |
Respire_Incr                  | 180.4 μs |  6.45 μs | 0.35 μs | 180.0 μs | 180.7 μs | 180.6 μs | 180.6 μs |  1.01 |     184 B |        1.00 |
StackExchange_Incr            | 181.2 μs | 38.33 μs | 2.10 μs | 178.9 μs | 183.1 μs | 181.5 μs | 183.0 μs |  1.01 |     400 B |        2.17 |
Respire_Transaction_2         | 187.6 μs | 48.91 μs | 2.68 μs | 184.5 μs | 189.2 μs | 189.1 μs | 189.2 μs |  1.05 |    1072 B |        5.83 |

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net8.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 173.7 μs 2.23 μs 0.12 μs 173.6 μs 173.8 μs 173.8 μs 173.8 μs 1.00 0.00 182 B 1.00
StackExchange_Ping 176.7 μs 16.33 μs 0.90 μs 176.1 μs 177.7 μs 176.2 μs 177.5 μs 1.02 0.00 408 B 2.24
Respire_Set_Small 175.1 μs 16.84 μs 0.92 μs 174.1 μs 175.9 μs 175.3 μs 175.8 μs 1.01 0.00 176 B 0.97
StackExchange_Set_Small 177.5 μs 45.71 μs 2.51 μs 174.7 μs 179.2 μs 178.7 μs 179.2 μs 1.02 0.01 416 B 2.29
Respire_Set_Medium 176.8 μs 9.40 μs 0.52 μs 176.3 μs 177.3 μs 176.6 μs 177.3 μs 1.02 0.00 176 B 0.97
StackExchange_Set_Medium 181.2 μs 24.22 μs 1.33 μs 180.0 μs 182.6 μs 180.9 μs 182.4 μs 1.04 0.01 416 B 2.29
Respire_Set_Large 179.7 μs 4.27 μs 0.23 μs 179.5 μs 179.9 μs 179.6 μs 179.9 μs 1.03 0.00 176 B 0.97
StackExchange_Set_Large 190.5 μs 7.97 μs 0.44 μs 190.1 μs 191.0 μs 190.4 μs 191.0 μs 1.10 0.00 416 B 2.29
Respire_Get 175.6 μs 36.84 μs 2.02 μs 173.2 μs 176.8 μs 176.6 μs 176.8 μs 1.01 0.01 224 B 1.23
StackExchange_Get 179.2 μs 28.87 μs 1.58 μs 177.5 μs 180.6 μs 179.4 μs 180.5 μs 1.03 0.01 424 B 2.33
StackExchange_MGet 181.5 μs 38.58 μs 2.11 μs 179.4 μs 183.6 μs 181.6 μs 183.4 μs 1.04 0.01 656 B 3.60
StackExchange_Pipeline_5_Sets 197.7 μs 57.08 μs 3.13 μs 194.8 μs 201.0 μs 197.4 μs 200.6 μs 1.14 0.02 2888 B 15.87
Respire_Exists 172.5 μs 26.80 μs 1.47 μs 171.1 μs 174.0 μs 172.4 μs 173.9 μs 0.99 0.01 176 B 0.97
StackExchange_Exists 176.3 μs 22.38 μs 1.23 μs 175.3 μs 177.7 μs 176.1 μs 177.5 μs 1.02 0.01 400 B 2.20
Respire_Del 332.3 μs 28.52 μs 1.56 μs 330.6 μs 333.8 μs 332.4 μs 333.6 μs 1.91 0.01 200 B 1.10
StackExchange_Del 341.0 μs 54.31 μs 2.98 μs 337.6 μs 343.2 μs 342.1 μs 343.1 μs 1.96 0.01 648 B 3.56
Respire_Incr 175.4 μs 10.20 μs 0.56 μs 174.8 μs 176.0 μs 175.5 μs 175.9 μs 1.01 0.00 183 B 1.01
StackExchange_Incr 179.3 μs 26.94 μs 1.48 μs 177.6 μs 180.5 μs 179.6 μs 180.4 μs 1.03 0.01 400 B 2.20
Respire_Transaction_2 179.4 μs 29.02 μs 1.59 μs 177.5 μs 180.4 μs 180.1 μs 180.4 μs 1.03 0.01 1072 B 5.89
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error    | StdDev  | Min      | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|---------:|--------:|---------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 173.7 μs |  2.23 μs | 0.12 μs | 173.6 μs | 173.8 μs | 173.8 μs | 173.8 μs |  1.00 |    0.00 |     182 B |        1.00 |
StackExchange_Ping            | 176.7 μs | 16.33 μs | 0.90 μs | 176.1 μs | 177.7 μs | 176.2 μs | 177.5 μs |  1.02 |    0.00 |     408 B |        2.24 |
Respire_Set_Small             | 175.1 μs | 16.84 μs | 0.92 μs | 174.1 μs | 175.9 μs | 175.3 μs | 175.8 μs |  1.01 |    0.00 |     176 B |        0.97 |
StackExchange_Set_Small       | 177.5 μs | 45.71 μs | 2.51 μs | 174.7 μs | 179.2 μs | 178.7 μs | 179.2 μs |  1.02 |    0.01 |     416 B |        2.29 |
Respire_Set_Medium            | 176.8 μs |  9.40 μs | 0.52 μs | 176.3 μs | 177.3 μs | 176.6 μs | 177.3 μs |  1.02 |    0.00 |     176 B |        0.97 |
StackExchange_Set_Medium      | 181.2 μs | 24.22 μs | 1.33 μs | 180.0 μs | 182.6 μs | 180.9 μs | 182.4 μs |  1.04 |    0.01 |     416 B |        2.29 |
Respire_Set_Large             | 179.7 μs |  4.27 μs | 0.23 μs | 179.5 μs | 179.9 μs | 179.6 μs | 179.9 μs |  1.03 |    0.00 |     176 B |        0.97 |
StackExchange_Set_Large       | 190.5 μs |  7.97 μs | 0.44 μs | 190.1 μs | 191.0 μs | 190.4 μs | 191.0 μs |  1.10 |    0.00 |     416 B |        2.29 |
Respire_Get                   | 175.6 μs | 36.84 μs | 2.02 μs | 173.2 μs | 176.8 μs | 176.6 μs | 176.8 μs |  1.01 |    0.01 |     224 B |        1.23 |
StackExchange_Get             | 179.2 μs | 28.87 μs | 1.58 μs | 177.5 μs | 180.6 μs | 179.4 μs | 180.5 μs |  1.03 |    0.01 |     424 B |        2.33 |
StackExchange_MGet            | 181.5 μs | 38.58 μs | 2.11 μs | 179.4 μs | 183.6 μs | 181.6 μs | 183.4 μs |  1.04 |    0.01 |     656 B |        3.60 |
StackExchange_Pipeline_5_Sets | 197.7 μs | 57.08 μs | 3.13 μs | 194.8 μs | 201.0 μs | 197.4 μs | 200.6 μs |  1.14 |    0.02 |    2888 B |       15.87 |
Respire_Exists                | 172.5 μs | 26.80 μs | 1.47 μs | 171.1 μs | 174.0 μs | 172.4 μs | 173.9 μs |  0.99 |    0.01 |     176 B |        0.97 |
StackExchange_Exists          | 176.3 μs | 22.38 μs | 1.23 μs | 175.3 μs | 177.7 μs | 176.1 μs | 177.5 μs |  1.02 |    0.01 |     400 B |        2.20 |
Respire_Del                   | 332.3 μs | 28.52 μs | 1.56 μs | 330.6 μs | 333.8 μs | 332.4 μs | 333.6 μs |  1.91 |    0.01 |     200 B |        1.10 |
StackExchange_Del             | 341.0 μs | 54.31 μs | 2.98 μs | 337.6 μs | 343.2 μs | 342.1 μs | 343.1 μs |  1.96 |    0.01 |     648 B |        3.56 |
Respire_Incr                  | 175.4 μs | 10.20 μs | 0.56 μs | 174.8 μs | 176.0 μs | 175.5 μs | 175.9 μs |  1.01 |    0.00 |     183 B |        1.01 |
StackExchange_Incr            | 179.3 μs | 26.94 μs | 1.48 μs | 177.6 μs | 180.5 μs | 179.6 μs | 180.4 μs |  1.03 |    0.01 |     400 B |        2.20 |
Respire_Transaction_2         | 179.4 μs | 29.02 μs | 1.59 μs | 177.5 μs | 180.4 μs | 180.1 μs | 180.4 μs |  1.03 |    0.01 |    1072 B |        5.89 |

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d3f2ab00d6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +576 to +579
if (TryEnqueueForWrite(in command, out var startedBatch, out var writeTask))
{
ScheduleFlush(startedBatch);
return ValueTask.CompletedTask;
return new ValueTask(writeTask);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor cancellation while awaiting the fire-and-forget write

When the socket write is backpressured and this normal-capacity fast path succeeds, the supplied cancellation token is never observed and the returned writeTask is awaited directly. Consequently, even a pre-canceled token still enqueues and executes a mutating command, while cancellation during a stalled write cannot release the caller; only the ring-full slow path checks the token before enqueueing. Check cancellation before enqueueing and make the caller's wait cancelable without canceling the underlying socket send.

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net10.0)

ℹ️ Execution Details

  • Framework: net10.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T02:54:05.527Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net8.0)

ℹ️ Execution Details

  • Framework: net8.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T02:55:53.602Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net10.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 174.0 μs 4.62 μs 0.25 μs 173.8 μs 174.3 μs 173.9 μs 174.2 μs 1.00 0.00 184 B 1.00
StackExchange_Ping 177.8 μs 22.54 μs 1.24 μs 176.9 μs 179.2 μs 177.3 μs 179.0 μs 1.02 0.01 408 B 2.22
Respire_Set_Small 176.2 μs 10.83 μs 0.59 μs 175.5 μs 176.7 μs 176.3 μs 176.6 μs 1.01 0.00 176 B 0.96
StackExchange_Set_Small 178.4 μs 57.38 μs 3.15 μs 174.8 μs 180.8 μs 179.5 μs 180.6 μs 1.03 0.02 415 B 2.26
Respire_Set_Medium 177.1 μs 12.67 μs 0.69 μs 176.3 μs 177.7 μs 177.1 μs 177.6 μs 1.02 0.00 176 B 0.96
StackExchange_Set_Medium 181.8 μs 14.92 μs 0.82 μs 180.9 μs 182.3 μs 182.3 μs 182.3 μs 1.05 0.00 416 B 2.26
Respire_Set_Large 180.1 μs 12.95 μs 0.71 μs 179.5 μs 180.9 μs 179.8 μs 180.8 μs 1.04 0.00 176 B 0.96
StackExchange_Set_Large 188.5 μs 26.55 μs 1.46 μs 186.9 μs 189.5 μs 189.2 μs 189.5 μs 1.08 0.01 416 B 2.26
Respire_Get 176.0 μs 17.03 μs 0.93 μs 175.0 μs 176.8 μs 176.1 μs 176.8 μs 1.01 0.00 222 B 1.21
StackExchange_Get 178.1 μs 40.80 μs 2.24 μs 176.5 μs 180.6 μs 177.1 μs 180.3 μs 1.02 0.01 424 B 2.30
StackExchange_MGet 182.0 μs 49.42 μs 2.71 μs 178.9 μs 183.8 μs 183.2 μs 183.8 μs 1.05 0.01 656 B 3.57
StackExchange_Pipeline_5_Sets 199.2 μs 28.17 μs 1.54 μs 197.4 μs 200.3 μs 199.8 μs 200.3 μs 1.14 0.01 2888 B 15.70
Respire_Exists 173.4 μs 26.79 μs 1.47 μs 171.7 μs 174.3 μs 174.1 μs 174.3 μs 1.00 0.01 175 B 0.95
StackExchange_Exists 177.0 μs 34.66 μs 1.90 μs 174.8 μs 178.1 μs 178.1 μs 178.1 μs 1.02 0.01 400 B 2.17
Respire_Del 335.1 μs 29.82 μs 1.63 μs 333.2 μs 336.3 μs 335.8 μs 336.2 μs 1.93 0.01 200 B 1.09
StackExchange_Del 335.1 μs 18.46 μs 1.01 μs 334.2 μs 336.2 μs 334.8 μs 336.0 μs 1.93 0.01 648 B 3.52
Respire_Incr 175.8 μs 5.62 μs 0.31 μs 175.6 μs 176.1 μs 175.7 μs 176.1 μs 1.01 0.00 184 B 1.00
StackExchange_Incr 177.7 μs 22.67 μs 1.24 μs 176.3 μs 178.6 μs 178.3 μs 178.6 μs 1.02 0.01 400 B 2.17
Respire_Transaction_2 178.5 μs 9.93 μs 0.54 μs 178.1 μs 179.1 μs 178.1 μs 179.0 μs 1.03 0.00 1071 B 5.82
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error    | StdDev  | Min      | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|---------:|--------:|---------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 174.0 μs |  4.62 μs | 0.25 μs | 173.8 μs | 174.3 μs | 173.9 μs | 174.2 μs |  1.00 |    0.00 |     184 B |        1.00 |
StackExchange_Ping            | 177.8 μs | 22.54 μs | 1.24 μs | 176.9 μs | 179.2 μs | 177.3 μs | 179.0 μs |  1.02 |    0.01 |     408 B |        2.22 |
Respire_Set_Small             | 176.2 μs | 10.83 μs | 0.59 μs | 175.5 μs | 176.7 μs | 176.3 μs | 176.6 μs |  1.01 |    0.00 |     176 B |        0.96 |
StackExchange_Set_Small       | 178.4 μs | 57.38 μs | 3.15 μs | 174.8 μs | 180.8 μs | 179.5 μs | 180.6 μs |  1.03 |    0.02 |     415 B |        2.26 |
Respire_Set_Medium            | 177.1 μs | 12.67 μs | 0.69 μs | 176.3 μs | 177.7 μs | 177.1 μs | 177.6 μs |  1.02 |    0.00 |     176 B |        0.96 |
StackExchange_Set_Medium      | 181.8 μs | 14.92 μs | 0.82 μs | 180.9 μs | 182.3 μs | 182.3 μs | 182.3 μs |  1.05 |    0.00 |     416 B |        2.26 |
Respire_Set_Large             | 180.1 μs | 12.95 μs | 0.71 μs | 179.5 μs | 180.9 μs | 179.8 μs | 180.8 μs |  1.04 |    0.00 |     176 B |        0.96 |
StackExchange_Set_Large       | 188.5 μs | 26.55 μs | 1.46 μs | 186.9 μs | 189.5 μs | 189.2 μs | 189.5 μs |  1.08 |    0.01 |     416 B |        2.26 |
Respire_Get                   | 176.0 μs | 17.03 μs | 0.93 μs | 175.0 μs | 176.8 μs | 176.1 μs | 176.8 μs |  1.01 |    0.00 |     222 B |        1.21 |
StackExchange_Get             | 178.1 μs | 40.80 μs | 2.24 μs | 176.5 μs | 180.6 μs | 177.1 μs | 180.3 μs |  1.02 |    0.01 |     424 B |        2.30 |
StackExchange_MGet            | 182.0 μs | 49.42 μs | 2.71 μs | 178.9 μs | 183.8 μs | 183.2 μs | 183.8 μs |  1.05 |    0.01 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 199.2 μs | 28.17 μs | 1.54 μs | 197.4 μs | 200.3 μs | 199.8 μs | 200.3 μs |  1.14 |    0.01 |    2888 B |       15.70 |
Respire_Exists                | 173.4 μs | 26.79 μs | 1.47 μs | 171.7 μs | 174.3 μs | 174.1 μs | 174.3 μs |  1.00 |    0.01 |     175 B |        0.95 |
StackExchange_Exists          | 177.0 μs | 34.66 μs | 1.90 μs | 174.8 μs | 178.1 μs | 178.1 μs | 178.1 μs |  1.02 |    0.01 |     400 B |        2.17 |
Respire_Del                   | 335.1 μs | 29.82 μs | 1.63 μs | 333.2 μs | 336.3 μs | 335.8 μs | 336.2 μs |  1.93 |    0.01 |     200 B |        1.09 |
StackExchange_Del             | 335.1 μs | 18.46 μs | 1.01 μs | 334.2 μs | 336.2 μs | 334.8 μs | 336.0 μs |  1.93 |    0.01 |     648 B |        3.52 |
Respire_Incr                  | 175.8 μs |  5.62 μs | 0.31 μs | 175.6 μs | 176.1 μs | 175.7 μs | 176.1 μs |  1.01 |    0.00 |     184 B |        1.00 |
StackExchange_Incr            | 177.7 μs | 22.67 μs | 1.24 μs | 176.3 μs | 178.6 μs | 178.3 μs | 178.6 μs |  1.02 |    0.01 |     400 B |        2.17 |
Respire_Transaction_2         | 178.5 μs |  9.93 μs | 0.54 μs | 178.1 μs | 179.1 μs | 178.1 μs | 179.0 μs |  1.03 |    0.00 |    1071 B |        5.82 |

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net8.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 102.1 μs 61.75 μs 3.38 μs 99.97 μs 106.0 μs 100.2 μs 105.4 μs 1.00 0.04 183 B 1.00
StackExchange_Ping 105.1 μs 9.27 μs 0.51 μs 104.54 μs 105.5 μs 105.1 μs 105.5 μs 1.03 0.03 407 B 2.22
Respire_Set_Small 102.5 μs 13.11 μs 0.72 μs 101.74 μs 103.1 μs 102.8 μs 103.1 μs 1.01 0.03 176 B 0.96
StackExchange_Set_Small 104.1 μs 25.48 μs 1.40 μs 102.48 μs 105.1 μs 104.6 μs 105.1 μs 1.02 0.03 416 B 2.27
Respire_Set_Medium 102.5 μs 7.59 μs 0.42 μs 102.08 μs 102.9 μs 102.6 μs 102.9 μs 1.01 0.03 176 B 0.96
StackExchange_Set_Medium 103.1 μs 194.36 μs 10.65 μs 91.61 μs 112.7 μs 105.0 μs 111.9 μs 1.01 0.09 416 B 2.27
Respire_Set_Large 107.3 μs 14.24 μs 0.78 μs 106.77 μs 108.2 μs 106.9 μs 108.0 μs 1.05 0.03 175 B 0.96
StackExchange_Set_Large 112.6 μs 6.10 μs 0.33 μs 112.23 μs 112.9 μs 112.6 μs 112.9 μs 1.10 0.03 416 B 2.27
Respire_Get 102.5 μs 4.64 μs 0.25 μs 102.28 μs 102.7 μs 102.3 μs 102.7 μs 1.00 0.03 224 B 1.22
StackExchange_Get 102.5 μs 15.89 μs 0.87 μs 101.54 μs 103.3 μs 102.6 μs 103.2 μs 1.00 0.03 424 B 2.32
StackExchange_MGet 107.1 μs 13.46 μs 0.74 μs 106.43 μs 107.9 μs 107.1 μs 107.8 μs 1.05 0.03 656 B 3.58
StackExchange_Pipeline_5_Sets 126.8 μs 179.85 μs 9.86 μs 118.94 μs 137.8 μs 123.5 μs 136.4 μs 1.24 0.09 2888 B 15.78
Respire_Exists 101.9 μs 32.71 μs 1.79 μs 100.55 μs 103.9 μs 101.1 μs 103.6 μs 1.00 0.03 176 B 0.96
StackExchange_Exists 100.4 μs 26.24 μs 1.44 μs 99.01 μs 101.9 μs 100.4 μs 101.7 μs 0.98 0.03 399 B 2.18
Respire_Del 187.4 μs 78.05 μs 4.28 μs 183.44 μs 191.9 μs 186.8 μs 191.4 μs 1.84 0.06 199 B 1.09
StackExchange_Del 201.0 μs 41.40 μs 2.27 μs 199.05 μs 203.5 μs 200.6 μs 203.2 μs 1.97 0.06 648 B 3.54
Respire_Incr 101.9 μs 16.05 μs 0.88 μs 100.90 μs 102.6 μs 102.1 μs 102.6 μs 1.00 0.03 184 B 1.01
StackExchange_Incr 101.3 μs 26.03 μs 1.43 μs 99.65 μs 102.4 μs 101.8 μs 102.3 μs 0.99 0.03 399 B 2.18
Respire_Transaction_2 104.2 μs 19.05 μs 1.04 μs 102.99 μs 104.9 μs 104.6 μs 104.9 μs 1.02 0.03 1063 B 5.81
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error     | StdDev   | Min       | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|----------:|---------:|----------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 102.1 μs |  61.75 μs |  3.38 μs |  99.97 μs | 106.0 μs | 100.2 μs | 105.4 μs |  1.00 |    0.04 |     183 B |        1.00 |
StackExchange_Ping            | 105.1 μs |   9.27 μs |  0.51 μs | 104.54 μs | 105.5 μs | 105.1 μs | 105.5 μs |  1.03 |    0.03 |     407 B |        2.22 |
Respire_Set_Small             | 102.5 μs |  13.11 μs |  0.72 μs | 101.74 μs | 103.1 μs | 102.8 μs | 103.1 μs |  1.01 |    0.03 |     176 B |        0.96 |
StackExchange_Set_Small       | 104.1 μs |  25.48 μs |  1.40 μs | 102.48 μs | 105.1 μs | 104.6 μs | 105.1 μs |  1.02 |    0.03 |     416 B |        2.27 |
Respire_Set_Medium            | 102.5 μs |   7.59 μs |  0.42 μs | 102.08 μs | 102.9 μs | 102.6 μs | 102.9 μs |  1.01 |    0.03 |     176 B |        0.96 |
StackExchange_Set_Medium      | 103.1 μs | 194.36 μs | 10.65 μs |  91.61 μs | 112.7 μs | 105.0 μs | 111.9 μs |  1.01 |    0.09 |     416 B |        2.27 |
Respire_Set_Large             | 107.3 μs |  14.24 μs |  0.78 μs | 106.77 μs | 108.2 μs | 106.9 μs | 108.0 μs |  1.05 |    0.03 |     175 B |        0.96 |
StackExchange_Set_Large       | 112.6 μs |   6.10 μs |  0.33 μs | 112.23 μs | 112.9 μs | 112.6 μs | 112.9 μs |  1.10 |    0.03 |     416 B |        2.27 |
Respire_Get                   | 102.5 μs |   4.64 μs |  0.25 μs | 102.28 μs | 102.7 μs | 102.3 μs | 102.7 μs |  1.00 |    0.03 |     224 B |        1.22 |
StackExchange_Get             | 102.5 μs |  15.89 μs |  0.87 μs | 101.54 μs | 103.3 μs | 102.6 μs | 103.2 μs |  1.00 |    0.03 |     424 B |        2.32 |
StackExchange_MGet            | 107.1 μs |  13.46 μs |  0.74 μs | 106.43 μs | 107.9 μs | 107.1 μs | 107.8 μs |  1.05 |    0.03 |     656 B |        3.58 |
StackExchange_Pipeline_5_Sets | 126.8 μs | 179.85 μs |  9.86 μs | 118.94 μs | 137.8 μs | 123.5 μs | 136.4 μs |  1.24 |    0.09 |    2888 B |       15.78 |
Respire_Exists                | 101.9 μs |  32.71 μs |  1.79 μs | 100.55 μs | 103.9 μs | 101.1 μs | 103.6 μs |  1.00 |    0.03 |     176 B |        0.96 |
StackExchange_Exists          | 100.4 μs |  26.24 μs |  1.44 μs |  99.01 μs | 101.9 μs | 100.4 μs | 101.7 μs |  0.98 |    0.03 |     399 B |        2.18 |
Respire_Del                   | 187.4 μs |  78.05 μs |  4.28 μs | 183.44 μs | 191.9 μs | 186.8 μs | 191.4 μs |  1.84 |    0.06 |     199 B |        1.09 |
StackExchange_Del             | 201.0 μs |  41.40 μs |  2.27 μs | 199.05 μs | 203.5 μs | 200.6 μs | 203.2 μs |  1.97 |    0.06 |     648 B |        3.54 |
Respire_Incr                  | 101.9 μs |  16.05 μs |  0.88 μs | 100.90 μs | 102.6 μs | 102.1 μs | 102.6 μs |  1.00 |    0.03 |     184 B |        1.01 |
StackExchange_Incr            | 101.3 μs |  26.03 μs |  1.43 μs |  99.65 μs | 102.4 μs | 101.8 μs | 102.3 μs |  0.99 |    0.03 |     399 B |        2.18 |
Respire_Transaction_2         | 104.2 μs |  19.05 μs |  1.04 μs | 102.99 μs | 104.9 μs | 104.6 μs | 104.9 μs |  1.02 |    0.03 |    1063 B |        5.81 |

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a1f0f36f1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

ReadOnlySpan<string> inlineArguments,
ReadOnlySpan<RespireValue> arguments)
{
var behavior = RespireCommand.Classify(operation);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Recognize multiplexed CLIENT subcommands

When raw fire-and-forget is invoked as ExecuteFireAndForgetAsync("CLIENT LIST") or ("CLIENT", "HELP"), parsing leaves operation as CLIENT, so this classifies the command as connection-scoped and throws. The catalog intentionally classifies exact commands such as CLIENT LIST, CLIENT HELP, CLIENT KILL, and CLIENT UNBLOCK as multiplexed and accepts their fire-and-forget forms, so valid raw commands are rejected solely because of the API shape. Inspect the inline or first supplied CLIENT subcommand before applying the affinity check, as is already done for SCRIPT.

Useful? React with 👍 / 👎.

Comment thread src/Respire/RespireClient.cs Outdated
var (operation, words, firstArgumentIndex) = ParseRawCommand(command);
ValidateRawFireAndForgetCommand(
operation, words.AsSpan(firstArgumentIndex), args);
var (_, commandValue) = CreateRawCommand(operation, words, firstArgumentIndex, args);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Pass stored-procedure names through fire-and-forget telemetry

When telemetry is enabled for a raw fire-and-forget EVALSHA or FCALL, this discards the stored-procedure name returned by CreateRawCommand; the catalog fire-and-forget path similarly never computes it. The downstream instrumentation therefore names every activity only EVALSHA/FCALL and omits db.stored_procedure.name from both spans and measurements, unlike the equivalent result-returning APIs, so production telemetry can no longer distinguish scripts or functions. Thread the derived name through the fire-and-forget send and instrumentation helpers.

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net10.0)

ℹ️ Execution Details

  • Framework: net10.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T04:20:48.150Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Integration Test Results (net8.0)

ℹ️ Execution Details

  • Framework: net8.0
  • Test Runner: TUnit
  • Runner: Linux - X64
  • Status: success
  • Timestamp: 2026-08-10T04:21:00.363Z

Automated integration testing with Redis containers using TUnit

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net10.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 125.1 μs 15.34 μs 0.84 μs 124.16 μs 125.8 μs 125.3 μs 125.7 μs 1.00 0.01 177 B 1.00
StackExchange_Ping 114.1 μs 112.10 μs 6.14 μs 109.13 μs 121.0 μs 112.3 μs 120.1 μs 0.91 0.04 392 B 2.21
Respire_Set_Small 131.0 μs 72.33 μs 3.96 μs 127.42 μs 135.2 μs 130.2 μs 134.7 μs 1.05 0.03 170 B 0.96
StackExchange_Set_Small 116.2 μs 152.45 μs 8.36 μs 106.64 μs 122.1 μs 119.9 μs 121.9 μs 0.93 0.06 404 B 2.28
Respire_Set_Medium 134.4 μs 24.92 μs 1.37 μs 133.10 μs 135.8 μs 134.2 μs 135.7 μs 1.07 0.01 174 B 0.98
StackExchange_Set_Medium 115.2 μs 192.54 μs 10.55 μs 103.02 μs 121.8 μs 120.7 μs 121.7 μs 0.92 0.07 408 B 2.31
Respire_Set_Large 147.5 μs 39.66 μs 2.17 μs 146.16 μs 150.0 μs 146.3 μs 149.7 μs 1.18 0.02 175 B 0.99
StackExchange_Set_Large 132.8 μs 165.13 μs 9.05 μs 123.49 μs 141.6 μs 133.4 μs 140.8 μs 1.06 0.06 406 B 2.29
Respire_Get 122.8 μs 138.39 μs 7.59 μs 115.35 μs 130.5 μs 122.6 μs 129.7 μs 0.98 0.05 221 B 1.25
StackExchange_Get 120.5 μs 172.82 μs 9.47 μs 114.61 μs 131.4 μs 115.4 μs 129.8 μs 0.96 0.07 414 B 2.34
StackExchange_MGet 124.6 μs 83.62 μs 4.58 μs 119.33 μs 127.6 μs 126.9 μs 127.5 μs 1.00 0.03 647 B 3.66
StackExchange_Pipeline_5_Sets 156.1 μs 62.67 μs 3.44 μs 152.55 μs 159.4 μs 156.2 μs 159.1 μs 1.25 0.02 2882 B 16.28
Respire_Exists 132.1 μs 42.18 μs 2.31 μs 129.77 μs 134.4 μs 132.1 μs 134.2 μs 1.06 0.02 162 B 0.92
StackExchange_Exists 110.6 μs 94.03 μs 5.15 μs 107.20 μs 116.5 μs 108.0 μs 115.6 μs 0.88 0.04 380 B 2.15
Respire_Del 237.9 μs 204.62 μs 11.22 μs 225.61 μs 247.5 μs 240.7 μs 246.9 μs 1.90 0.08 200 B 1.13
StackExchange_Del 250.1 μs 152.57 μs 8.36 μs 244.51 μs 259.7 μs 246.1 μs 258.4 μs 2.00 0.06 646 B 3.65
Respire_Incr 125.7 μs 69.50 μs 3.81 μs 121.99 μs 129.6 μs 125.5 μs 129.2 μs 1.01 0.03 182 B 1.03
StackExchange_Incr 112.6 μs 252.28 μs 13.83 μs 96.61 μs 120.9 μs 120.2 μs 120.8 μs 0.90 0.10 385 B 2.18
Respire_Transaction_2 139.3 μs 106.33 μs 5.83 μs 132.84 μs 144.1 μs 141.1 μs 143.8 μs 1.11 0.04 1069 B 6.04
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v3

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean     | Error     | StdDev   | Min       | Max      | Median   | P95      | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |---------:|----------:|---------:|----------:|---------:|---------:|---------:|------:|--------:|----------:|------------:|
Respire_Ping                  | 125.1 μs |  15.34 μs |  0.84 μs | 124.16 μs | 125.8 μs | 125.3 μs | 125.7 μs |  1.00 |    0.01 |     177 B |        1.00 |
StackExchange_Ping            | 114.1 μs | 112.10 μs |  6.14 μs | 109.13 μs | 121.0 μs | 112.3 μs | 120.1 μs |  0.91 |    0.04 |     392 B |        2.21 |
Respire_Set_Small             | 131.0 μs |  72.33 μs |  3.96 μs | 127.42 μs | 135.2 μs | 130.2 μs | 134.7 μs |  1.05 |    0.03 |     170 B |        0.96 |
StackExchange_Set_Small       | 116.2 μs | 152.45 μs |  8.36 μs | 106.64 μs | 122.1 μs | 119.9 μs | 121.9 μs |  0.93 |    0.06 |     404 B |        2.28 |
Respire_Set_Medium            | 134.4 μs |  24.92 μs |  1.37 μs | 133.10 μs | 135.8 μs | 134.2 μs | 135.7 μs |  1.07 |    0.01 |     174 B |        0.98 |
StackExchange_Set_Medium      | 115.2 μs | 192.54 μs | 10.55 μs | 103.02 μs | 121.8 μs | 120.7 μs | 121.7 μs |  0.92 |    0.07 |     408 B |        2.31 |
Respire_Set_Large             | 147.5 μs |  39.66 μs |  2.17 μs | 146.16 μs | 150.0 μs | 146.3 μs | 149.7 μs |  1.18 |    0.02 |     175 B |        0.99 |
StackExchange_Set_Large       | 132.8 μs | 165.13 μs |  9.05 μs | 123.49 μs | 141.6 μs | 133.4 μs | 140.8 μs |  1.06 |    0.06 |     406 B |        2.29 |
Respire_Get                   | 122.8 μs | 138.39 μs |  7.59 μs | 115.35 μs | 130.5 μs | 122.6 μs | 129.7 μs |  0.98 |    0.05 |     221 B |        1.25 |
StackExchange_Get             | 120.5 μs | 172.82 μs |  9.47 μs | 114.61 μs | 131.4 μs | 115.4 μs | 129.8 μs |  0.96 |    0.07 |     414 B |        2.34 |
StackExchange_MGet            | 124.6 μs |  83.62 μs |  4.58 μs | 119.33 μs | 127.6 μs | 126.9 μs | 127.5 μs |  1.00 |    0.03 |     647 B |        3.66 |
StackExchange_Pipeline_5_Sets | 156.1 μs |  62.67 μs |  3.44 μs | 152.55 μs | 159.4 μs | 156.2 μs | 159.1 μs |  1.25 |    0.02 |    2882 B |       16.28 |
Respire_Exists                | 132.1 μs |  42.18 μs |  2.31 μs | 129.77 μs | 134.4 μs | 132.1 μs | 134.2 μs |  1.06 |    0.02 |     162 B |        0.92 |
StackExchange_Exists          | 110.6 μs |  94.03 μs |  5.15 μs | 107.20 μs | 116.5 μs | 108.0 μs | 115.6 μs |  0.88 |    0.04 |     380 B |        2.15 |
Respire_Del                   | 237.9 μs | 204.62 μs | 11.22 μs | 225.61 μs | 247.5 μs | 240.7 μs | 246.9 μs |  1.90 |    0.08 |     200 B |        1.13 |
StackExchange_Del             | 250.1 μs | 152.57 μs |  8.36 μs | 244.51 μs | 259.7 μs | 246.1 μs | 258.4 μs |  2.00 |    0.06 |     646 B |        3.65 |
Respire_Incr                  | 125.7 μs |  69.50 μs |  3.81 μs | 121.99 μs | 129.6 μs | 125.5 μs | 129.2 μs |  1.01 |    0.03 |     182 B |        1.03 |
StackExchange_Incr            | 112.6 μs | 252.28 μs | 13.83 μs |  96.61 μs | 120.9 μs | 120.2 μs | 120.8 μs |  0.90 |    0.10 |     385 B |        2.18 |
Respire_Transaction_2         | 139.3 μs | 106.33 μs |  5.83 μs | 132.84 μs | 144.1 μs | 141.1 μs | 143.8 μs |  1.11 |    0.04 |    1069 B |        6.04 |

@github-actions

Copy link
Copy Markdown
Contributor

Redis Container Benchmark Results (net8.0)

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host] : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4

Runtime=.NET 8.0 IterationCount=3 WarmupCount=1

Method Mean Error StdDev Min Max Median P95 Ratio RatioSD Allocated Alloc Ratio
Respire_Ping 98.24 μs 12.750 μs 0.699 μs 97.44 μs 98.76 μs 98.50 μs 98.74 μs 1.00 0.01 184 B 1.00
StackExchange_Ping 100.86 μs 22.408 μs 1.228 μs 99.73 μs 102.17 μs 100.68 μs 102.02 μs 1.03 0.01 408 B 2.22
Respire_Set_Small 98.61 μs 17.576 μs 0.963 μs 97.51 μs 99.27 μs 99.06 μs 99.25 μs 1.00 0.01 176 B 0.96
StackExchange_Set_Small 99.44 μs 35.882 μs 1.967 μs 97.95 μs 101.67 μs 98.71 μs 101.37 μs 1.01 0.02 416 B 2.26
Respire_Set_Medium 102.52 μs 21.085 μs 1.156 μs 101.67 μs 103.83 μs 102.05 μs 103.65 μs 1.04 0.01 176 B 0.96
StackExchange_Set_Medium 103.71 μs 12.283 μs 0.673 μs 102.95 μs 104.21 μs 103.98 μs 104.19 μs 1.06 0.01 416 B 2.26
Respire_Set_Large 104.74 μs 28.130 μs 1.542 μs 102.97 μs 105.80 μs 105.44 μs 105.77 μs 1.07 0.02 175 B 0.95
StackExchange_Set_Large 111.47 μs 8.482 μs 0.465 μs 110.95 μs 111.85 μs 111.61 μs 111.83 μs 1.13 0.01 416 B 2.26
Respire_Get 98.44 μs 7.405 μs 0.406 μs 98.04 μs 98.85 μs 98.44 μs 98.81 μs 1.00 0.01 224 B 1.22
StackExchange_Get 101.37 μs 30.683 μs 1.682 μs 99.44 μs 102.52 μs 102.14 μs 102.48 μs 1.03 0.02 424 B 2.30
StackExchange_MGet 104.92 μs 28.121 μs 1.541 μs 103.26 μs 106.30 μs 105.21 μs 106.19 μs 1.07 0.02 656 B 3.57
StackExchange_Pipeline_5_Sets 116.11 μs 47.237 μs 2.589 μs 114.31 μs 119.08 μs 114.96 μs 118.67 μs 1.18 0.02 2888 B 15.70
Respire_Exists 98.83 μs 6.436 μs 0.353 μs 98.44 μs 99.12 μs 98.94 μs 99.10 μs 1.01 0.01 175 B 0.95
StackExchange_Exists 99.24 μs 19.190 μs 1.052 μs 98.03 μs 99.93 μs 99.76 μs 99.92 μs 1.01 0.01 400 B 2.17
Respire_Del 180.02 μs 83.281 μs 4.565 μs 174.98 μs 183.88 μs 181.19 μs 183.61 μs 1.83 0.04 200 B 1.09
StackExchange_Del 186.95 μs 38.800 μs 2.127 μs 184.84 μs 189.10 μs 186.90 μs 188.88 μs 1.90 0.02 647 B 3.52
Respire_Incr 98.18 μs 21.636 μs 1.186 μs 96.87 μs 99.16 μs 98.52 μs 99.10 μs 1.00 0.01 184 B 1.00
StackExchange_Incr 98.28 μs 17.271 μs 0.947 μs 97.48 μs 99.33 μs 98.04 μs 99.20 μs 1.00 0.01 400 B 2.17
Respire_Transaction_2 101.09 μs 9.084 μs 0.498 μs 100.76 μs 101.66 μs 100.84 μs 101.58 μs 1.03 0.01 1072 B 5.83
View raw benchmark output

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.302
[Host]     : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4
Job-YBPNYS : .NET 8.0.29 (8.0.29, 8.0.2926.32403), X64 RyuJIT x86-64-v4

Runtime=.NET 8.0  IterationCount=3  WarmupCount=1  

Method                        | Mean      | Error     | StdDev   | Min       | Max       | Median    | P95       | Ratio | RatioSD | Allocated | Alloc Ratio |
------------------------------ |----------:|----------:|---------:|----------:|----------:|----------:|----------:|------:|--------:|----------:|------------:|
Respire_Ping                  |  98.24 μs | 12.750 μs | 0.699 μs |  97.44 μs |  98.76 μs |  98.50 μs |  98.74 μs |  1.00 |    0.01 |     184 B |        1.00 |
StackExchange_Ping            | 100.86 μs | 22.408 μs | 1.228 μs |  99.73 μs | 102.17 μs | 100.68 μs | 102.02 μs |  1.03 |    0.01 |     408 B |        2.22 |
Respire_Set_Small             |  98.61 μs | 17.576 μs | 0.963 μs |  97.51 μs |  99.27 μs |  99.06 μs |  99.25 μs |  1.00 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Small       |  99.44 μs | 35.882 μs | 1.967 μs |  97.95 μs | 101.67 μs |  98.71 μs | 101.37 μs |  1.01 |    0.02 |     416 B |        2.26 |
Respire_Set_Medium            | 102.52 μs | 21.085 μs | 1.156 μs | 101.67 μs | 103.83 μs | 102.05 μs | 103.65 μs |  1.04 |    0.01 |     176 B |        0.96 |
StackExchange_Set_Medium      | 103.71 μs | 12.283 μs | 0.673 μs | 102.95 μs | 104.21 μs | 103.98 μs | 104.19 μs |  1.06 |    0.01 |     416 B |        2.26 |
Respire_Set_Large             | 104.74 μs | 28.130 μs | 1.542 μs | 102.97 μs | 105.80 μs | 105.44 μs | 105.77 μs |  1.07 |    0.02 |     175 B |        0.95 |
StackExchange_Set_Large       | 111.47 μs |  8.482 μs | 0.465 μs | 110.95 μs | 111.85 μs | 111.61 μs | 111.83 μs |  1.13 |    0.01 |     416 B |        2.26 |
Respire_Get                   |  98.44 μs |  7.405 μs | 0.406 μs |  98.04 μs |  98.85 μs |  98.44 μs |  98.81 μs |  1.00 |    0.01 |     224 B |        1.22 |
StackExchange_Get             | 101.37 μs | 30.683 μs | 1.682 μs |  99.44 μs | 102.52 μs | 102.14 μs | 102.48 μs |  1.03 |    0.02 |     424 B |        2.30 |
StackExchange_MGet            | 104.92 μs | 28.121 μs | 1.541 μs | 103.26 μs | 106.30 μs | 105.21 μs | 106.19 μs |  1.07 |    0.02 |     656 B |        3.57 |
StackExchange_Pipeline_5_Sets | 116.11 μs | 47.237 μs | 2.589 μs | 114.31 μs | 119.08 μs | 114.96 μs | 118.67 μs |  1.18 |    0.02 |    2888 B |       15.70 |
Respire_Exists                |  98.83 μs |  6.436 μs | 0.353 μs |  98.44 μs |  99.12 μs |  98.94 μs |  99.10 μs |  1.01 |    0.01 |     175 B |        0.95 |
StackExchange_Exists          |  99.24 μs | 19.190 μs | 1.052 μs |  98.03 μs |  99.93 μs |  99.76 μs |  99.92 μs |  1.01 |    0.01 |     400 B |        2.17 |
Respire_Del                   | 180.02 μs | 83.281 μs | 4.565 μs | 174.98 μs | 183.88 μs | 181.19 μs | 183.61 μs |  1.83 |    0.04 |     200 B |        1.09 |
StackExchange_Del             | 186.95 μs | 38.800 μs | 2.127 μs | 184.84 μs | 189.10 μs | 186.90 μs | 188.88 μs |  1.90 |    0.02 |     647 B |        3.52 |
Respire_Incr                  |  98.18 μs | 21.636 μs | 1.186 μs |  96.87 μs |  99.16 μs |  98.52 μs |  99.10 μs |  1.00 |    0.01 |     184 B |        1.00 |
StackExchange_Incr            |  98.28 μs | 17.271 μs | 0.947 μs |  97.48 μs |  99.33 μs |  98.04 μs |  99.20 μs |  1.00 |    0.01 |     400 B |        2.17 |
Respire_Transaction_2         | 101.09 μs |  9.084 μs | 0.498 μs | 100.76 μs | 101.66 μs | 100.84 μs | 101.58 μs |  1.03 |    0.01 |    1072 B |        5.83 |

@thomhurst
thomhurst merged commit 764959e into main Aug 10, 2026
14 of 15 checks passed

This branch was previously deployed

1 inactive deployment
Pull Requests — 92a2e775 Deployed Aug 10, 2026 by thomhurst via modularpipeline #489
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.

1 participant