Skip to content

Conversation

@gimlichael
Copy link
Member

@gimlichael gimlichael commented Jan 23, 2026

This pull request updates CI pipeline configurations, documentation build images, and release notes across the project. The main focus is on ensuring compatibility with newer platforms and dependencies, improving benchmark and NuGet automation, and maintaining up-to-date documentation and metadata.

CI/CD and Platform Support:

  • Expanded CI test matrix to include windows-2025, windows-11-arm, and ubuntu-24.04-arm for broader platform coverage in the pipeline configuration (.github/workflows/ci-pipeline.yml).
  • Renamed the workflow to Savvy I/O CI Pipeline for clarity and updated job matrices for functional tests to use the new platforms. [1] [2]

Documentation and Build System:

  • Upgraded the DocFX Docker image and NGINX base image to their latest patch versions for improved security and compatibility (.docfx/Dockerfile.docfx).
  • Added new external cross-reference sources in docfx.json to enhance documentation linking, and updated copyright year to 2026. [1] [2]

Automation Prompts:

  • Introduced a new benchmark fixture prompt for consistent BenchmarkDotNet usage, detailing naming, structure, and best practices (.github/prompts/benchmark.prompt.md).
  • Added a NuGet release notes automation prompt to standardize how release blocks are prepended to .nuget/**/PackageReleaseNotes.txt files, with strict formatting and versioning instructions (.github/prompts/nuget.prompt.md).

Release Notes Updates:

Summary by CodeRabbit

  • New Features

    • Released v5.0.1 with official Availability for .NET 10 and .NET 9.
  • Bug Fixes & Updates

    • Wide dependency version upgrades across core and extension packages.
  • Documentation

    • Expanded testing/benchmarking guidance, added xref sources and many per-package release notes; updated global footer year to 2026.
  • Chores

    • Updated container images, expanded CI matrix, swapped solution format, adjusted build/versioning settings and package release notes handling.
  • Tests

    • Hardened NATS functional tests for concurrency, determinism and stability.

✏️ Tip: You can customize this high-level summary in your review settings.

@gimlichael gimlichael self-assigned this Jan 23, 2026
Copilot AI review requested due to automatic review settings January 23, 2026 19:14
@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Repository-wide maintenance: bulk dependency version bumps, many 5.0.1 release-note insertions, CI/build/docfx/docker image updates, solution file replacement (.sln → .slnx), new GitHub prompts/docs, MSBuild target/prop tweaks, and robustness improvements to NATS functional tests.

Changes

Cohort / File(s) Summary
Images & infra
\.docfx/Dockerfile.docfx, Dockerfile.localstack, docker-compose.yml, testenvironments.json
Bumped base/build image tags (nginx/docfx, localstack, awscli, test-runner); no build-step logic changes.
DocFX config
\.docfx/docfx.json
Added three xref sources, removed Microsoft xrefService entry, updated footer year to 2021–2026.
CI workflow
.github/workflows/ci-pipeline.yml
Renamed workflow, removed paths-ignore, expanded OS matrix (added Windows-2025 and ARM variants).
GitHub guidance & prompts
.github/copilot-instructions.md, .github/prompts/benchmark.prompt.md, .github/prompts/nuget.prompt.md
Large rewrite of Copilot guidance; added benchmark and deterministic nuget prompt files with conventions and examples.
Central package pins
Directory.Packages.props
Bulk package version upgrades (MinVer, NATS.Client*, xunit.v3, EF Core, Cuemon.*, System.Linq.Async, etc.).
MSBuild props & targets
Directory.Build.props, Directory.Build.targets
Props: added PackageReleaseNotesFile and updated copyright year. Targets: removed top-level PackageReleaseNotesFile and added ApplyFileVersion target computing FileVersion from MinVer + GITHUB_RUN_NUMBER.
Solution files
Savvyio.sln, Savvyio.slnx
Removed legacy Savvyio.sln; added Savvyio.slnx enumerating projects under /src and /test.
Release notes & changelog
.nuget/.../PackageReleaseNotes.txt (many), CHANGELOG.md, LICENSE.md, Directory.Build.props
Prepended Version 5.0.1 entries (Availability: .NET 10/.NET 9) and ALM notes about dependency upgrades across many packages; updated CHANGELOG and LICENSE year; minor EOF/whitespace fixes.
NATS functional tests
test/.../NatsCommandQueueJsonSerializerContextTest.cs, test/.../NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs
Replaced static names with GUIDs, added Interlocked counters, increased setup delays, moved sleeps to timeout-based polling, added concurrent receivers and stronger assertions.
Misc build/test env
Dockerfile.localstack, testenvironments.json, Directory.Build.targets
Image tag updates and new FileVersion target; removed duplicated PackageReleaseNotesFile property from targets.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through manifests, bump by bump,
Pins and images left my thumpity-thump.
Solutions shuffled, changelogs gleam,
CI widened paths to race the stream,
Carrots for deps — the repo’s dream!

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'V5.0.1/service update' directly summarizes the main change: releasing version 5.0.1 as a service update focusing on dependency upgrades.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Savvyio project to version 5.0.1, focusing on dependency upgrades, CI/CD platform expansion, and documentation improvements. The update maintains compatibility with .NET 10 and .NET 9 while modernizing the development infrastructure.

Changes:

  • Upgraded all package dependencies to latest compatible versions across all supported target frameworks
  • Expanded CI test matrix to include new platforms (Windows 2025, Ubuntu 24.04 ARM, Windows 11 ARM)
  • Updated documentation infrastructure (DocFX, NGINX images, cross-reference sources)
  • Migrated solution format from .sln to .slnx (Visual Studio 2022+ XML format)
  • Added automation prompts for benchmarking and NuGet release notes
  • Updated copyright year to 2026

Reviewed changes

Copilot reviewed 51 out of 51 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Directory.Packages.props Updated dependency versions for Cuemon, AWS SDK, Azure, NATS, xUnit, MinVer, and EF Core packages
Directory.Build.props Moved PackageReleaseNotesFile property definition and updated copyright year
Directory.Build.targets Removed PackageReleaseNotesFile property definition (moved to props)
.github/workflows/ci-pipeline.yml Renamed workflow, added ARM runner support, removed paths-ignore filter
.github/copilot-instructions.md Updated unit test and benchmark guidance with namespace requirements and xUnit v3 notes
.github/prompts/benchmark.prompt.md Added comprehensive benchmark fixture writing guidelines
.github/prompts/nuget.prompt.md Added automation prompt for NuGet release notes updates
.nuget/**/PackageReleaseNotes.txt Prepended version 5.0.1 release notes to all 29 package files
.docfx/docfx.json Replaced xrefService with static xref files, updated copyright year
.docfx/Dockerfile.docfx Updated DocFX and NGINX base images to latest versions
CHANGELOG.md Added version 5.0.1 entry
LICENSE.md Updated copyright year to 2026
Savvyio.sln Deleted traditional solution file
Savvyio.slnx Added new XML-based solution file format
testenvironments.json Updated Ubuntu test runner Docker image version
docker-compose.yml Updated LocalStack and AWS CLI image versions
Dockerfile.localstack Updated LocalStack base image version
Comments suppressed due to low confidence (2)

.github/workflows/ci-pipeline.yml:72

  • The CI pipeline now includes ARM-based runners (ubuntu-24.04-arm and windows-11-arm) in the test matrix. Before merging, verify that these GitHub-hosted runners are available for your organization/account. As of early 2025, ARM runners on GitHub Actions may have limited availability or require specific plans/permissions. If these runners are not available, the CI pipeline will fail.

Consider:

  1. Verifying runner availability with GitHub documentation or your organization's settings
  2. Testing this change in a separate PR or branch first
  3. Potentially making these runners conditional or opt-in until confirmed available
    .github/workflows/ci-pipeline.yml:4
  • The paths-ignore configuration has been removed from the pull request trigger. Previously, changes to .codecov/**, .docfx/**, .nuget/**, and **/*.md files would not trigger CI runs.

Removing this filter means:

  • Documentation-only changes will now trigger full CI runs
  • Changes to release notes will trigger CI runs
  • This increases CI usage and may slow down documentation PRs

This change increases operational costs and CI wait times for documentation updates. Consider whether this is intentional or if the paths-ignore should be restored to optimize CI resource usage.

@@ -1,3 +1,9 @@
Version 5.0.1
Availability: .NET 10 and .NET 9
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

There is an extra space after the colon in "Availability: .NET 10" (two spaces instead of one). This appears consistently across all updated PackageReleaseNotes.txt files. For consistency with the existing format used in line 7 ("Availability: .NET 10"), line 2 should have only one space after the colon:

Availability: .NET 10 and .NET 9

This formatting inconsistency exists in all the updated release notes files.

Suggested change
Availability: .NET 10 and .NET 9
Availability: .NET 10 and .NET 9

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

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

⚠️ Outside diff range comments (1)
.nuget/Savvyio.Commands/PackageReleaseNotes.txt (1)

107-110: Remove stray “<----” marker from release notes.

This looks like an accidental annotation and should not ship in package release notes.

🧹 Proposed fix
-- ADDED MemoryCommandQueue class in the Savvyio.Commands.Messaging namespace that provides an in-memory implementation of the IPointToPointChannel{TRequest} interface useful for unit testing and the likes thereof  <----
+- ADDED MemoryCommandQueue class in the Savvyio.Commands.Messaging namespace that provides an in-memory implementation of the IPointToPointChannel{TRequest} interface useful for unit testing and the likes thereof
🤖 Fix all issues with AI agents
In @.github/prompts/nuget.prompt.md:
- Around line 10-28: Update the template fenced code block so it uses a plain
code fence (remove the "text" language specifier) and ensure the templated lines
remain exactly as shown (the block starting with "Version {{version}}" and the
"Availability: {{previous-tfm}}" line, preserving NBSP U+00A0 blank lines and
whitespace); edit the fenced block header from ```text to ``` and keep the rest
of the template content unchanged so grammar/lint issues are resolved.

In
@.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt:
- Around line 1-2: The "Version" line is missing the colon and should match the
existing "Key: Value" format; update the header from "Version 5.0.1" to
"Version: 5.0.1" so it follows the same "Key: Value" formatting pattern used by
"Availability:" and other entries in PackageReleaseNotes.txt.

In
@.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt:
- Around line 1-2: Update the release notes header to include the missing colon
so it matches the rest of the file; change the line "Version 5.0.1" to "Version:
5.0.1" in the PackageReleaseNotes content to keep the `Version:` header
consistent and avoid parser edge cases.

In @.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt:
- Around line 1-2: The release note header in PackageReleaseNotes.txt is
inconsistent: change the header from "Version 5.0.1" to "Version: 5.0.1" so it
matches the prior entries' "Version: ..." prefix; update the single line in the
file (the entry under Version/Availability) to use the "Version:" prefix for
consistent parsing.

In @.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt:
- Around line 1-2: Update the release notes header to match the established
"Version: <number>" format by adding the missing colon so the header reads
"Version: 5.0.1"; ensure the same "Version:" prefix style is used for this entry
(and any similar entries) to keep parsing consistent with existing release
notes.

In @.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt:
- Around line 1-2: The "Version 5.0.1" line in PackageReleaseNotes.txt is
missing the colon used elsewhere; update the entry so the header reads "Version:
5.0.1" to match the existing "Version:" format and keep parsers consistent
(ensure the rest of the line "Availability:  .NET 10 and .NET 9" is unchanged).

In @.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt:
- Around line 1-2: Update the release notes header to use the normalized
"Version:" label — replace the line "Version 5.0.1" with "Version: 5.0.1" in the
.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt file so it matches
the existing blocks and tooling expectations.
🧹 Nitpick comments (16)
.github/copilot-instructions.md (1)

50-61: Tighten wording: “exact same” → “same”.
Minor style polish; reduces wordiness without changing meaning.

✏️ Proposed wording tweak
- - Use namespaces that mirror the source code structure. The namespace of a test file MUST match the namespace of the System Under Test (SUT). Do NOT append ".Tests", ".Benchmarks" or similar suffixes to the namespace. Only the assembly/project name should indicate that the file is a test/benchmark (for example: YourProject.Foo.Tests assembly, but namespace YourProject.Foo).
+ - Use namespaces that mirror the source code structure. The namespace of a test file MUST match the namespace of the System Under Test (SUT). Do NOT append ".Tests", ".Benchmarks" or similar suffixes to the namespace. Only the assembly/project name should indicate that the file is a test/benchmark (for example: YourProject.Foo.Tests assembly, but namespace YourProject.Foo).
...
-         then the corresponding unit test class must use the exact same namespace:
+         then the corresponding unit test class must use the same namespace:
Directory.Build.props (1)

7-7: Consider anchoring PackageReleaseNotesFile to $(MSBuildThisFileDirectory) for architectural clarity.

While the relative path ..\..\.nuget\... currently resolves correctly for all projects (all are 2 levels deep), using $(MSBuildThisFileDirectory) would remove the depth dependency and improve maintainability for potential future changes.

🔧 Suggested change
-    <PackageReleaseNotesFile>..\..\.nuget\$(MSBuildProjectName)\PackageReleaseNotes.txt</PackageReleaseNotesFile>
+    <PackageReleaseNotesFile>$(MSBuildThisFileDirectory).nuget\$(MSBuildProjectName)\PackageReleaseNotes.txt</PackageReleaseNotesFile>
docker-compose.yml (1)

3-13: Consider pinning images by digest for reproducibility.

The aws-cli 2.33.5 entrypoint syntax is compatible with the version update. However, for better reproducibility and to avoid unexpected upstream changes, consider pinning both localstack/localstack:4.12.0 and amazon/aws-cli:2.33.5 to their image digests.

.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt (1)

1-2: Normalize version/availability formatting for consistency.

New entry uses Version 5.0.1 (no colon) and double space after Availability: which differs from the rest of the file. Consider aligning with existing format.

♻️ Suggested formatting tweak
-Version 5.0.1
-Availability:  .NET 10 and .NET 9
+Version: 5.0.1
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Domain/PackageReleaseNotes.txt (1)

1-2: Standardize formatting to match existing convention.

The new version block has minor formatting inconsistencies compared to existing entries:

  • Line 1: Version 5.0.1 lacks a colon, while existing entries use Version: X.X.X
  • Line 2: Availability: .NET has two spaces after the colon, while existing entries use one space
✨ Suggested formatting fix
-Version 5.0.1
-Availability:  .NET 10 and .NET 9
+Version: 5.0.1
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt (1)

1-2: Standardize formatting to match existing convention.

The new version block has minor formatting inconsistencies compared to existing entries:

  • Line 1: Version 5.0.1 lacks a colon, while existing entries use Version: X.X.X
  • Line 2: Availability: .NET has two spaces after the colon, while existing entries use one space
✨ Suggested formatting fix
-Version 5.0.1
-Availability:  .NET 10 and .NET 9
+Version: 5.0.1
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt (1)

1-2: Standardize formatting to match existing convention.

The new version block has minor formatting inconsistencies compared to existing entries:

  • Line 1: Version 5.0.1 lacks a colon, while existing entries use Version: X.X.X
  • Line 2: Availability: .NET has two spaces after the colon, while existing entries use one space
✨ Suggested formatting fix
-Version 5.0.1
-Availability:  .NET 10 and .NET 9
+Version: 5.0.1
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt (1)

1-2: Standardize formatting to match existing convention.

The new version block has minor formatting inconsistencies compared to existing entries:

  • Line 1: Version 5.0.1 lacks a colon, while existing entries use Version: X.X.X
  • Line 2: Availability: .NET has two spaces after the colon, while existing entries use one space
✨ Suggested formatting fix
-Version 5.0.1
-Availability:  .NET 10 and .NET 9
+Version: 5.0.1
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt (1)

1-2: Standardize formatting to match existing convention.

The new version block has minor formatting inconsistencies compared to existing entries:

  • Line 1: Version 5.0.1 lacks a colon, while existing entries use Version: X.X.X
  • Line 2: Availability: .NET has two spaces after the colon, while existing entries use one space
✨ Suggested formatting fix
-Version 5.0.1
-Availability:  .NET 10 and .NET 9
+Version: 5.0.1
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Messaging/PackageReleaseNotes.txt (1)

1-2: Standardize formatting to match existing convention.

The new version block has minor formatting inconsistencies compared to existing entries:

  • Line 1: Version 5.0.1 lacks a colon, while existing entries use Version: X.X.X
  • Line 2: Availability: .NET has two spaces after the colon, while existing entries use one space
✨ Suggested formatting fix
-Version 5.0.1
-Availability:  .NET 10 and .NET 9
+Version: 5.0.1
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt (1)

2-2: Minor formatting inconsistency: extra space after "Availability:".

Line 2 has two spaces after the colon (Availability: .NET), while the Version 5.0.0 entry on Line 8 uses a single space. Consider standardizing to one space for consistency.

✨ Suggested formatting fix
-Availability:  .NET 10 and .NET 9
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/PackageReleaseNotes.txt (1)

2-2: Minor formatting inconsistency: extra space after "Availability:".

Same as in other files, this line has two spaces after the colon. Consider standardizing to one space to match the Version 5.0.0 entry format.

.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt (1)

2-2: Minor formatting inconsistency: extra space after "Availability:".

Consider standardizing the spacing to match the existing Version 5.0.0 format (single space after colon).

.nuget/Savvyio.App/PackageReleaseNotes.txt (1)

2-2: Minor formatting inconsistency: extra space after "Availability:".

Consider standardizing to one space after the colon to match the existing Version 5.0.0 format on Line 36.

.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/PackageReleaseNotes.txt (1)

2-2: Minor formatting inconsistency: extra space after "Availability:".

Consider standardizing the spacing to match existing entries (single space after colon).

.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt (1)

2-2: Minor formatting inconsistency: extra space after "Availability:".

Consider standardizing to one space after the colon to match the Version 5.0.0 format on Line 8.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (2)
test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs (1)

157-197: Synchronize cross-thread counters to avoid flaky timeout assertions.

count1 and count2 are updated in background tasks and read on the test thread without memory barriers. This can cause the test thread to observe stale values, making the timeout loop and final assertion non-deterministic. Use Interlocked.Increment for updates and Volatile.Read for reads to ensure visibility.

🔧 Suggested fix
-                        count1++;
+                        System.Threading.Interlocked.Increment(ref count1);
...
-                        count2++;
+                        System.Threading.Interlocked.Increment(ref count2);
...
-            while ((count1 + count2) < messages.Count && (DateTime.UtcNow - start) < timeout)
+            while ((System.Threading.Volatile.Read(ref count1) + System.Threading.Volatile.Read(ref count2)) < messages.Count
+                   && (DateTime.UtcNow - start) < timeout)
             {
                 await Task.Delay(10);
             }
...
-            Assert.Equal(messages.Count, count1 + count2);
+            Assert.Equal(messages.Count,
+                System.Threading.Volatile.Read(ref count1) + System.Threading.Volatile.Read(ref count2));
test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs (1)

156-198: Synchronize cross-thread counters to avoid non-deterministic test failures.

The timeout loop at lines 192-197 reads count1 and count2 without synchronization while background tasks update them; this violates the requirement that tests be "deterministic and repeatable" per the coding guidelines. Without explicit synchronization, the main thread may observe stale cached values, leading to intermittent failures. Use Interlocked.Increment for increments and Volatile.Read for timeout loop reads to ensure visibility of updates across threads.

Suggested fix
-                        count1++;
+                        System.Threading.Interlocked.Increment(ref count1);
...
-                        count2++;
+                        System.Threading.Interlocked.Increment(ref count2);
...
-            while ((count1 + count2) < messages.Count && (DateTime.UtcNow - start) < timeout)
+            while ((System.Threading.Volatile.Read(ref count1) + System.Threading.Volatile.Read(ref count2)) < messages.Count
+                   && (DateTime.UtcNow - start) < timeout)
             {
                 await Task.Delay(10);
             }
...
-            Assert.Equal(messages.Count, count1 + count2);
+            Assert.Equal(messages.Count,
+                System.Threading.Volatile.Read(ref count1) + System.Threading.Volatile.Read(ref count2));

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs (1)

158-205: Receiver loops deadlock on per-receiver message counts; fix CancellationToken passing syntax.

The test splits 100 messages between two receivers, each with its own count condition (count1 < messages.Count and count2 < messages.Count). If messages distribute unevenly (e.g., 60/40), both loops hang indefinitely waiting for their individual count to reach 100. Additionally, the receiver tasks are never awaited before receivedMessages.Writer.Complete(), risking ChannelClosedException if tasks write after channel closure.

Replace per-receiver counts with a shared Interlocked counter, pass CancellationToken via the AsyncOptions parameter (not directly), and await receiver tasks before completing the channel:

🐛 Suggested fix
            var receivedMessages = Channel.CreateUnbounded<IMessage<ICommand>>();
+           var totalReceived = 0;
+           using var cts = new CancellationTokenSource();
 
-            var count1 = 0;
-            Task.Run<Task>(async () =>
+            var receiver1 = Task.Run(async () =>
             {
-                while (count1 < messages.Count)
+                try
                 {
-                    await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false))
+                    await foreach (var msg in queue.ReceiveAsync(o => o.CancellationToken = cts.Token).ConfigureAwait(false))
                     {
-                        Interlocked.Increment(ref count1);
+                        var current = Interlocked.Increment(ref totalReceived);
                         await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false);
                         await msg.AcknowledgeAsync().ConfigureAwait(false);
+                        if (current >= messages.Count) { cts.Cancel(); }
                     }
                 }
+                catch (OperationCanceledException) { }
             });
 
-            var count2 = 0;
-            Task.Run<Task>(async () =>
+            var receiver2 = Task.Run(async () =>
             {
-                while (count2 < messages.Count)
+                try
                 {
-                    await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false))
+                    await foreach (var msg in queue.ReceiveAsync(o => o.CancellationToken = cts.Token).ConfigureAwait(false))
                     {
-                        Interlocked.Increment(ref count2);
+                        var current = Interlocked.Increment(ref totalReceived);
                         await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false);
                         await msg.AcknowledgeAsync().ConfigureAwait(false);
+                        if (current >= messages.Count) { cts.Cancel(); }
                     }
                 }
+                catch (OperationCanceledException) { }
             });
 
             await Task.Delay(2000); // wait briefly to ensure subscription setup
 
             await queue.SendAsync(messages).ConfigureAwait(false);
 
             // Wait for all messages to be received with a timeout
             var timeout = TimeSpan.FromSeconds(10);
             var start = DateTime.UtcNow;
-            while ((count1 + count2) < messages.Count && (DateTime.UtcNow - start) < timeout)
+            while (totalReceived < messages.Count && (DateTime.UtcNow - start) < timeout)
             {
                 await Task.Delay(10);
             }
 
-            Assert.Equal(messages.Count, count1 + count2);
+            Assert.Equal(messages.Count, totalReceived);
 
-            TestOutput.WriteLine(count1.ToString());
-            TestOutput.WriteLine(count2.ToString());
+            await Task.WhenAll(receiver1, receiver2);
             receivedMessages.Writer.Complete(); // mark channel write is complete
🤖 Fix all issues with AI agents
In
`@test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs`:
- Around line 165-166: The test increments shared counters with
Interlocked.Increment (e.g., count1/count2) but later reads them non-atomically
in the wait loops and assertions which can cause flaky results; update all reads
of count1 and count2 (the wait loop totals and final Assert checks in
NatsCommandQueueJsonSerializerContextTest) to perform atomic/volatile reads—use
Volatile.Read(ref count1)/Volatile.Read(ref count2) or Interlocked.Add(ref
count1, 0)/Interlocked.Add(ref count2, 0) wherever the code currently reads the
counters (including the loops around lines referenced and the final assertions)
so the observed totals are consistent across threads.

Comment on lines +165 to 166
Interlocked.Increment(ref count1);
await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Synchronize count reads to avoid flaky waits/asserts.
Interlocked.Increment is good, but the wait loop and final assertion read count1/count2 without a volatile/atomic read, which can observe stale values across threads. Use Volatile.Read (or Interlocked.Add(ref count, 0)) when computing totals.

✅ Suggested fix
-            while ((count1 + count2) < messages.Count && (DateTime.UtcNow - start) < timeout)
+            while ((Volatile.Read(ref count1) + Volatile.Read(ref count2)) < messages.Count && (DateTime.UtcNow - start) < timeout)
             {
                 await Task.Delay(10);
             }

-            Assert.Equal(messages.Count, count1 + count2);
+            var total = Volatile.Read(ref count1) + Volatile.Read(ref count2);
+            Assert.Equal(messages.Count, total);

Also applies to: 179-180, 190-198

🤖 Prompt for AI Agents
In
`@test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs`
around lines 165 - 166, The test increments shared counters with
Interlocked.Increment (e.g., count1/count2) but later reads them non-atomically
in the wait loops and assertions which can cause flaky results; update all reads
of count1 and count2 (the wait loop totals and final Assert checks in
NatsCommandQueueJsonSerializerContextTest) to perform atomic/volatile reads—use
Volatile.Read(ref count1)/Volatile.Read(ref count2) or Interlocked.Add(ref
count1, 0)/Interlocked.Add(ref count2, 0) wherever the code currently reads the
counters (including the loops around lines referenced and the final assertions)
so the observed totals are consistent across threads.

@github-advanced-security
Copy link

This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation.

@codecov
Copy link

codecov bot commented Jan 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.11%. Comparing base (8a1e386) to head (45173de).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #45   +/-   ##
=======================================
  Coverage   79.11%   79.11%           
=======================================
  Files         177      177           
  Lines        3711     3711           
  Branches      365      365           
=======================================
  Hits         2936     2936           
  Misses        774      774           
  Partials        1        1           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Fix all issues with AI agents
In @.nuget/Savvyio.App/PackageReleaseNotes.txt:
- Line 2: Normalize the spacing in the "Availability" line by replacing the
double space after the colon in the string "Availability:  .NET 10 and .NET 9"
with a single space so it reads "Availability: .NET 10 and .NET 9"; update that
exact line in PackageReleaseNotes.txt to maintain formatting consistency with
other entries.

In @.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt:
- Around line 1-3: Normalize the spacing and blank line in the release notes:
update the "Availability:  .NET 10 and .NET 9" line to use a single space after
the colon (e.g., "Availability: .NET 10 and .NET 9") and replace the
non-standard blank line (NBSP) following it with a standard empty newline so the
file uses normal ASCII whitespace; edit the lines containing "Version: 5.0.1"
and "Availability:" to ensure consistent spacing and a regular blank line
separator.

In @.nuget/Savvyio.Extensions.DependencyInjection.NATS/PackageReleaseNotes.txt:
- Line 2: Fix the spacing after the "Availability:" label in the release notes:
locate the line containing "Availability:  .NET 10 and .NET 9" and change the
double space after the colon to a single space so it reads "Availability: .NET
10 and .NET 9" to match other entries; ensure other "Availability:" lines remain
unchanged.

In
@.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/PackageReleaseNotes.txt:
- Around line 2-5: The release notes have inconsistent punctuation and spacing:
normalize the header and change-entry formatting by removing the extra space
after "Availability:" and adding a colon after the "CHANGED" tag; specifically
update the text lines containing "Availability:" to "Availability: .NET 10 and
.NET 9" (single space) and change "- CHANGED Dependencies have been upgraded..."
to "- CHANGED: Dependencies have been upgraded to the latest compatible versions
for all supported target frameworks (TFMs)" so the file follows the new colon
convention.

In @.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt:
- Around line 1-6: The "Availability:" line in the Version 5.0.1 block has two
spaces after the colon; locate the text block for Version: 5.0.1 and the line
that begins with "Availability:" and change the double space to a single space
so it matches other entries (e.g., the 5.0.0 block), ensuring the line reads
"Availability: .NET 10 and .NET 9".

In @.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt:
- Around line 1-3: Normalize the header spacing: change the "Availability:  .NET
10 and .NET 9" line to use a single space after the colon (i.e., "Availability:
.NET 10 and .NET 9") and replace the non‑breaking space on the blank line after
the version/header with a plain ASCII space/newline so the file uses consistent
single spaces and an ordinary blank line; update the lines containing "Version:
5.0.1" and "Availability:  .NET 10 and .NET 9" accordingly.

In @.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt:
- Around line 1-6: Fix the spacing inconsistency in the release notes by
changing the "Availability:" line so it uses a single space after the colon
(i.e., "Availability: .NET 10 and .NET 9") to match the other entries; edit the
text containing the "Availability:" token in the PackageReleaseNotes content to
remove the extra space.

In @.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt:
- Around line 1-3: Fix the accidental double space in the
PackageReleaseNotes.txt "Availability" entry by normalizing the whitespace after
the colon so it reads "Availability: .NET 10 and .NET 9" (single space). Locate
the "Availability" line in
.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt and replace the
double space after the colon with a single space to keep formatting/tooling
consistent.
♻️ Duplicate comments (1)
.nuget/Savvyio.Core/PackageReleaseNotes.txt (1)

2-2: Fix the double space after the colon in “Availability”.

There are two spaces after Availability: on Line 2. This is the same formatting issue previously flagged.

✏️ Proposed fix
-Availability:  .NET 10 and .NET 9
+Availability: .NET 10 and .NET 9
🧹 Nitpick comments (7)
.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt (1)

2-2: Fix formatting inconsistency: extra space after colon.

Line 2 contains a double space after "Availability:" while all other version blocks in this file use a single space.

✨ Proposed fix
-Availability:  .NET 10 and .NET 9
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt (1)

2-2: Fix formatting inconsistency: extra space after colon.

Line 2 contains a double space after "Availability:" while all other version blocks in this file use a single space.

✨ Proposed fix
-Availability:  .NET 10 and .NET 9
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt (1)

1-6: Fix spacing inconsistency on Line 2.

Line 2 has two spaces after "Availability:" while Line 8 (and presumably other entries) use a single space. Please align the formatting for consistency.

✨ Proposed fix
-Availability:  .NET 10 and .NET 9
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt (1)

1-6: LGTM! Release notes entry is well-formatted.

The new version 5.0.1 entry follows the established format and maintains proper reverse chronological ordering. The content aligns with the PR objectives for documenting dependency upgrades.

Optional: Consider adding more specific dependency details.

While the current generic note is consistent with other patch releases in this file, users would benefit from knowing which specific dependencies were upgraded (e.g., "Savvyio.Core 5.0.0 → 5.0.1, Dapper 2.x.x → 2.y.y"). This helps with troubleshooting and understanding the scope of changes.

.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt (1)

2-2: Use consistent single space after "Availability:" label.

Line 2 has two spaces after the colon, while all other "Availability:" entries in the file (lines 8, 16, 22, etc.) use a single space. This inconsistency could affect parsing tools.

🔧 Suggested fix
-Availability:  .NET 10 and .NET 9
+Availability: .NET 10 and .NET 9
.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt (1)

1-6: LGTM! Well-formatted release entry.

The version 5.0.1 entry follows the established format and correctly maintains reverse chronological order. The generic dependency upgrade note is appropriate for a patch release.

Consider adding more specific details about which dependencies were upgraded (e.g., major packages or version ranges) to provide better transparency for package consumers. However, this is optional for maintenance releases.

.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/PackageReleaseNotes.txt (1)

2-2: Minor spacing inconsistency after colon.

Line 2 has two spaces after Availability: while all other version entries (lines 8, 16, 22, 28, 34) use a single space.

✨ Suggested fix for consistency
-Availability:  .NET 10 and .NET 9
+Availability: .NET 10 and .NET 9

Comment on lines 1 to 3
Version: 5.0.1
Availability: .NET 10 and .NET 9

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Normalize Availability spacing and blank line character.
Line 2 has a double space after the colon, and Line 3 looks like a non‑standard blank line (NBSP). Consider normalizing to a single space and a standard empty line for consistency in release notes.

✏️ Proposed fix
-Version: 5.0.1
-Availability:  .NET 10 and .NET 9
- 
+Version: 5.0.1
+Availability: .NET 10 and .NET 9
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Version: 5.0.1
Availability: .NET 10 and .NET 9
 
Version: 5.0.1
Availability: .NET 10 and .NET 9
🤖 Prompt for AI Agents
In @.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt around lines 1
- 3, Normalize the spacing and blank line in the release notes: update the
"Availability:  .NET 10 and .NET 9" line to use a single space after the colon
(e.g., "Availability: .NET 10 and .NET 9") and replace the non-standard blank
line (NBSP) following it with a standard empty newline so the file uses normal
ASCII whitespace; edit the lines containing "Version: 5.0.1" and "Availability:"
to ensure consistent spacing and a regular blank line separator.

Comment on lines 2 to 5
Availability: .NET 10 and .NET 9

# ALM
- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align release-note formatting with the new colon convention.
Line 2 has a double space after Availability: and Line 5 omits the colon after CHANGED, which conflicts with the PR’s stated formatting update. Consider standardizing to Availability: .NET 10 and .NET 9 and - CHANGED: ....

📝 Suggested formatting
-Availability:  .NET 10 and .NET 9
+Availability: .NET 10 and .NET 9

-- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs)
+- CHANGED: Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs)
🤖 Prompt for AI Agents
In
@.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/PackageReleaseNotes.txt
around lines 2 - 5, The release notes have inconsistent punctuation and spacing:
normalize the header and change-entry formatting by removing the extra space
after "Availability:" and adding a colon after the "CHANGED" tag; specifically
update the text lines containing "Availability:" to "Availability: .NET 10 and
.NET 9" (single space) and change "- CHANGED Dependencies have been upgraded..."
to "- CHANGED: Dependencies have been upgraded to the latest compatible versions
for all supported target frameworks (TFMs)" so the file follows the new colon
convention.

@sonarqubecloud
Copy link

@gimlichael gimlichael merged commit 38af9f4 into main Jan 24, 2026
271 checks passed
@gimlichael gimlichael deleted the v5.0.1/service-update branch January 24, 2026 01:31
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.

2 participants